fix(bridge): 5 bug fixes for approval signal drop and Discord relay
- DEDUP: add conversation_id guard to prevent cross-session step_index collision - step_probe: suppress pending when projectName=default (empty window) - watchCommandsDir: add 3s polling fallback (fs.watch silent fail on Windows) - auto toggle: write chat_snapshot confirmation back to Discord - bot on_message: add message ID dedup for Gateway event replay
This commit is contained in:
@@ -223,6 +223,10 @@ function processCommandFile(filePath) {
|
||||
autoApproveEnabled = !autoApproveEnabled;
|
||||
}
|
||||
logToFile(`[AUTO] auto-approve toggled → ${autoApproveEnabled}`);
|
||||
// Confirm back to Discord
|
||||
const emoji = autoApproveEnabled ? '🟢' : '🔴';
|
||||
const mode = autoApproveEnabled ? '자동 승인 활성' : '수동 승인 모드';
|
||||
writeChatSnapshot(`${emoji} **Extension 확인**: ${mode} (project=${projectName})`);
|
||||
}
|
||||
else if (text) {
|
||||
// Send message to Antigravity — use VS Code command (most reliable)
|
||||
@@ -243,15 +247,18 @@ function processCommandFile(filePath) {
|
||||
function watchCommandsDir() {
|
||||
const cmdDir = path.join(bridgePath, 'commands');
|
||||
// Process existing files
|
||||
try {
|
||||
for (const f of fs.readdirSync(cmdDir)) {
|
||||
if (f.endsWith('.json')) {
|
||||
processCommandFile(path.join(cmdDir, f));
|
||||
const processAllCommands = () => {
|
||||
try {
|
||||
for (const f of fs.readdirSync(cmdDir)) {
|
||||
if (f.endsWith('.json')) {
|
||||
processCommandFile(path.join(cmdDir, f));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
// Watch for new files
|
||||
catch { }
|
||||
};
|
||||
processAllCommands();
|
||||
// Watch for new files (may not fire reliably on Windows)
|
||||
try {
|
||||
commandsWatcher = fs.watch(cmdDir, (event, filename) => {
|
||||
if (filename && filename.endsWith('.json') && event === 'rename') {
|
||||
@@ -263,6 +270,10 @@ function watchCommandsDir() {
|
||||
});
|
||||
}
|
||||
catch { }
|
||||
// Polling fallback: fs.watch on Windows can silently fail
|
||||
setInterval(() => {
|
||||
processAllCommands();
|
||||
}, 3000);
|
||||
}
|
||||
// ─── SDK Integration ───
|
||||
async function initSDK(context) {
|
||||
@@ -1992,8 +2003,12 @@ function setupMonitor() {
|
||||
lastPendingStepIndex = actualIndex;
|
||||
lastPendingTime = Date.now();
|
||||
sawRunningAfterPending = false;
|
||||
// Auto-approve: skip Discord, approve directly
|
||||
if (autoApproveEnabled) {
|
||||
// Skip pending for workspace-less AG windows (project=default)
|
||||
if (projectName === 'default') {
|
||||
logToFile(`[STEP-PROBE] skip pending: projectName=default (no workspace)`);
|
||||
}
|
||||
else if (autoApproveEnabled) {
|
||||
// Auto-approve: skip Discord, approve directly
|
||||
logToFile(`[AUTO] auto-approving step=${actualIndex} cmd='${command.substring(0, 60)}'`);
|
||||
tryApprovalStrategies(true, activeSessionId, ['view_file', 'list_dir', 'find_by_name', 'read_file', 'grep_search', 'replace_file_content', 'write_to_file', 'multi_replace_file_content'].includes(toolName) ? 'file_permission' : toolName, actualIndex);
|
||||
}
|
||||
@@ -2055,8 +2070,12 @@ function setupMonitor() {
|
||||
lastPendingStepIndex = si;
|
||||
lastPendingTime = Date.now();
|
||||
sawRunningAfterPending = false;
|
||||
// Auto-approve: skip Discord, approve directly
|
||||
if (autoApproveEnabled) {
|
||||
// Skip pending for workspace-less AG windows (project=default)
|
||||
if (projectName === 'default') {
|
||||
logToFile(`[STEP-PROBE] skip pending: projectName=default (no workspace)`);
|
||||
}
|
||||
else if (autoApproveEnabled) {
|
||||
// Auto-approve: skip Discord, approve directly
|
||||
logToFile(`[AUTO] auto-approving step=${si} cmd='${command.substring(0, 60)}'`);
|
||||
tryApprovalStrategies(true, activeSessionId, ['view_file', 'list_dir', 'find_by_name', 'read_file', 'grep_search', 'replace_file_content', 'write_to_file', 'multi_replace_file_content'].includes(toolName) ? 'file_permission' : toolName, si);
|
||||
}
|
||||
@@ -2718,8 +2737,9 @@ function writePendingApproval(data) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Dedup: skip if step_probe already created pending for same step_index (within window)
|
||||
// Dedup: skip if step_probe already created pending for same step_index IN SAME SESSION (within window)
|
||||
if (existing.status === 'pending' && existing.project_name === projectName
|
||||
&& existing.conversation_id === data.conversation_id // CRITICAL: same session only
|
||||
&& data.step_index !== undefined && existing.step_index === data.step_index) {
|
||||
const age = nowMs - (existing.timestamp * 1000);
|
||||
if (age < DEDUP_WINDOW_MS && age >= 0) {
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -188,6 +188,10 @@ function processCommandFile(filePath: string) {
|
||||
autoApproveEnabled = !autoApproveEnabled;
|
||||
}
|
||||
logToFile(`[AUTO] auto-approve toggled → ${autoApproveEnabled}`);
|
||||
// Confirm back to Discord
|
||||
const emoji = autoApproveEnabled ? '🟢' : '🔴';
|
||||
const mode = autoApproveEnabled ? '자동 승인 활성' : '수동 승인 모드';
|
||||
writeChatSnapshot(`${emoji} **Extension 확인**: ${mode} (project=${projectName})`);
|
||||
} else if (text) {
|
||||
// Send message to Antigravity — use VS Code command (most reliable)
|
||||
recentDiscordSentTexts.set(text.trim(), Date.now());
|
||||
@@ -207,15 +211,19 @@ function watchCommandsDir() {
|
||||
const cmdDir = path.join(bridgePath, 'commands');
|
||||
|
||||
// Process existing files
|
||||
try {
|
||||
for (const f of fs.readdirSync(cmdDir)) {
|
||||
if (f.endsWith('.json')) {
|
||||
processCommandFile(path.join(cmdDir, f));
|
||||
const processAllCommands = () => {
|
||||
try {
|
||||
for (const f of fs.readdirSync(cmdDir)) {
|
||||
if (f.endsWith('.json')) {
|
||||
processCommandFile(path.join(cmdDir, f));
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch { }
|
||||
} catch { }
|
||||
};
|
||||
|
||||
// Watch for new files
|
||||
processAllCommands();
|
||||
|
||||
// Watch for new files (may not fire reliably on Windows)
|
||||
try {
|
||||
commandsWatcher = fs.watch(cmdDir, (event, filename) => {
|
||||
if (filename && filename.endsWith('.json') && event === 'rename') {
|
||||
@@ -226,6 +234,11 @@ function watchCommandsDir() {
|
||||
}
|
||||
});
|
||||
} catch { }
|
||||
|
||||
// Polling fallback: fs.watch on Windows can silently fail
|
||||
setInterval(() => {
|
||||
processAllCommands();
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
// ─── SDK Integration ───
|
||||
@@ -1982,8 +1995,11 @@ function setupMonitor() {
|
||||
lastPendingStepIndex = actualIndex;
|
||||
lastPendingTime = Date.now();
|
||||
sawRunningAfterPending = false;
|
||||
// Auto-approve: skip Discord, approve directly
|
||||
if (autoApproveEnabled) {
|
||||
// Skip pending for workspace-less AG windows (project=default)
|
||||
if (projectName === 'default') {
|
||||
logToFile(`[STEP-PROBE] skip pending: projectName=default (no workspace)`);
|
||||
} else if (autoApproveEnabled) {
|
||||
// Auto-approve: skip Discord, approve directly
|
||||
logToFile(`[AUTO] auto-approving step=${actualIndex} cmd='${command.substring(0, 60)}'`);
|
||||
tryApprovalStrategies(true, activeSessionId, ['view_file', 'list_dir', 'find_by_name', 'read_file', 'grep_search', 'replace_file_content', 'write_to_file', 'multi_replace_file_content'].includes(toolName) ? 'file_permission' : toolName, actualIndex);
|
||||
} else {
|
||||
@@ -2043,8 +2059,11 @@ function setupMonitor() {
|
||||
lastPendingStepIndex = si;
|
||||
lastPendingTime = Date.now();
|
||||
sawRunningAfterPending = false;
|
||||
// Auto-approve: skip Discord, approve directly
|
||||
if (autoApproveEnabled) {
|
||||
// Skip pending for workspace-less AG windows (project=default)
|
||||
if (projectName === 'default') {
|
||||
logToFile(`[STEP-PROBE] skip pending: projectName=default (no workspace)`);
|
||||
} else if (autoApproveEnabled) {
|
||||
// Auto-approve: skip Discord, approve directly
|
||||
logToFile(`[AUTO] auto-approving step=${si} cmd='${command.substring(0, 60)}'`);
|
||||
tryApprovalStrategies(true, activeSessionId, ['view_file', 'list_dir', 'find_by_name', 'read_file', 'grep_search', 'replace_file_content', 'write_to_file', 'multi_replace_file_content'].includes(toolName) ? 'file_permission' : toolName, si);
|
||||
} else {
|
||||
@@ -2672,8 +2691,9 @@ function writePendingApproval(data: { conversation_id: string; command: string;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Dedup: skip if step_probe already created pending for same step_index (within window)
|
||||
// Dedup: skip if step_probe already created pending for same step_index IN SAME SESSION (within window)
|
||||
if (existing.status === 'pending' && existing.project_name === projectName
|
||||
&& existing.conversation_id === data.conversation_id // CRITICAL: same session only
|
||||
&& data.step_index !== undefined && existing.step_index === data.step_index) {
|
||||
const age = nowMs - (existing.timestamp * 1000);
|
||||
if (age < DEDUP_WINDOW_MS && age >= 0) {
|
||||
|
||||
Reference in New Issue
Block a user