fix(bridge): remove SDK EventMonitor to stop ERR_CONNECTION_REFUSED spam
EventMonitor was dual-polling GetCascadeTrajectorySteps every 2s via rawRPC, which has a 775-step hard limit and generates connection errors on port change. Changes: - Remove entire SDK EventMonitor (onStepCountChanged, onNewConversation, etc.) - Keep only GetAllCascadeTrajectories POLL at 5s interval - Remove all sdk.monitor.stop() calls - Unleash ERR_CONNECTION_REFUSED (127.0.0.1:1080) is Antigravity's own issue
This commit is contained in:
@@ -252,192 +252,11 @@ function setupMonitor() {
|
||||
if (!sdk) {
|
||||
return;
|
||||
}
|
||||
// Step count changed → fetch new steps via GetCascadeTrajectorySteps
|
||||
sdk.monitor.onStepCountChanged(async (e) => {
|
||||
console.log(`Gravity Bridge: [SDK] step changed: "${e.title}" step ${e.newCount} (+${e.delta})`);
|
||||
// Auto-register session with Bot on first step event
|
||||
writeRegistration(e.sessionId);
|
||||
// ── ONE-TIME FULL STEP TYPE DUMP ──
|
||||
if (!lastSeenStep.has(e.sessionId)) {
|
||||
try {
|
||||
const fullData = await sdk.ls.rawRPC('GetCascadeTrajectorySteps', {
|
||||
cascadeId: e.sessionId
|
||||
});
|
||||
if (fullData && Array.isArray(fullData.steps)) {
|
||||
const typeCounts = new Map();
|
||||
for (const step of fullData.steps) {
|
||||
const t = (step.type || '').replace('CORTEX_STEP_TYPE_', '');
|
||||
const s = (step.status || '').replace('CORTEX_STEP_STATUS_', '');
|
||||
const dataKeys = Object.keys(step).filter(k => !['type', 'status', 'metadata'].includes(k));
|
||||
if (!typeCounts.has(t)) {
|
||||
typeCounts.set(t, { count: 0, statuses: new Set(), keys: new Set(), sample: step });
|
||||
}
|
||||
const entry = typeCounts.get(t);
|
||||
entry.count++;
|
||||
entry.statuses.add(s);
|
||||
for (const k of dataKeys) {
|
||||
entry.keys.add(k);
|
||||
}
|
||||
}
|
||||
console.log(`Gravity Bridge: ══════════════════════════════════════`);
|
||||
console.log(`Gravity Bridge: FULL STEP TYPE MAP (${fullData.steps.length} total steps)`);
|
||||
console.log(`Gravity Bridge: ══════════════════════════════════════`);
|
||||
for (const [type, info] of typeCounts.entries()) {
|
||||
console.log(`Gravity Bridge: [TYPE] ${type} ×${info.count} statuses=[${[...info.statuses].join(',')}] keys=[${[...info.keys].join(',')}]`);
|
||||
// Dump ONE sample of each type
|
||||
const s = info.sample;
|
||||
const dataKeys = Object.keys(s).filter(k => !['type', 'status', 'metadata'].includes(k));
|
||||
for (const k of dataKeys) {
|
||||
const v = s[k];
|
||||
const vStr = typeof v === 'object' ? JSON.stringify(v).substring(0, 150) : String(v).substring(0, 150);
|
||||
console.log(`Gravity Bridge: .${k} (${typeof v}): ${vStr}`);
|
||||
}
|
||||
}
|
||||
console.log(`Gravity Bridge: ══════════════════════════════════════`);
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
console.log(`Gravity Bridge: full dump error: ${e.message}`);
|
||||
}
|
||||
}
|
||||
try {
|
||||
// IMPORTANT: Only fetch NEW steps, never re-fetch history
|
||||
const fromStep = Math.max(lastSeenStep.get(e.sessionId) ?? e.newCount - e.delta, e.newCount - e.delta);
|
||||
const stepsData = await sdk.ls.rawRPC('GetCascadeTrajectorySteps', {
|
||||
cascadeId: e.sessionId, startStepIndex: fromStep
|
||||
});
|
||||
lastSeenStep.set(e.sessionId, e.newCount);
|
||||
if (stepsData && Array.isArray(stepsData.steps)) {
|
||||
// API may ignore startStepIndex — only process the last e.delta steps
|
||||
const allSteps = stepsData.steps;
|
||||
const newSteps = allSteps.slice(-e.delta);
|
||||
console.log(`Gravity Bridge: [SDK] processing ${newSteps.length} of ${allSteps.length} steps`);
|
||||
let lastPlannerText = '';
|
||||
for (const step of newSteps) {
|
||||
const sType = step.type || '';
|
||||
const sStatus = step.status || '';
|
||||
const shortType = sType.replace('CORTEX_STEP_TYPE_', '');
|
||||
const shortStatus = sStatus.replace('CORTEX_STEP_STATUS_', '');
|
||||
// ── DIAGNOSTIC: log ALL step types (minimal) ──
|
||||
console.log(`Gravity Bridge: [STEP] ${shortType} ${shortStatus}`);
|
||||
// ══════════════════════════════════════════════
|
||||
// ANY WAITING step → Pending Approval to Discord
|
||||
// ══════════════════════════════════════════════
|
||||
if (sStatus.includes('WAITING')) {
|
||||
let description = '';
|
||||
let command = '';
|
||||
if (sType.includes('RUN_COMMAND')) {
|
||||
const rc = step.runCommand || {};
|
||||
command = rc.commandLine || rc.proposedCommandLine || '';
|
||||
description = `💻 **명령 실행 요청**\n\`\`\`\n${command}\n\`\`\`\ncwd: ${rc.cwd || ''}`;
|
||||
}
|
||||
else if (sType.includes('EDIT_FILE') || sType.includes('CODE_EDIT') || sType.includes('CODE_ACTION') || sType.includes('WRITE_FILE') || sType.includes('FILE_EDIT')) {
|
||||
// File edit/write/code action
|
||||
const edit = step.codeEdit || step.editFile || step.writeFile || step.codeAction || {};
|
||||
const filePath = edit.filePath || edit.targetFile || edit.path || '';
|
||||
const desc = edit.description || edit.instruction || '';
|
||||
command = `📝 파일 수정: ${filePath}`;
|
||||
description = `📝 **파일 변경 확인**\n파일: \`${filePath}\`\n${desc ? `설명: ${desc}` : ''}`;
|
||||
// Full dump for diagnostic
|
||||
console.log(`Gravity Bridge: [STEP-DETAIL] ${shortType} WAITING keys=${JSON.stringify(Object.keys(step).filter(k => !['type', 'status', 'metadata'].includes(k)))}`);
|
||||
for (const k of Object.keys(step).filter(k => !['type', 'status', 'metadata'].includes(k))) {
|
||||
const v = step[k];
|
||||
console.log(`Gravity Bridge: [STEP-DETAIL] .${k} = ${typeof v === 'object' ? JSON.stringify(v).substring(0, 200) : String(v).substring(0, 200)}`);
|
||||
}
|
||||
}
|
||||
else if (sType.includes('FILE_ACCESS') || sType.includes('READ_FILE') || sType.includes('FILE_READ')) {
|
||||
// File access permission
|
||||
const fa = step.fileAccess || step.readFile || step.fileRead || {};
|
||||
const filePath = fa.filePath || fa.path || '';
|
||||
command = `📖 파일 접근: ${filePath}`;
|
||||
description = `📖 **파일 접근 권한 요청**\n파일: \`${filePath}\``;
|
||||
console.log(`Gravity Bridge: [STEP-DETAIL] ${shortType} WAITING keys=${JSON.stringify(Object.keys(step).filter(k => !['type', 'status', 'metadata'].includes(k)))}`);
|
||||
for (const k of Object.keys(step).filter(k => !['type', 'status', 'metadata'].includes(k))) {
|
||||
const v = step[k];
|
||||
console.log(`Gravity Bridge: [STEP-DETAIL] .${k} = ${typeof v === 'object' ? JSON.stringify(v).substring(0, 200) : String(v).substring(0, 200)}`);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Unknown WAITING step — still relay it with full diagnostic
|
||||
const stepKeys = Object.keys(step).filter(k => !['type', 'status', 'metadata'].includes(k));
|
||||
command = `⏳ ${shortType}`;
|
||||
description = `⏳ **대기 중: ${shortType}**\nkeys: ${stepKeys.join(', ')}`;
|
||||
console.log(`Gravity Bridge: [STEP-DETAIL] UNKNOWN WAITING: ${shortType} keys=${JSON.stringify(stepKeys)}`);
|
||||
for (const k of stepKeys) {
|
||||
const v = step[k];
|
||||
console.log(`Gravity Bridge: [STEP-DETAIL] .${k} = ${typeof v === 'object' ? JSON.stringify(v).substring(0, 200) : String(v).substring(0, 200)}`);
|
||||
}
|
||||
}
|
||||
writePendingApproval({
|
||||
conversation_id: e.sessionId,
|
||||
command: command,
|
||||
description: `${description}\n\n🏷️ ${e.title}`,
|
||||
});
|
||||
console.log(`Gravity Bridge: [SDK] ⏳ pending ${shortType}: "${command.substring(0, 80)}"`);
|
||||
continue;
|
||||
}
|
||||
// ══════════════════════════════════════════════
|
||||
// PLANNER_RESPONSE → AI text relay (COMPLETED/DONE)
|
||||
// ══════════════════════════════════════════════
|
||||
if (sType.includes('PLANNER_RESPONSE')) {
|
||||
if (!sStatus.includes('COMPLETED') && !sStatus.includes('DONE')) {
|
||||
continue;
|
||||
}
|
||||
const pr = step.plannerResponse;
|
||||
const responseText = pr?.modifiedResponse || pr?.response || '';
|
||||
if (responseText && typeof responseText === 'string' && responseText.length > 0) {
|
||||
lastPlannerText = responseText;
|
||||
console.log(`Gravity Bridge: [SDK] 📝 planner response found (${responseText.length} chars)`);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// ══════════════════════════════════════════════
|
||||
// NOTIFY_USER → also relay as chat snapshot
|
||||
// ══════════════════════════════════════════════
|
||||
if (sType.includes('NOTIFY_USER') && (sStatus.includes('COMPLETED') || sStatus.includes('DONE'))) {
|
||||
const nu = step.notifyUser;
|
||||
const content = nu?.notificationContent || '';
|
||||
if (content && content.length > 0) {
|
||||
// Write NOTIFY_USER as snapshot too
|
||||
writeChatSnapshot(`📣 **알림**\n\n${content}`);
|
||||
console.log(`Gravity Bridge: [SDK] 📣 NOTIFY_USER relayed (${content.length} chars)`);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// Write the LAST planner response as snapshot (with dedup)
|
||||
if (lastPlannerText && lastPlannerText !== lastSnapshotText.get(e.sessionId)) {
|
||||
lastSnapshotText.set(e.sessionId, lastPlannerText);
|
||||
writeChatSnapshot(`🤖 **${e.title}**\n\n${lastPlannerText}`);
|
||||
console.log(`Gravity Bridge: [SDK] 💬 snapshot written (${lastPlannerText.length} chars)`);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
console.log(`Gravity Bridge: [SDK] steps error: ${err.message}`);
|
||||
}
|
||||
// Fallback
|
||||
lastSeenStep.set(e.sessionId, e.newCount);
|
||||
});
|
||||
// New conversation started
|
||||
sdk.monitor.onNewConversation((e) => {
|
||||
console.log(`Gravity Bridge: [SDK] new conversation: ${e.title}`);
|
||||
writeRegistration(e.sessionId || e.id || '');
|
||||
writeChatSnapshot(`🚀 **${e.title}** — 새 대화 시작`);
|
||||
});
|
||||
// Active session changed
|
||||
sdk.monitor.onActiveSessionChanged((e) => {
|
||||
console.log(`Gravity Bridge: [SDK] active session: "${e.title}" (${e.sessionId?.substring(0, 8)})`);
|
||||
writeRegistration(e.sessionId || e.id || '');
|
||||
});
|
||||
// State changed (USS update)
|
||||
sdk.monitor.onStateChanged((e) => {
|
||||
console.log(`Gravity Bridge: [SDK] state changed: ${e.key}`);
|
||||
});
|
||||
// Start monitoring (USS every 3s, trajectory every 2s for faster detection)
|
||||
sdk.monitor.start(3000, 2000);
|
||||
console.log('Gravity Bridge: [SDK] monitor started (USS 3s, trajectory 2s)');
|
||||
// NOTE: SDK EventMonitor DISABLED to prevent ERR_CONNECTION_REFUSED spam.
|
||||
// Root cause: EventMonitor polls GetCascadeTrajectorySteps every 2s via rawRPC,
|
||||
// which has a 775-step hard limit and generates connection errors.
|
||||
// ALL relay is now handled by the GetAllCascadeTrajectories POLL below.
|
||||
console.log('Gravity Bridge: SDK monitor DISABLED (using GetAllCascadeTrajectories POLL instead)');
|
||||
// ══════════════════════════════════════════════════════════════════════
|
||||
// PRIMARY RELAY: GetAllCascadeTrajectories (THE CORRECT API!)
|
||||
//
|
||||
@@ -577,7 +396,7 @@ function setupMonitor() {
|
||||
console.log(`Gravity Bridge: [POLL#${pollCount}] error: ${e.message}`);
|
||||
}
|
||||
}
|
||||
}, 3000);
|
||||
}, 5000);
|
||||
}
|
||||
// ─── Response Watcher (Discord approval → Antigravity RPC) ───
|
||||
let responseWatcher = null;
|
||||
@@ -776,9 +595,9 @@ async function activate(context) {
|
||||
// Initialize SDK
|
||||
const sdkReady = await initSDK(context);
|
||||
if (sdkReady) {
|
||||
setupMonitor();
|
||||
statusBar.text = '$(check) Bridge SDK';
|
||||
statusBar.tooltip = `Gravity Bridge: ${projectName} (SDK active)`;
|
||||
setupMonitor(); // Now just logs that monitor is disabled
|
||||
statusBar.text = '$(check) Bridge';
|
||||
statusBar.tooltip = `Gravity Bridge: ${projectName} (POLL active)`;
|
||||
// Register SDK-powered commands
|
||||
context.subscriptions.push(vscode.commands.registerCommand('gravityBridge.approve', async () => {
|
||||
try {
|
||||
@@ -813,9 +632,7 @@ async function activate(context) {
|
||||
vscode.window.showInformationMessage(`Gravity Bridge started for "${projectName}"`);
|
||||
}), vscode.commands.registerCommand('gravityBridge.stop', () => {
|
||||
isActive = false;
|
||||
if (sdk) {
|
||||
sdk.monitor.stop();
|
||||
}
|
||||
// SDK monitor is disabled, no need to stop
|
||||
statusBar.text = '$(circle-slash) Bridge OFF';
|
||||
vscode.window.showInformationMessage('Gravity Bridge stopped');
|
||||
}), vscode.commands.registerCommand('gravityBridge.connect', async () => {
|
||||
@@ -846,8 +663,10 @@ async function activate(context) {
|
||||
context.subscriptions.push({
|
||||
dispose: () => {
|
||||
if (sdk) {
|
||||
sdk.monitor.stop();
|
||||
sdk.dispose();
|
||||
try {
|
||||
sdk.dispose();
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
if (watcher) {
|
||||
watcher.close();
|
||||
@@ -863,7 +682,6 @@ async function activate(context) {
|
||||
function deactivate() {
|
||||
if (sdk) {
|
||||
try {
|
||||
sdk.monitor.stop();
|
||||
sdk.dispose();
|
||||
}
|
||||
catch { }
|
||||
|
||||
Reference in New Issue
Block a user