From 559b1e02a710cef8fe9b2ccd2d4902b576729f38 Mon Sep 17 00:00:00 2001 From: catlog22 Date: Sun, 21 Dec 2025 10:02:36 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=20CLI=20=E9=80=9A?= =?UTF-8?q?=E7=9F=A5=E7=9A=84=E8=B6=85=E6=97=B6=E8=AE=BE=E7=BD=AE=EF=BC=8C?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=89=A7=E8=A1=8C=E5=B7=A5=E5=85=B7=E7=9A=84?= =?UTF-8?q?=E4=BC=9A=E8=AF=9D=E8=B7=9F=E8=B8=AA=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ccw/src/commands/cli.ts | 5 ++++ ccw/src/tools/cli-executor.ts | 43 +++++++++++++++++------------------ 2 files changed, 26 insertions(+), 22 deletions(-) diff --git a/ccw/src/commands/cli.ts b/ccw/src/commands/cli.ts index 1de7e568..01769b5f 100644 --- a/ccw/src/commands/cli.ts +++ b/ccw/src/commands/cli.ts @@ -43,6 +43,7 @@ function notifyDashboard(data: Record): void { port: Number(DASHBOARD_PORT), path: '/api/hook', method: 'POST', + timeout: 2000, // 2 second timeout to prevent hanging headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(payload) @@ -53,6 +54,10 @@ function notifyDashboard(data: Record): void { req.on('error', (err) => { if (process.env.DEBUG) console.error('[Dashboard] CLI notification failed:', err.message); }); + req.on('timeout', () => { + req.destroy(); + if (process.env.DEBUG) console.error('[Dashboard] CLI notification timed out'); + }); req.write(payload); req.end(); } diff --git a/ccw/src/tools/cli-executor.ts b/ccw/src/tools/cli-executor.ts index ef052a90..7b986c92 100644 --- a/ccw/src/tools/cli-executor.ts +++ b/ccw/src/tools/cli-executor.ts @@ -796,7 +796,7 @@ async function executeCliTool( }); // Handle completion - child.on('close', (code) => { + child.on('close', async (code) => { const endTime = Date.now(); const duration = endTime - startTime; @@ -942,29 +942,28 @@ async function executeCliTool( } } - // Track native session after execution (async, non-blocking) + // Track native session after execution (awaited to prevent process hang) // Pass prompt for precise matching in parallel execution scenarios - trackNewSession(tool, new Date(startTime), workingDir, prompt) - .then((nativeSession) => { - if (nativeSession) { - // Save native session mapping - try { - store.saveNativeSessionMapping({ - ccw_id: conversationId, - tool, - native_session_id: nativeSession.sessionId, - native_session_path: nativeSession.filePath, - project_hash: nativeSession.projectHash, - created_at: new Date().toISOString() - }); - } catch (err) { - console.error('[CLI Executor] Failed to save native session mapping:', (err as Error).message); - } + try { + const nativeSession = await trackNewSession(tool, new Date(startTime), workingDir, prompt); + if (nativeSession) { + // Save native session mapping + try { + store.saveNativeSessionMapping({ + ccw_id: conversationId, + tool, + native_session_id: nativeSession.sessionId, + native_session_path: nativeSession.filePath, + project_hash: nativeSession.projectHash, + created_at: new Date().toISOString() + }); + } catch (err) { + console.error('[CLI Executor] Failed to save native session mapping:', (err as Error).message); } - }) - .catch((err) => { - console.error('[CLI Executor] Failed to track native session:', (err as Error).message); - }); + } + } catch (err) { + console.error('[CLI Executor] Failed to track native session:', (err as Error).message); + } // Create legacy execution record for backward compatibility const execution: ExecutionRecord = {