feat(bot,bridge): P1 !auto 토글 자동승인 + P2 BridgeTransport 추상화 #task-304 #task-305

P1: !auto 토글 (bot.py + extension.ts)
- auto_approve_projects set으로 프로젝트별 상태 관리
- !auto → on/off 토글, pending 자동 승인 + 🤖 자동 승인됨 embed
- Extension step_probe에서 autoApproveEnabled 시 직접 tryApprovalStrategies

P2: BridgeTransport 추상화 (bridge.py)
- BridgeTransport ABC + LocalTransport (기존 동작 100% 호환)
- RemoteTransport 스켈레톤 (multi-PC 대비)
- config.py BOT_MODE/REMOTE_BRIDGE_URL, main.py transport 주입

docs: usage-guide.md + tech-stack.md Python 경로 기록
This commit is contained in:
Variet Worker
2026-03-11 19:25:40 +09:00
parent 1696a2976b
commit c1303999cf
8 changed files with 434 additions and 106 deletions

View File

@@ -42,6 +42,7 @@ let bridgePath: string;
let projectName: string;
let workspaceUri: string = ''; // filesystem path of the workspace folder (for session filtering)
let isActive = false;
let autoApproveEnabled = false; // toggled via !auto from Discord
let deterministicPort = 0; // derived from projectName, consistent across restarts
let watcher: fs.FSWatcher | null = null;
let commandsWatcher: fs.FSWatcher | null = null;
@@ -155,10 +156,17 @@ function processCommandFile(filePath: string) {
vscode.commands.executeCommand('antigravity.agent.rejectAgentStep')
.then(() => console.log('Gravity Bridge: ✅ stop sent'),
() => { });
} else if (text.startsWith('!auto ')) {
} else if (text.startsWith('!auto')) {
// Auto-approve mode toggle
const mode = text.includes('on') ? 'true' : 'false';
console.log(`Gravity Bridge: auto-approve${mode}`);
if (text === '!auto on') {
autoApproveEnabled = true;
} else if (text === '!auto off') {
autoApproveEnabled = false;
} else {
// Toggle if no explicit on/off
autoApproveEnabled = !autoApproveEnabled;
}
logToFile(`[AUTO] auto-approve toggled → ${autoApproveEnabled}`);
} else if (text) {
// Send message to Antigravity — use VS Code command (most reliable)
recentDiscordSentTexts.set(text.trim(), Date.now());
@@ -1891,14 +1899,20 @@ function setupMonitor() {
lastPendingStepIndex = actualIndex;
lastPendingTime = Date.now();
sawRunningAfterPending = false;
writePendingApproval({
conversation_id: activeSessionId,
command,
description: `Step #${actualIndex} (${(oStep.type || '').replace('CORTEX_STEP_TYPE_', '')})`,
step_type: ['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,
step_index: actualIndex,
source: 'step_probe_offset',
});
// Auto-approve: skip Discord, approve directly
if (autoApproveEnabled) {
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 {
writePendingApproval({
conversation_id: activeSessionId,
command,
description: `Step #${actualIndex} (${(oStep.type || '').replace('CORTEX_STEP_TYPE_', '')})`,
step_type: ['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,
step_index: actualIndex,
source: 'step_probe_offset',
});
}
}
break;
}
@@ -1946,14 +1960,20 @@ function setupMonitor() {
lastPendingStepIndex = si;
lastPendingTime = Date.now();
sawRunningAfterPending = false;
writePendingApproval({
conversation_id: activeSessionId,
command,
description,
step_type: ['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,
step_index: si,
source: 'step_probe',
});
// Auto-approve: skip Discord, approve directly
if (autoApproveEnabled) {
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 {
writePendingApproval({
conversation_id: activeSessionId,
command,
description,
step_type: ['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,
step_index: si,
source: 'step_probe',
});
}
}
break;
}