aws-runtime-bridge 1.9.150 → 1.9.153
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +122 -0
- package/dist/adapter/AcodeSdkAdapter.d.ts +27 -0
- package/dist/adapter/AcodeSdkAdapter.js +5 -5
- package/dist/adapter/types.d.ts +16 -0
- package/dist/desktop/built-in-desktop-tools.js +1 -1
- package/dist/index.js +1 -1
- package/dist/routes/lsp.d.ts +6 -0
- package/dist/routes/lsp.js +4 -0
- package/dist/routes/ltr.js +1 -1
- package/dist/routes/sessions.d.ts +87 -0
- package/dist/routes/sessions.js +1 -1
- package/dist/routes/terminal.js +20 -20
- package/dist/services/instance-features.d.ts +11 -1
- package/dist/services/instance-features.js +1 -1
- package/dist/services/lsp-stdio-bridge.d.ts +48 -0
- package/dist/services/lsp-stdio-bridge.js +6 -0
- package/dist/utils/file-utils.d.ts +2 -0
- package/dist/utils/file-utils.js +2 -2
- package/package/acode/dist/capability-prompt.d.ts +16 -0
- package/package/acode/dist/capability-prompt.js +3 -0
- package/package/acode/dist/runtime.d.ts +6 -0
- package/package/acode/dist/runtime.js +23 -22
- package/package/acode/dist/types.d.ts +3 -0
- package/package/aws-client-agent-mcp/dist/agent-client.d.ts +28 -4
- package/package/aws-client-agent-mcp/dist/agent-client.js +1 -1
- package/package/aws-client-agent-mcp/dist/http-client.d.ts +1 -1
- package/package/aws-client-agent-mcp/dist/http-client.js +1 -1
- package/package/aws-client-agent-mcp/dist/mcp-server.d.ts +24 -17
- package/package/aws-client-agent-mcp/dist/mcp-server.js +28 -28
- package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts +20 -0
- package/package/aws-client-agent-mcp/dist/mcp-tools.js +25 -8
- package/package/aws-client-agent-mcp/dist/tool-groups.d.ts +57 -0
- package/package/aws-client-agent-mcp/dist/tool-groups.js +3 -0
- package/package/aws-client-agent-mcp/dist/types.d.ts +23 -0
- package/package.json +3 -1
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{existsSync as T,readFileSync as D}from"node:fs";import M from"node:os";import S from"node:path";import{pathToFileURL as E}from"node:url";import x from"cors";import P from"express";import{adapterRegistry as F}from"./adapter/index.js";import{attachBrowserWebSocketServer as G}from"./browser/browser-ws-bridge.js";import{getAcodeDataHome as O,getActiveBridgeHttpPort as y,getAutoRegisterConfigFilePath as L,getBridgeDataHome as _,getBridgeRuntimePropertiesFilePath as j,getBridgeTemplateConfigFile as K,reserveBridgeListenPort as N,validateProductionToken as W,writeBridgeRuntimePropertiesFile as H}from"./config.js";import{attachRemoteDesktopWebSocketServer as U}from"./remote-desktop/index.js";import{acodeTodosRouter as z}from"./routes/acode-todos.js";import{aiSourcesRouter as J}from"./routes/ai-sources.js";import{backgroundTasksRouter as Y}from"./routes/background-tasks.js";import{browserListenersRouter as Z}from"./routes/browser-listeners.js";import{browserSessionsRouter as q}from"./routes/browser-sessions.js";import{capabilitiesRouter as Q}from"./routes/capabilities.js";import{computerRouter as V}from"./routes/computer.js";import{dashboardRouter as X}from"./routes/dashboard.js";import{eventsRouter as ee}from"./routes/events.js";import{fileBrowserRouter as re}from"./routes/file-browser.js";import{fileChangeDiffRouter as te}from"./routes/file-change-diff.js";import{fileDiffRollbackRouter as ie}from"./routes/file-diff-rollback.js";import{fileSnapshotRouter as oe}from"./routes/file-snapshot.js";import{gitRouter as ne}from"./routes/git.js";import{instanceRouter as se,setGracefulShutdownFn as ae}from"./routes/instance.js";import{jdksRouter as me}from"./routes/jdks.js";import{launchRouter as ue}from"./routes/launch.js";import{ltrRouter as ce}from"./routes/ltr.js";import{mcpExtraRouter as de}from"./routes/mcp-extra.js";import{mcpRouter as ge}from"./routes/mcp.js";import{pluginsRouter as pe}from"./routes/plugins.js";import{processesRouter as fe}from"./routes/processes.js";import{propertiesRouter as le}from"./routes/properties.js";import{attachPtyWebSocketServer as be,closeAllPtySessions as he,ptyRouter as we,ptySessions as Re}from"./routes/pty.js";import{runtimeBindingRouter as Se,logRuntimeBindingStartupState as Pe}from"./routes/runtime-binding.js";import{sessionsRouter as ye}from"./routes/sessions.js";import{skillsRouter as Ie}from"./routes/skills.js";import{subAgentsRouter as $e}from"./routes/sub-agents.js";import{systemMetricsRouter as ke}from"./routes/system-metrics.js";import{taskContextRouter as Ae}from"./routes/task-context.js";import{terminalRouter as Ce,sdkSessions as w}from"./routes/terminal.js";import{ymlRouter as ve}from"./routes/yml.js";import{accessControlMiddleware as Be}from"./services/access-control.js";import{ensureAcodePackageReleased as Te,getReleasedAcodeEntryPath as De}from"./services/acode-package.js";import{getAgentProcessManager as I}from"./services/agent-process-manager.js";import{autoRegister as Me,unregister as Ee,bridgeRestartCleanup as xe,cancelBackgroundRegisterRetries as Fe}from"./services/auto-register.js";import{ensureAwsClientAgentMcpReleased as Ge}from"./services/aws-client-agent-mcp.js";import{disposeBrowserSessionManager as Oe}from"./services/browser-session-manager.js";import{handleCliCommand as Le}from"./services/cli-commands.js";import{disposeDesktopMcpManager as _e}from"./services/desktop-mcp-manager.js";import{getLaunchManager as je}from"./services/launch-manager.js";import{migrateOldPathsOnStartup as Ke}from"./services/legacy-path-migration.js";import{deliverPendingBridgeLifecycleNotifications as Ne}from"./services/lifecycle-state.js";import{startOrphanMonitor as We,stopOrphanMonitor as He}from"./services/orphan-monitor.js";import{pluginManager as Ue}from"./services/plugin-manager.js";import{detectOrphanProcesses as ze}from"./services/process-detector.js";import{buildGracefulShutdownPlan as Je,shouldCleanupPersistedSessionsOnStartup as Ye}from"./services/runtime-lifecycle-policy.js";import{ensureStartupConfig as Ze}from"./services/startup-config-wizard.js";import{subAgentStore as qe}from"./services/sub-agent-manager-instance.js";import{loadPersistedSessions as $,savePersistedSessions as k}from"./services/terminal-persistence.js";import{stopTunnelClient as Qe}from"./services/tunnel-client.js";import{logger as e}from"./utils/logger.js";const A=await Le();A.handled&&process.exit(A.exitCode),await Ze(),W(),Ge(),Te(),Ke(),Pe(),await N(),H(),e.info(`[runtime-bridge] \u5DF2\u5199\u5165\u8FD0\u884C\u65F6\u914D\u7F6E ${j()}\uFF08port=${y()}\uFF09`),e.info(`[runtime-bridge] ACode \u6570\u636E\u76EE\u5F55(\u7528\u6237): ${O()}`),e.info(`[runtime-bridge] Bridge \u6570\u636E\u76EE\u5F55: ${_()}`),e.info(`[runtime-bridge] \u6A21\u677F\u914D\u7F6E: ${K()}`);async function Ve(){try{if(await Me())e.info("[runtime-bridge] \u81EA\u52A8\u6CE8\u518C\u6210\u529F");else{const{loadConfig:o}=await import("./services/auto-register.js"),n=o();!!n.userKey&&n.enabled?e.warn("[runtime-bridge] \u81EA\u52A8\u6CE8\u518C\u6682\u65F6\u5931\u8D25\uFF0C\u5C06\u5728\u540E\u53F0\u6301\u7EED\u91CD\u8BD5\u76F4\u5230\u4E0E\u8C03\u5EA6\u4E2D\u5FC3\u5EFA\u7ACB\u8FDE\u63A5"):(e.info("[runtime-bridge] \u81EA\u52A8\u6CE8\u518C\u672A\u914D\u7F6E\uFF0C\u7EE7\u7EED\u542F\u52A8\u670D\u52A1"),e.info(`[runtime-bridge] \u8981\u542F\u7528\u81EA\u52A8\u6CE8\u518C\uFF0C\u8BF7\u521B\u5EFA\u914D\u7F6E\u6587\u4EF6 ${L()}`))}}catch(r){const o=r;e.warn("[runtime-bridge] \u81EA\u52A8\u6CE8\u518C\u51FA\u9519:",o.message)}}Ve().then(()=>Xe()).then(()=>Ne()).then(()=>{e.info("[runtime-bridge] Bridge \u751F\u547D\u5468\u671F\u901A\u77E5\u540C\u6B65\u5B8C\u6210")}).catch(r=>{e.warn("[runtime-bridge] \u81EA\u52A8\u6CE8\u518C\u6216\u6E05\u7406\u51FA\u9519:",r)}),import("./services/update-notifier.js").then(({startUpdateNotifier:r})=>r()).catch(r=>{e.warn("[runtime-bridge] \u7248\u672C\u68C0\u67E5\u670D\u52A1\u542F\u52A8\u5931\u8D25:",r.message)});async function Xe(){try{if(process.env.AWS_BRIDGE_RESTART_CLEANUP!=="true"){e.info("[runtime-bridge] \u8DF3\u8FC7 Bridge \u91CD\u542F\u6E05\u7406\uFF0C\u4FDD\u7559 Agent \u72B6\u6001\u4F9B\u8C03\u5EA6\u4E2D\u5FC3\u6062\u590D");return}const{getRegistrationState:r}=await import("./services/auto-register.js"),o=r();if(!o.registered||!o.instanceId){e.info("[runtime-bridge] \u5B9E\u4F8B\u672A\u6CE8\u518C\uFF0C\u8DF3\u8FC7 Bridge \u91CD\u542F\u6E05\u7406");return}e.info("[runtime-bridge] \u2605 Bridge \u91CD\u542F\u6E05\u7406\u5DF2\u663E\u5F0F\u542F\u7528\uFF0C\u6B63\u5728\u901A\u77E5\u8C03\u5EA6\u4E2D\u5FC3\u6E05\u7406 Agent \u72B6\u6001...");const n=await xe();n.success?e.info(`[runtime-bridge] \u2605 Bridge \u91CD\u542F\u6E05\u7406\u6210\u529F\uFF0C\u6E05\u7406\u4E86 ${n.agentCount||0} \u4E2A Agent`):e.warn(`[runtime-bridge] \u2605 Bridge \u91CD\u542F\u6E05\u7406\u5931\u8D25: ${n.error}`)}catch(r){const o=r;e.warn("[runtime-bridge] Bridge \u91CD\u542F\u6E05\u7406\u51FA\u9519:",o.message)}}async function er(){try{const r=await $();if(r.length===0){e.info("[runtime-bridge] \u65E0\u6301\u4E45\u5316\u4F1A\u8BDD\uFF0C\u8DF3\u8FC7\u8FDB\u7A0B\u6CE8\u518C\u8868\u91CD\u5EFA");return}await I().rebuildRegistry(r.map(n=>({agentId:n.agentId,sessionId:n.sessionId,pid:n.pid,workspacePath:n.workspacePath,command:n.command,mode:"sdk"}))),e.info(`[runtime-bridge] \u8FDB\u7A0B\u6CE8\u518C\u8868\u91CD\u5EFA\u5B8C\u6210: ${r.length} \u6761\u8BB0\u5F55`)}catch(r){const o=r;e.warn("[runtime-bridge] \u8FDB\u7A0B\u6CE8\u518C\u8868\u91CD\u5EFA\u5931\u8D25:",o.message)}}er().catch(r=>{e.warn("[runtime-bridge] \u8FDB\u7A0B\u6CE8\u518C\u8868\u91CD\u5EFA\u5931\u8D25:",r)}),import(E(S.join(De(),"..","background-command-manager.js")).href).then(async r=>{const o=r.backgroundCommandManager;if(!o||typeof o.reconcileAllAgents!="function"){e.warn("[runtime-bridge] \u540E\u53F0\u547D\u4EE4\u7BA1\u7406\u5668\u4E0D\u53EF\u7528\uFF0C\u8DF3\u8FC7\u542F\u52A8\u5B64\u513F\u5BF9\u8D26");return}const n=await o.reconcileAllAgents();n>0&&e.info(`[runtime-bridge] \u2605 \u542F\u52A8\u5B64\u513F\u5BF9\u8D26\u5B8C\u6210\uFF1A\u4FEE\u590D ${n} \u6761\u540E\u53F0\u547D\u4EE4\u72B6\u6001`)}).catch(r=>{e.warn("[runtime-bridge] \u542F\u52A8\u5B64\u513F\u5BF9\u8D26\u5931\u8D25:",r.message)});async function rr(){try{const r=await import("node:fs/promises"),o=await import("node:path"),n=await import("node:os"),f=o.join(n.tmpdir(),"agentswork-runtime-bridge",".preserve-sessions");let u=!1;try{const t=await r.readFile(f,"utf-8");u=JSON.parse(t).preserveSessions===!0,await r.unlink(f),e.info(`[runtime-bridge] \u2605 \u68C0\u6D4B\u5230\u4FDD\u7559\u4F1A\u8BDD\u6807\u8BB0\uFF0CpreserveSessions=${u}`)}catch{}const a=await $();if(a.length===0){e.info("[runtime-bridge] \u542F\u52A8\u65F6\u65E0\u6301\u4E45\u5316\u4F1A\u8BDD\uFF0C\u65E0\u9700\u68C0\u6D4B\u5B64\u513F\u8FDB\u7A0B");return}if(!Ye(u)){e.info(`[runtime-bridge] \u2605 \u4FDD\u7559 ${a.length} \u4E2A\u6301\u4E45\u5316\u4F1A\u8BDD\u5E76\u91CD\u5EFA\u8FDB\u7A0B\u6CE8\u518C\u8868`),await I().rebuildRegistry(a.map(s=>({agentId:s.agentId,sessionId:s.sessionId,pid:s.pid,workspacePath:s.workspacePath,command:s.command,mode:"sdk"})));return}e.info(`[runtime-bridge] \u2605 \u5DF2\u663E\u5F0F\u542F\u7528\u542F\u52A8\u6E05\u7406\uFF0C\u68C0\u6D4B ${a.length} \u4E2A\u6301\u4E45\u5316\u4F1A\u8BDD\u7684\u5B64\u513F\u8FDB\u7A0B...`);const d=await ze(a.map(t=>({agentId:t.agentId,pid:t.pid,workspacePath:t.workspacePath,command:t.command})));if(d.length>0){e.warn(`[runtime-bridge] \u2605 \u68C0\u6D4B\u5230 ${d.length} \u4E2A\u5B64\u513F\u8FDB\u7A0B\u4ECD\u5728\u8FD0\u884C\uFF1A`);for(const t of d)e.warn(` - agentId=${t.agentId}, pid=${t.process.pid}, command=${t.process.command?.slice(0,50)}`);e.info("[runtime-bridge] \u6B63\u5728\u81EA\u52A8\u6E05\u7406\u6240\u6709\u5B64\u513F\u8FDB\u7A0B...");for(const t of d)try{if(t.process.pid)if(process.platform==="win32"){const{execSync:s}=await import("node:child_process");s(`taskkill /PID ${t.process.pid} /T /F`,{encoding:"utf8",timeout:3e3}),e.info(`[runtime-bridge] \u5DF2\u81EA\u52A8\u7EC8\u6B62\u5B64\u513F\u8FDB\u7A0B: agentId=${t.agentId}, PID=${t.process.pid}`)}else process.kill(t.process.pid,"SIGKILL"),e.info(`[runtime-bridge] \u5DF2\u81EA\u52A8\u7EC8\u6B62\u5B64\u513F\u8FDB\u7A0B: agentId=${t.agentId}, PID=${t.process.pid}`)}catch(s){const c=s;e.warn(`[runtime-bridge] \u81EA\u52A8\u7EC8\u6B62\u5B64\u513F\u8FDB\u7A0B\u5931\u8D25: agentId=${t.agentId}, PID=${t.process.pid}, error=${c.message}`)}await new Promise(t=>setTimeout(t,1e3))}await k([]),e.info(`[runtime-bridge] \u2605 \u542F\u52A8\u6E05\u7406\u5B8C\u6210\uFF0C\u5DF2\u6E05\u7A7A\u6240\u6709\u6301\u4E45\u5316\u4F1A\u8BDD\uFF08\u6E05\u7406\u4E86 ${d.length} \u4E2A\u5B64\u513F\u8FDB\u7A0B\uFF09`)}catch(r){const o=r;e.warn("[runtime-bridge] \u542F\u52A8\u65F6\u5B64\u513F\u8FDB\u7A0B\u68C0\u6D4B\u5931\u8D25:",o.message)}}rr().catch(r=>{e.warn("[runtime-bridge] \u5B64\u513F\u8FDB\u7A0B\u68C0\u6D4B\u51FA\u9519:",r)}),We().catch(r=>{e.warn("[runtime-bridge] \u542F\u52A8\u5B64\u513F\u8FDB\u7A0B\u76D1\u63A7\u5931\u8D25:",r)});const i=P();i.use(Be),i.use(x()),i.use(P.json({limit:"1mb"})),i.use("/runtime",Se),i.use("/runtime",le),i.use("/runtime",ve),i.use("/runtime",se),i.use("/runtime",Ie),i.use("/runtime",ge),i.use("/runtime",Q),i.use("/runtime",Ce),i.use("/runtime",ye),i.use("/runtime",fe),i.use("/runtime",ue),i.use("/runtime",me),i.use("/runtime",ke),i.use("/runtime",ee),i.use("/runtime",ne),i.use("/runtime",oe),i.use("/runtime",z),i.use("/runtime",Y),i.use("/runtime",$e),i.use("/runtime",q),i.use("/runtime",Z),i.use("/runtime",pe),i.use("/runtime",de),i.use("/runtime",J),i.use("/runtime",Ae),i.use("/runtime",ie),i.use("/runtime",te),i.use("/runtime/computer",V),i.use("/pty",we),i.use("/",X),i.use("/api/file-browser",re),i.use("/api/ltr",ce);function tr(){const r=y(),o=i.listen(r,()=>{e.info(`[runtime-bridge] listening on ${r}`)});return be(o),U(o),G(o),o.on("error",n=>{if(n.code==="EADDRINUSE"){e.error(`[runtime-bridge] port ${r} became unavailable after reservation (another process grabbed it concurrently). Set AWS_RUNTIME_BRIDGE_PORT to a free port and restart.`),process.exitCode=1;return}e.error("[runtime-bridge] failed to start server:",n),process.exitCode=1}),o}let C=!1;async function b(r,o,n=!1){if(C){e.info(`[runtime-bridge] \u5DF2\u5728\u5173\u95ED\u4E2D\uFF0C\u5FFD\u7565 ${r}`);return}C=!0,n||R()&&(n=!0,e.info("[runtime-bridge] \u2605 \u68C0\u6D4B\u5230 .preserve-sessions \u6807\u8BB0\u6587\u4EF6\uFF0C\u81EA\u52A8\u5347\u7EA7\u4E3A\u4FDD\u7559\u4F1A\u8BDD\u6A21\u5F0F")),e.info(`[runtime-bridge] \u6536\u5230 ${r} \u4FE1\u53F7\uFF0C\u5F00\u59CB\u4F18\u96C5\u5173\u95ED... (preserveSessions=${n})`);const f=Date.now(),u=Je(n);try{const a=w.size;if(u.terminateSdkSessions){e.info(`[runtime-bridge] \u6B63\u5728\u505C\u6B62 ${a} \u4E2A SDK \u4F1A\u8BDD...`);for(const[t,s]of w.entries())try{const c=s.providerId||"claude-code",g=F.get(c);let p="";try{const m=g.getSessionPid?.(t);m&&(p=` (PID: ${m})`)}catch{}await g.terminateSession(t),e.info(`[runtime-bridge] SDK \u4F1A\u8BDD ${t} \u5DF2\u7EC8\u6B62${p}`),w.delete(t)}catch(c){const g=c;e.error(`[runtime-bridge] SDK \u4F1A\u8BDD ${t} \u7EC8\u6B62\u5931\u8D25:`,g.message),w.delete(t)}}else e.info(`[runtime-bridge] \u2605 \u4FDD\u7559 ${a} \u4E2A SDK \u4F1A\u8BDD\uFF0C\u4E0D\u5728\u91CD\u542F\u6062\u590D\u573A\u666F\u4E2D\u7EC8\u6B62 Agent \u8FDB\u7A0B`);const l=Re.size;u.closePtySessions?(e.info(`[runtime-bridge] \u6B63\u5728\u505C\u6B62 ${l} \u4E2A PTY \u4F1A\u8BDD...`),he("shutdown")):e.info(`[runtime-bridge] \u2605 \u4FDD\u7559 ${l} \u4E2A PTY \u4F1A\u8BDD\uFF0C\u4E0D\u5728\u91CD\u542F\u6062\u590D\u573A\u666F\u4E2D\u5173\u95ED\u7EC8\u7AEF\u8FDB\u7A0B`);try{const{running:t,stopped:s}=await je().stopAll();t>0&&e.info(`[runtime-bridge] \u542F\u52A8\u9879\u8FDB\u7A0B\u5DF2\u505C\u6B62: running=${t}, stopped=${s}`)}catch(t){e.warn("[runtime-bridge] \u505C\u6B62\u542F\u52A8\u9879\u8FDB\u7A0B\u5931\u8D25:",t.message)}e.info("[runtime-bridge] \u6B63\u5728\u505C\u6B62\u5B64\u513F\u8FDB\u7A0B\u76D1\u63A7...");try{const c=(await import("file://"+S.join(__dirname,"..","package","acode","dist","background-command-manager.js")).catch(()=>({backgroundCommandManager:null}))).backgroundCommandManager;c&&(e.info("[runtime-bridge] \u6B63\u5728\u6E05\u7406\u540E\u53F0\u547D\u4EE4..."),await c.disposeAll())}catch(t){e.warn("[runtime-bridge] \u540E\u53F0\u547D\u4EE4\u6E05\u7406\u5931\u8D25: %s",t?.message)}if(He(),u.terminateResidualProcesses&&(e.info("[runtime-bridge] \u7B49\u5F85\u8FDB\u7A0B\u5B8C\u5168\u7EC8\u6B62..."),await new Promise(t=>setTimeout(t,1e3))),u.terminateResidualProcesses)try{const{detectOrphanProcesses:t,terminateProcessTree:s}=await import("./services/process-detector.js"),{loadPersistedSessions:c}=await import("./services/terminal-persistence.js"),g=await c();if(g.length>0){const p=await t(g.map(m=>({agentId:m.agentId,pid:m.pid,workspacePath:m.workspacePath,command:m.command})));if(p.length>0){e.warn(`[runtime-bridge] \u68C0\u6D4B\u5230 ${p.length} \u4E2A\u6B8B\u7559\u8FDB\u7A0B\uFF0C\u6B63\u5728\u5F3A\u5236\u7EC8\u6B62...`);for(const m of p)if(m.process.pid){const B=await s(m.process.pid);e.info(`[runtime-bridge] \u5DF2\u5F3A\u5236\u7EC8\u6B62\u6B8B\u7559\u8FDB\u7A0B\u6811\uFF1AagentId=${m.agentId}, PID=${m.process.pid}, \u7EC8\u6B62\u4E86 ${B.terminated} \u4E2A\u8FDB\u7A0B`)}}}}catch(t){const s=t;e.warn("[runtime-bridge] \u6B8B\u7559\u8FDB\u7A0B\u68C0\u67E5\u5931\u8D25:",s.message)}else e.info("[runtime-bridge] \u2605 \u4FDD\u7559\u6A21\u5F0F\u8DF3\u8FC7\u6B8B\u7559\u8FDB\u7A0B\u5F3A\u5236\u7EC8\u6B62\uFF0C\u7B49\u5F85\u8C03\u5EA6\u4E2D\u5FC3\u6062\u590D\u4F1A\u8BDD");if(u.unregisterInstance){e.info("[runtime-bridge] \u6B63\u5728\u6CE8\u9500\u5B9E\u4F8B...");try{await Ee()}catch(t){const s=t;e.error("[runtime-bridge] \u6CE8\u9500\u5B9E\u4F8B\u5931\u8D25:",s.message)}}else e.info("[runtime-bridge] \u2605 \u4FDD\u7559\u6A21\u5F0F\u8DF3\u8FC7\u5B9E\u4F8B\u6CE8\u9500\uFF0C\u907F\u514D\u8C03\u5EA6\u4E2D\u5FC3\u5C06 Agent \u6807\u8BB0\u4E3A stopped");if(Fe(),u.stopTunnelClient&&(e.info("[runtime-bridge] \u6B63\u5728\u5173\u95ED\u96A7\u9053\u5BA2\u6237\u7AEF..."),Qe()),u.clearPersistedSessions){e.info("[runtime-bridge] \u6B63\u5728\u6E05\u7A7A\u6301\u4E45\u5316\u4F1A\u8BDD\u72B6\u6001...");try{await k([])}catch(t){const s=t;e.error("[runtime-bridge] \u6E05\u7A7A\u6301\u4E45\u5316\u72B6\u6001\u5931\u8D25:",s.message)}}else e.info("[runtime-bridge] \u2605 \u4FDD\u7559\u6301\u4E45\u5316\u4F1A\u8BDD\u72B6\u6001\uFF08aws-mcp-server \u91CD\u542F\u6062\u590D\u573A\u666F\uFF09");try{await Oe(),e.info("[runtime-bridge] browser \u5DE5\u5177\u6808\u5DF2\u6E05\u7406")}catch(t){e.warn("[runtime-bridge] browser \u5DE5\u5177\u6808\u6E05\u7406\u5931\u8D25:",t.message)}try{await _e(),e.info("[runtime-bridge] desktop \u5DE5\u5177\u6808\u5DF2\u6E05\u7406")}catch(t){e.warn("[runtime-bridge] desktop \u5DE5\u5177\u6808\u6E05\u7406\u5931\u8D25:",t.message)}try{await Ue.stopAll(),e.info("[runtime-bridge] \u63D2\u4EF6\u76D1\u542C\u8FDB\u7A0B\u5DF2\u6E05\u7406")}catch(t){e.warn("[runtime-bridge] \u63D2\u4EF6\u76D1\u542C\u8FDB\u7A0B\u6E05\u7406\u5931\u8D25:",t.message)}const d=Date.now()-f;e.info(`[runtime-bridge] \u4F18\u96C5\u5173\u95ED\u5B8C\u6210 (\u8017\u65F6 ${d}ms)\uFF0C\u505C\u6B62 ${a} SDK \u4F1A\u8BDD`),o.close(()=>{e.info("[runtime-bridge] HTTP \u670D\u52A1\u5668\u5DF2\u5173\u95ED"),process.exit(process.exitCode||0)}),setTimeout(()=>{e.warn("[runtime-bridge] \u4F18\u96C5\u5173\u95ED\u8D85\u65F6\uFF0C\u5F3A\u5236\u9000\u51FA"),process.exit(1)},15e3)}catch(a){const l=a;e.error("[runtime-bridge] \u4F18\u96C5\u5173\u95ED\u8FC7\u7A0B\u4E2D\u53D1\u751F\u9519\u8BEF:",l),process.exit(1)}}qe.reconcileZombies().then(r=>{r>0&&e.info(`[runtime-bridge] \u5DF2\u6E05\u7406 ${r} \u4E2A\u50F5\u5C38 sub-agent \u8BB0\u5F55`)}).catch(r=>{e.warn("[runtime-bridge] \u6E05\u7406\u50F5\u5C38 sub-agent \u8BB0\u5F55\u5931\u8D25:",r.message)});const h=tr(),v=S.join(M.tmpdir(),"agentswork-runtime-bridge",".preserve-sessions");function R(){try{if(T(v)){const r=D(v,"utf-8");return JSON.parse(r).preserveSessions===!0}}catch{}return!1}ae(async(r,o)=>{await b(r,h,o)}),process.on("SIGTERM",()=>{const r=R();b("SIGTERM",h,r)}),process.on("SIGINT",()=>{const r=R();b("SIGINT",h,r)}),process.platform==="win32"&&process.on("SIGBREAK",()=>{const r=R();b("SIGBREAK",h,r)}),process.on("uncaughtException",r=>{e.error("[runtime-bridge] \u672A\u6355\u83B7\u5F02\u5E38:",r),b("uncaughtException",h)}),process.on("unhandledRejection",r=>{e.error("[runtime-bridge] \u672A\u5904\u7406\u7684 Promise \u62D2\u7EDD:",r)});
|
|
2
|
+
import{existsSync as T,readFileSync as D}from"node:fs";import M from"node:os";import S from"node:path";import{pathToFileURL as E}from"node:url";import x from"cors";import P from"express";import{adapterRegistry as F}from"./adapter/index.js";import{attachBrowserWebSocketServer as G}from"./browser/browser-ws-bridge.js";import{getAcodeDataHome as O,getActiveBridgeHttpPort as y,getAutoRegisterConfigFilePath as L,getBridgeDataHome as _,getBridgeRuntimePropertiesFilePath as j,getBridgeTemplateConfigFile as K,reserveBridgeListenPort as N,validateProductionToken as W,writeBridgeRuntimePropertiesFile as H}from"./config.js";import{attachRemoteDesktopWebSocketServer as U}from"./remote-desktop/index.js";import{acodeTodosRouter as z}from"./routes/acode-todos.js";import{aiSourcesRouter as J}from"./routes/ai-sources.js";import{backgroundTasksRouter as Y}from"./routes/background-tasks.js";import{browserListenersRouter as Z}from"./routes/browser-listeners.js";import{browserSessionsRouter as q}from"./routes/browser-sessions.js";import{capabilitiesRouter as Q}from"./routes/capabilities.js";import{computerRouter as V}from"./routes/computer.js";import{dashboardRouter as X}from"./routes/dashboard.js";import{eventsRouter as ee}from"./routes/events.js";import{fileBrowserRouter as re}from"./routes/file-browser.js";import{fileChangeDiffRouter as te}from"./routes/file-change-diff.js";import{fileDiffRollbackRouter as ie}from"./routes/file-diff-rollback.js";import{fileSnapshotRouter as oe}from"./routes/file-snapshot.js";import{gitRouter as ne}from"./routes/git.js";import{instanceRouter as se,setGracefulShutdownFn as ae}from"./routes/instance.js";import{jdksRouter as me}from"./routes/jdks.js";import{launchRouter as ue}from"./routes/launch.js";import{attachLspWebSocketServer as ce}from"./routes/lsp.js";import{ltrRouter as de}from"./routes/ltr.js";import{mcpExtraRouter as ge}from"./routes/mcp-extra.js";import{mcpRouter as pe}from"./routes/mcp.js";import{pluginsRouter as fe}from"./routes/plugins.js";import{processesRouter as le}from"./routes/processes.js";import{propertiesRouter as be}from"./routes/properties.js";import{attachPtyWebSocketServer as he,closeAllPtySessions as we,ptyRouter as Re,ptySessions as Se}from"./routes/pty.js";import{runtimeBindingRouter as Pe,logRuntimeBindingStartupState as ye}from"./routes/runtime-binding.js";import{sessionsRouter as Ie}from"./routes/sessions.js";import{skillsRouter as $e}from"./routes/skills.js";import{subAgentsRouter as ke}from"./routes/sub-agents.js";import{systemMetricsRouter as Ae}from"./routes/system-metrics.js";import{taskContextRouter as Ce}from"./routes/task-context.js";import{terminalRouter as ve,sdkSessions as w}from"./routes/terminal.js";import{ymlRouter as Be}from"./routes/yml.js";import{accessControlMiddleware as Te}from"./services/access-control.js";import{ensureAcodePackageReleased as De,getReleasedAcodeEntryPath as Me}from"./services/acode-package.js";import{getAgentProcessManager as I}from"./services/agent-process-manager.js";import{autoRegister as Ee,unregister as xe,bridgeRestartCleanup as Fe,cancelBackgroundRegisterRetries as Ge}from"./services/auto-register.js";import{ensureAwsClientAgentMcpReleased as Oe}from"./services/aws-client-agent-mcp.js";import{disposeBrowserSessionManager as Le}from"./services/browser-session-manager.js";import{handleCliCommand as _e}from"./services/cli-commands.js";import{disposeDesktopMcpManager as je}from"./services/desktop-mcp-manager.js";import{getLaunchManager as Ke}from"./services/launch-manager.js";import{migrateOldPathsOnStartup as Ne}from"./services/legacy-path-migration.js";import{deliverPendingBridgeLifecycleNotifications as We}from"./services/lifecycle-state.js";import{startOrphanMonitor as He,stopOrphanMonitor as Ue}from"./services/orphan-monitor.js";import{pluginManager as ze}from"./services/plugin-manager.js";import{detectOrphanProcesses as Je}from"./services/process-detector.js";import{buildGracefulShutdownPlan as Ye,shouldCleanupPersistedSessionsOnStartup as Ze}from"./services/runtime-lifecycle-policy.js";import{ensureStartupConfig as qe}from"./services/startup-config-wizard.js";import{subAgentStore as Qe}from"./services/sub-agent-manager-instance.js";import{loadPersistedSessions as $,savePersistedSessions as k}from"./services/terminal-persistence.js";import{stopTunnelClient as Ve}from"./services/tunnel-client.js";import{logger as e}from"./utils/logger.js";const A=await _e();A.handled&&process.exit(A.exitCode),await qe(),W(),Oe(),De(),Ne(),ye(),await N(),H(),e.info(`[runtime-bridge] \u5DF2\u5199\u5165\u8FD0\u884C\u65F6\u914D\u7F6E ${j()}\uFF08port=${y()}\uFF09`),e.info(`[runtime-bridge] ACode \u6570\u636E\u76EE\u5F55(\u7528\u6237): ${O()}`),e.info(`[runtime-bridge] Bridge \u6570\u636E\u76EE\u5F55: ${_()}`),e.info(`[runtime-bridge] \u6A21\u677F\u914D\u7F6E: ${K()}`);async function Xe(){try{if(await Ee())e.info("[runtime-bridge] \u81EA\u52A8\u6CE8\u518C\u6210\u529F");else{const{loadConfig:o}=await import("./services/auto-register.js"),n=o();!!n.userKey&&n.enabled?e.warn("[runtime-bridge] \u81EA\u52A8\u6CE8\u518C\u6682\u65F6\u5931\u8D25\uFF0C\u5C06\u5728\u540E\u53F0\u6301\u7EED\u91CD\u8BD5\u76F4\u5230\u4E0E\u8C03\u5EA6\u4E2D\u5FC3\u5EFA\u7ACB\u8FDE\u63A5"):(e.info("[runtime-bridge] \u81EA\u52A8\u6CE8\u518C\u672A\u914D\u7F6E\uFF0C\u7EE7\u7EED\u542F\u52A8\u670D\u52A1"),e.info(`[runtime-bridge] \u8981\u542F\u7528\u81EA\u52A8\u6CE8\u518C\uFF0C\u8BF7\u521B\u5EFA\u914D\u7F6E\u6587\u4EF6 ${L()}`))}}catch(r){const o=r;e.warn("[runtime-bridge] \u81EA\u52A8\u6CE8\u518C\u51FA\u9519:",o.message)}}Xe().then(()=>er()).then(()=>We()).then(()=>{e.info("[runtime-bridge] Bridge \u751F\u547D\u5468\u671F\u901A\u77E5\u540C\u6B65\u5B8C\u6210")}).catch(r=>{e.warn("[runtime-bridge] \u81EA\u52A8\u6CE8\u518C\u6216\u6E05\u7406\u51FA\u9519:",r)}),import("./services/update-notifier.js").then(({startUpdateNotifier:r})=>r()).catch(r=>{e.warn("[runtime-bridge] \u7248\u672C\u68C0\u67E5\u670D\u52A1\u542F\u52A8\u5931\u8D25:",r.message)});async function er(){try{if(process.env.AWS_BRIDGE_RESTART_CLEANUP!=="true"){e.info("[runtime-bridge] \u8DF3\u8FC7 Bridge \u91CD\u542F\u6E05\u7406\uFF0C\u4FDD\u7559 Agent \u72B6\u6001\u4F9B\u8C03\u5EA6\u4E2D\u5FC3\u6062\u590D");return}const{getRegistrationState:r}=await import("./services/auto-register.js"),o=r();if(!o.registered||!o.instanceId){e.info("[runtime-bridge] \u5B9E\u4F8B\u672A\u6CE8\u518C\uFF0C\u8DF3\u8FC7 Bridge \u91CD\u542F\u6E05\u7406");return}e.info("[runtime-bridge] \u2605 Bridge \u91CD\u542F\u6E05\u7406\u5DF2\u663E\u5F0F\u542F\u7528\uFF0C\u6B63\u5728\u901A\u77E5\u8C03\u5EA6\u4E2D\u5FC3\u6E05\u7406 Agent \u72B6\u6001...");const n=await Fe();n.success?e.info(`[runtime-bridge] \u2605 Bridge \u91CD\u542F\u6E05\u7406\u6210\u529F\uFF0C\u6E05\u7406\u4E86 ${n.agentCount||0} \u4E2A Agent`):e.warn(`[runtime-bridge] \u2605 Bridge \u91CD\u542F\u6E05\u7406\u5931\u8D25: ${n.error}`)}catch(r){const o=r;e.warn("[runtime-bridge] Bridge \u91CD\u542F\u6E05\u7406\u51FA\u9519:",o.message)}}async function rr(){try{const r=await $();if(r.length===0){e.info("[runtime-bridge] \u65E0\u6301\u4E45\u5316\u4F1A\u8BDD\uFF0C\u8DF3\u8FC7\u8FDB\u7A0B\u6CE8\u518C\u8868\u91CD\u5EFA");return}await I().rebuildRegistry(r.map(n=>({agentId:n.agentId,sessionId:n.sessionId,pid:n.pid,workspacePath:n.workspacePath,command:n.command,mode:"sdk"}))),e.info(`[runtime-bridge] \u8FDB\u7A0B\u6CE8\u518C\u8868\u91CD\u5EFA\u5B8C\u6210: ${r.length} \u6761\u8BB0\u5F55`)}catch(r){const o=r;e.warn("[runtime-bridge] \u8FDB\u7A0B\u6CE8\u518C\u8868\u91CD\u5EFA\u5931\u8D25:",o.message)}}rr().catch(r=>{e.warn("[runtime-bridge] \u8FDB\u7A0B\u6CE8\u518C\u8868\u91CD\u5EFA\u5931\u8D25:",r)}),import(E(S.join(Me(),"..","background-command-manager.js")).href).then(async r=>{const o=r.backgroundCommandManager;if(!o||typeof o.reconcileAllAgents!="function"){e.warn("[runtime-bridge] \u540E\u53F0\u547D\u4EE4\u7BA1\u7406\u5668\u4E0D\u53EF\u7528\uFF0C\u8DF3\u8FC7\u542F\u52A8\u5B64\u513F\u5BF9\u8D26");return}const n=await o.reconcileAllAgents();n>0&&e.info(`[runtime-bridge] \u2605 \u542F\u52A8\u5B64\u513F\u5BF9\u8D26\u5B8C\u6210\uFF1A\u4FEE\u590D ${n} \u6761\u540E\u53F0\u547D\u4EE4\u72B6\u6001`)}).catch(r=>{e.warn("[runtime-bridge] \u542F\u52A8\u5B64\u513F\u5BF9\u8D26\u5931\u8D25:",r.message)});async function tr(){try{const r=await import("node:fs/promises"),o=await import("node:path"),n=await import("node:os"),f=o.join(n.tmpdir(),"agentswork-runtime-bridge",".preserve-sessions");let u=!1;try{const t=await r.readFile(f,"utf-8");u=JSON.parse(t).preserveSessions===!0,await r.unlink(f),e.info(`[runtime-bridge] \u2605 \u68C0\u6D4B\u5230\u4FDD\u7559\u4F1A\u8BDD\u6807\u8BB0\uFF0CpreserveSessions=${u}`)}catch{}const a=await $();if(a.length===0){e.info("[runtime-bridge] \u542F\u52A8\u65F6\u65E0\u6301\u4E45\u5316\u4F1A\u8BDD\uFF0C\u65E0\u9700\u68C0\u6D4B\u5B64\u513F\u8FDB\u7A0B");return}if(!Ze(u)){e.info(`[runtime-bridge] \u2605 \u4FDD\u7559 ${a.length} \u4E2A\u6301\u4E45\u5316\u4F1A\u8BDD\u5E76\u91CD\u5EFA\u8FDB\u7A0B\u6CE8\u518C\u8868`),await I().rebuildRegistry(a.map(s=>({agentId:s.agentId,sessionId:s.sessionId,pid:s.pid,workspacePath:s.workspacePath,command:s.command,mode:"sdk"})));return}e.info(`[runtime-bridge] \u2605 \u5DF2\u663E\u5F0F\u542F\u7528\u542F\u52A8\u6E05\u7406\uFF0C\u68C0\u6D4B ${a.length} \u4E2A\u6301\u4E45\u5316\u4F1A\u8BDD\u7684\u5B64\u513F\u8FDB\u7A0B...`);const d=await Je(a.map(t=>({agentId:t.agentId,pid:t.pid,workspacePath:t.workspacePath,command:t.command})));if(d.length>0){e.warn(`[runtime-bridge] \u2605 \u68C0\u6D4B\u5230 ${d.length} \u4E2A\u5B64\u513F\u8FDB\u7A0B\u4ECD\u5728\u8FD0\u884C\uFF1A`);for(const t of d)e.warn(` - agentId=${t.agentId}, pid=${t.process.pid}, command=${t.process.command?.slice(0,50)}`);e.info("[runtime-bridge] \u6B63\u5728\u81EA\u52A8\u6E05\u7406\u6240\u6709\u5B64\u513F\u8FDB\u7A0B...");for(const t of d)try{if(t.process.pid)if(process.platform==="win32"){const{execSync:s}=await import("node:child_process");s(`taskkill /PID ${t.process.pid} /T /F`,{encoding:"utf8",timeout:3e3}),e.info(`[runtime-bridge] \u5DF2\u81EA\u52A8\u7EC8\u6B62\u5B64\u513F\u8FDB\u7A0B: agentId=${t.agentId}, PID=${t.process.pid}`)}else process.kill(t.process.pid,"SIGKILL"),e.info(`[runtime-bridge] \u5DF2\u81EA\u52A8\u7EC8\u6B62\u5B64\u513F\u8FDB\u7A0B: agentId=${t.agentId}, PID=${t.process.pid}`)}catch(s){const c=s;e.warn(`[runtime-bridge] \u81EA\u52A8\u7EC8\u6B62\u5B64\u513F\u8FDB\u7A0B\u5931\u8D25: agentId=${t.agentId}, PID=${t.process.pid}, error=${c.message}`)}await new Promise(t=>setTimeout(t,1e3))}await k([]),e.info(`[runtime-bridge] \u2605 \u542F\u52A8\u6E05\u7406\u5B8C\u6210\uFF0C\u5DF2\u6E05\u7A7A\u6240\u6709\u6301\u4E45\u5316\u4F1A\u8BDD\uFF08\u6E05\u7406\u4E86 ${d.length} \u4E2A\u5B64\u513F\u8FDB\u7A0B\uFF09`)}catch(r){const o=r;e.warn("[runtime-bridge] \u542F\u52A8\u65F6\u5B64\u513F\u8FDB\u7A0B\u68C0\u6D4B\u5931\u8D25:",o.message)}}tr().catch(r=>{e.warn("[runtime-bridge] \u5B64\u513F\u8FDB\u7A0B\u68C0\u6D4B\u51FA\u9519:",r)}),He().catch(r=>{e.warn("[runtime-bridge] \u542F\u52A8\u5B64\u513F\u8FDB\u7A0B\u76D1\u63A7\u5931\u8D25:",r)});const i=P();i.use(Te),i.use(x()),i.use(P.json({limit:"1mb"})),i.use("/runtime",Pe),i.use("/runtime",be),i.use("/runtime",Be),i.use("/runtime",se),i.use("/runtime",$e),i.use("/runtime",pe),i.use("/runtime",Q),i.use("/runtime",ve),i.use("/runtime",Ie),i.use("/runtime",le),i.use("/runtime",ue),i.use("/runtime",me),i.use("/runtime",Ae),i.use("/runtime",ee),i.use("/runtime",ne),i.use("/runtime",oe),i.use("/runtime",z),i.use("/runtime",Y),i.use("/runtime",ke),i.use("/runtime",q),i.use("/runtime",Z),i.use("/runtime",fe),i.use("/runtime",ge),i.use("/runtime",J),i.use("/runtime",Ce),i.use("/runtime",ie),i.use("/runtime",te),i.use("/runtime/computer",V),i.use("/pty",Re),i.use("/",X),i.use("/api/file-browser",re),i.use("/api/ltr",de);function ir(){const r=y(),o=i.listen(r,()=>{e.info(`[runtime-bridge] listening on ${r}`)});return he(o),U(o),G(o),ce(o),o.on("error",n=>{if(n.code==="EADDRINUSE"){e.error(`[runtime-bridge] port ${r} became unavailable after reservation (another process grabbed it concurrently). Set AWS_RUNTIME_BRIDGE_PORT to a free port and restart.`),process.exitCode=1;return}e.error("[runtime-bridge] failed to start server:",n),process.exitCode=1}),o}let C=!1;async function b(r,o,n=!1){if(C){e.info(`[runtime-bridge] \u5DF2\u5728\u5173\u95ED\u4E2D\uFF0C\u5FFD\u7565 ${r}`);return}C=!0,n||R()&&(n=!0,e.info("[runtime-bridge] \u2605 \u68C0\u6D4B\u5230 .preserve-sessions \u6807\u8BB0\u6587\u4EF6\uFF0C\u81EA\u52A8\u5347\u7EA7\u4E3A\u4FDD\u7559\u4F1A\u8BDD\u6A21\u5F0F")),e.info(`[runtime-bridge] \u6536\u5230 ${r} \u4FE1\u53F7\uFF0C\u5F00\u59CB\u4F18\u96C5\u5173\u95ED... (preserveSessions=${n})`);const f=Date.now(),u=Ye(n);try{const a=w.size;if(u.terminateSdkSessions){e.info(`[runtime-bridge] \u6B63\u5728\u505C\u6B62 ${a} \u4E2A SDK \u4F1A\u8BDD...`);for(const[t,s]of w.entries())try{const c=s.providerId||"claude-code",g=F.get(c);let p="";try{const m=g.getSessionPid?.(t);m&&(p=` (PID: ${m})`)}catch{}await g.terminateSession(t),e.info(`[runtime-bridge] SDK \u4F1A\u8BDD ${t} \u5DF2\u7EC8\u6B62${p}`),w.delete(t)}catch(c){const g=c;e.error(`[runtime-bridge] SDK \u4F1A\u8BDD ${t} \u7EC8\u6B62\u5931\u8D25:`,g.message),w.delete(t)}}else e.info(`[runtime-bridge] \u2605 \u4FDD\u7559 ${a} \u4E2A SDK \u4F1A\u8BDD\uFF0C\u4E0D\u5728\u91CD\u542F\u6062\u590D\u573A\u666F\u4E2D\u7EC8\u6B62 Agent \u8FDB\u7A0B`);const l=Se.size;u.closePtySessions?(e.info(`[runtime-bridge] \u6B63\u5728\u505C\u6B62 ${l} \u4E2A PTY \u4F1A\u8BDD...`),we("shutdown")):e.info(`[runtime-bridge] \u2605 \u4FDD\u7559 ${l} \u4E2A PTY \u4F1A\u8BDD\uFF0C\u4E0D\u5728\u91CD\u542F\u6062\u590D\u573A\u666F\u4E2D\u5173\u95ED\u7EC8\u7AEF\u8FDB\u7A0B`);try{const{running:t,stopped:s}=await Ke().stopAll();t>0&&e.info(`[runtime-bridge] \u542F\u52A8\u9879\u8FDB\u7A0B\u5DF2\u505C\u6B62: running=${t}, stopped=${s}`)}catch(t){e.warn("[runtime-bridge] \u505C\u6B62\u542F\u52A8\u9879\u8FDB\u7A0B\u5931\u8D25:",t.message)}e.info("[runtime-bridge] \u6B63\u5728\u505C\u6B62\u5B64\u513F\u8FDB\u7A0B\u76D1\u63A7...");try{const c=(await import("file://"+S.join(__dirname,"..","package","acode","dist","background-command-manager.js")).catch(()=>({backgroundCommandManager:null}))).backgroundCommandManager;c&&(e.info("[runtime-bridge] \u6B63\u5728\u6E05\u7406\u540E\u53F0\u547D\u4EE4..."),await c.disposeAll())}catch(t){e.warn("[runtime-bridge] \u540E\u53F0\u547D\u4EE4\u6E05\u7406\u5931\u8D25: %s",t?.message)}if(Ue(),u.terminateResidualProcesses&&(e.info("[runtime-bridge] \u7B49\u5F85\u8FDB\u7A0B\u5B8C\u5168\u7EC8\u6B62..."),await new Promise(t=>setTimeout(t,1e3))),u.terminateResidualProcesses)try{const{detectOrphanProcesses:t,terminateProcessTree:s}=await import("./services/process-detector.js"),{loadPersistedSessions:c}=await import("./services/terminal-persistence.js"),g=await c();if(g.length>0){const p=await t(g.map(m=>({agentId:m.agentId,pid:m.pid,workspacePath:m.workspacePath,command:m.command})));if(p.length>0){e.warn(`[runtime-bridge] \u68C0\u6D4B\u5230 ${p.length} \u4E2A\u6B8B\u7559\u8FDB\u7A0B\uFF0C\u6B63\u5728\u5F3A\u5236\u7EC8\u6B62...`);for(const m of p)if(m.process.pid){const B=await s(m.process.pid);e.info(`[runtime-bridge] \u5DF2\u5F3A\u5236\u7EC8\u6B62\u6B8B\u7559\u8FDB\u7A0B\u6811\uFF1AagentId=${m.agentId}, PID=${m.process.pid}, \u7EC8\u6B62\u4E86 ${B.terminated} \u4E2A\u8FDB\u7A0B`)}}}}catch(t){const s=t;e.warn("[runtime-bridge] \u6B8B\u7559\u8FDB\u7A0B\u68C0\u67E5\u5931\u8D25:",s.message)}else e.info("[runtime-bridge] \u2605 \u4FDD\u7559\u6A21\u5F0F\u8DF3\u8FC7\u6B8B\u7559\u8FDB\u7A0B\u5F3A\u5236\u7EC8\u6B62\uFF0C\u7B49\u5F85\u8C03\u5EA6\u4E2D\u5FC3\u6062\u590D\u4F1A\u8BDD");if(u.unregisterInstance){e.info("[runtime-bridge] \u6B63\u5728\u6CE8\u9500\u5B9E\u4F8B...");try{await xe()}catch(t){const s=t;e.error("[runtime-bridge] \u6CE8\u9500\u5B9E\u4F8B\u5931\u8D25:",s.message)}}else e.info("[runtime-bridge] \u2605 \u4FDD\u7559\u6A21\u5F0F\u8DF3\u8FC7\u5B9E\u4F8B\u6CE8\u9500\uFF0C\u907F\u514D\u8C03\u5EA6\u4E2D\u5FC3\u5C06 Agent \u6807\u8BB0\u4E3A stopped");if(Ge(),u.stopTunnelClient&&(e.info("[runtime-bridge] \u6B63\u5728\u5173\u95ED\u96A7\u9053\u5BA2\u6237\u7AEF..."),Ve()),u.clearPersistedSessions){e.info("[runtime-bridge] \u6B63\u5728\u6E05\u7A7A\u6301\u4E45\u5316\u4F1A\u8BDD\u72B6\u6001...");try{await k([])}catch(t){const s=t;e.error("[runtime-bridge] \u6E05\u7A7A\u6301\u4E45\u5316\u72B6\u6001\u5931\u8D25:",s.message)}}else e.info("[runtime-bridge] \u2605 \u4FDD\u7559\u6301\u4E45\u5316\u4F1A\u8BDD\u72B6\u6001\uFF08aws-mcp-server \u91CD\u542F\u6062\u590D\u573A\u666F\uFF09");try{await Le(),e.info("[runtime-bridge] browser \u5DE5\u5177\u6808\u5DF2\u6E05\u7406")}catch(t){e.warn("[runtime-bridge] browser \u5DE5\u5177\u6808\u6E05\u7406\u5931\u8D25:",t.message)}try{await je(),e.info("[runtime-bridge] desktop \u5DE5\u5177\u6808\u5DF2\u6E05\u7406")}catch(t){e.warn("[runtime-bridge] desktop \u5DE5\u5177\u6808\u6E05\u7406\u5931\u8D25:",t.message)}try{await ze.stopAll(),e.info("[runtime-bridge] \u63D2\u4EF6\u76D1\u542C\u8FDB\u7A0B\u5DF2\u6E05\u7406")}catch(t){e.warn("[runtime-bridge] \u63D2\u4EF6\u76D1\u542C\u8FDB\u7A0B\u6E05\u7406\u5931\u8D25:",t.message)}const d=Date.now()-f;e.info(`[runtime-bridge] \u4F18\u96C5\u5173\u95ED\u5B8C\u6210 (\u8017\u65F6 ${d}ms)\uFF0C\u505C\u6B62 ${a} SDK \u4F1A\u8BDD`),o.close(()=>{e.info("[runtime-bridge] HTTP \u670D\u52A1\u5668\u5DF2\u5173\u95ED"),process.exit(process.exitCode||0)}),setTimeout(()=>{e.warn("[runtime-bridge] \u4F18\u96C5\u5173\u95ED\u8D85\u65F6\uFF0C\u5F3A\u5236\u9000\u51FA"),process.exit(1)},15e3)}catch(a){const l=a;e.error("[runtime-bridge] \u4F18\u96C5\u5173\u95ED\u8FC7\u7A0B\u4E2D\u53D1\u751F\u9519\u8BEF:",l),process.exit(1)}}Qe.reconcileZombies().then(r=>{r>0&&e.info(`[runtime-bridge] \u5DF2\u6E05\u7406 ${r} \u4E2A\u50F5\u5C38 sub-agent \u8BB0\u5F55`)}).catch(r=>{e.warn("[runtime-bridge] \u6E05\u7406\u50F5\u5C38 sub-agent \u8BB0\u5F55\u5931\u8D25:",r.message)});const h=ir(),v=S.join(M.tmpdir(),"agentswork-runtime-bridge",".preserve-sessions");function R(){try{if(T(v)){const r=D(v,"utf-8");return JSON.parse(r).preserveSessions===!0}}catch{}return!1}ae(async(r,o)=>{await b(r,h,o)}),process.on("SIGTERM",()=>{const r=R();b("SIGTERM",h,r)}),process.on("SIGINT",()=>{const r=R();b("SIGINT",h,r)}),process.platform==="win32"&&process.on("SIGBREAK",()=>{const r=R();b("SIGBREAK",h,r)}),process.on("uncaughtException",r=>{e.error("[runtime-bridge] \u672A\u6355\u83B7\u5F02\u5E38:",r),b("uncaughtException",h)}),process.on("unhandledRejection",r=>{e.error("[runtime-bridge] \u672A\u5904\u7406\u7684 Promise \u62D2\u7EDD:",r)});
|
|
3
3
|
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { IncomingMessage } from "node:http";
|
|
2
|
+
import type { Socket } from "node:net";
|
|
3
|
+
|
|
4
|
+
export declare function attachLspWebSocketServer(server: {
|
|
5
|
+
on: (event: "upgrade", listener: (request: IncomingMessage, socket: Socket, head: Buffer) => void) => unknown;
|
|
6
|
+
}): void;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import h from"node:path";import w,{WebSocketServer as m}from"ws";import{isUpgradeAllowed as P}from"../services/access-control.js";import{LspProcessBridge as S}from"../services/lsp-stdio-bridge.js";import{createLogger as $}from"../utils/logger.js";const o=$("lsp-ws"),k=6e4,b={typescript:"typescript",ts:"typescript",javascript:"javascript",js:"javascript",tsx:"typescript",jsx:"javascript"};function v(e){return b[e.toLowerCase()]??null}const l=new Map;function L(e){return h.resolve(e)}function E(e){const s=e.toString("utf8");if(!s.trim())return null;try{return JSON.parse(s)}catch{return null}}function u(e){e.idleTimer&&(clearTimeout(e.idleTimer),e.idleTimer=null)}function T(e){u(e),e.idleTimer=setTimeout(()=>{if(!(e.ws!==null&&e.ws.readyState===w.OPEN)){for(const[t,a]of l)if(a===e){l.delete(t);break}e.bridge.dispose()}},k)}function d(e,s){const t=new S({workspacePath:s.workspacePath,language:s.language},{onMessage:a=>{const r=l.get(e)?.ws;if(r&&r.readyState===w.OPEN)try{r.send(JSON.stringify(a))}catch(n){o.warn(`[lsp-ws] \u8F6C\u53D1 server \u6D88\u606F\u5931\u8D25: ${n.message}`)}},onExit:()=>{l.get(e)?.bridge===t&&l.delete(e)},onError:a=>{o.warn(`[lsp-ws] \u8BED\u8A00\u670D\u52A1\u9519\u8BEF ${s.workspacePath}: ${a.message}`)}});return t.start(),t}function y(e,s){return{bridge:d(e,s),ws:null,idleTimer:null,initialized:!1}}function z(e,s){const t=L(s.workspacePath);let a=l.get(t);a||(a=y(t,s),l.set(t,a)),u(a);const r=a;r.ws&&r.ws!==e&&r.ws.readyState===w.OPEN&&(o.info(`[lsp-ws] \u6324\u5360\u65E7\u8FDE\u63A5 workspace=${s.workspacePath}\uFF08\u65B0\u8FDE\u63A5\u63A5\u7BA1\u540C\u4E00\u8FDB\u7A0B\uFF09`),r.ws.close(1e3,"superseded by new lsp connection")),r.ws=e,e.on("message",n=>{const i=E(n);if(i===null){o.warn(`[lsp-ws] \u5FFD\u7565\u65E0\u6CD5\u89E3\u6790\u7684\u6D88\u606F: ${n.toString("utf8").slice(0,200)}`);return}i.method==="initialize"&&(r.initialized&&(o.info(`[lsp-ws] \u590D\u7528\u8FDB\u7A0B\u6536\u5230\u4E8C\u6B21 initialize\uFF0C\u91CD\u5EFA\u8BED\u8A00\u670D\u52A1\u8FDB\u7A0B workspace=${s.workspacePath}`),r.bridge.dispose(),r.bridge=d(t,s)),r.initialized=!0),r.bridge.send(i)}),e.on("close",()=>{r.ws===e&&(r.ws=null),T(r)}),e.on("error",n=>{o.warn(`[lsp-ws] \u8FDE\u63A5\u5F02\u5E38 workspace=${s.workspacePath}: ${n.message}`)}),o.info(`[lsp-ws] \u8FDE\u63A5\u5EFA\u7ACB workspace=${s.workspacePath} file=${s.filePath} language=${s.language} reused=${a.bridge.running}`)}function U(e){const s=new m({noServer:!0});e.on("upgrade",(t,a,r)=>{if(!P(t,a))return;const n=t.headers.host||"localhost",i=new URL(t.url||"/",`http://${n}`);if(i.pathname!=="/ws/lsp")return;const c=i.searchParams.get("workspacePath")||"",p=i.searchParams.get("file")||"",g=v(i.searchParams.get("language")||"");if(!c||!p||!g){o.warn(`[lsp-ws] upgrade \u53C2\u6570\u7F3A\u5931: workspacePath=${!!c}, file=${!!p}, language=${g}`),a.write(`HTTP/1.1 400 Bad Request\r
|
|
2
|
+
\r
|
|
3
|
+
`),a.destroy();return}s.handleUpgrade(t,a,r,f=>{z(f,{workspacePath:c,filePath:p,language:g})})})}export{U as attachLspWebSocketServer};
|
|
4
|
+
|
package/dist/routes/ltr.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import m
|
|
1
|
+
import{randomUUID as m}from"node:crypto";import{promises as i}from"node:fs";import p from"node:os";import n from"node:path";import{Router as l}from"express";import{validateToken as u}from"../middleware/auth.js";import{createLogger as d}from"../utils/logger.js";const s=d("ltr"),w=l(),c=n.join(p.tmpdir(),"aw-temp","LTR"),y=7,f=512*1024;function g(o=new Date){const e=o.getFullYear(),t=String(o.getMonth()+1).padStart(2,"0"),r=String(o.getDate()).padStart(2,"0");return n.join(c,`${e}${t}${r}`)}async function h(){const o=Date.now()-y*24*60*60*1e3;try{const e=await i.readdir(c,{withFileTypes:!0});for(const t of e){if(!t.isDirectory())continue;const r=n.join(c,t.name);try{(await i.stat(r)).mtimeMs<o&&(await i.rm(r,{recursive:!0,force:!0}),s.info(`[ltr] removed expired temp dir: ${r}`))}catch{}}}catch(e){const t=e;t.code!=="ENOENT"&&s.warn("[ltr] cleanup expired dirs failed:",t)}}async function T(o){const e=String(o??"");if(!e.trim())throw new Error("ltr content is empty");const t=Buffer.byteLength(e,"utf8");if(t>f)throw new Error(`ltr content too large: ${t} bytes, max ${f} bytes`);const r=g();await i.mkdir(r,{recursive:!0});const a=n.join(r,`${m()}.txt`);return await i.writeFile(a,e,"utf8"),h(),a}w.post("/upload",u,async(o,e)=>{try{const{content:t}=o.body||{},r=await T(String(t??""));e.json({path:r})}catch(t){const r=t;s.error("[ltr] failed to write temp text file:",r),e.status(400).json({error:r.message})}});export{c as LTR_ROOT,w as ltrRouter};
|
|
2
2
|
|
|
@@ -1,4 +1,91 @@
|
|
|
1
1
|
|
|
2
2
|
export declare const sessionsRouter: import("express-serve-static-core").Router;
|
|
3
3
|
|
|
4
|
+
export declare function handleCapabilityToolsRequest(input: {
|
|
5
|
+
agentId: string;
|
|
6
|
+
capability: string;
|
|
7
|
+
action: unknown;
|
|
8
|
+
|
|
9
|
+
resolveSession?: () => {
|
|
10
|
+
agentId: string;
|
|
11
|
+
providerId: string;
|
|
12
|
+
} | undefined;
|
|
13
|
+
resolveAdapter?: (providerId: string) => {
|
|
14
|
+
setBuiltInCapabilityTools?: (agentId: string, capability: string, action: 'expand' | 'collapse') => Promise<{
|
|
15
|
+
sessions: number;
|
|
16
|
+
tools: number;
|
|
17
|
+
manifests?: Array<{
|
|
18
|
+
name: string;
|
|
19
|
+
description?: string;
|
|
20
|
+
inputSchema?: unknown;
|
|
21
|
+
}>;
|
|
22
|
+
}>;
|
|
23
|
+
};
|
|
24
|
+
}): Promise<{
|
|
25
|
+
status: 400;
|
|
26
|
+
body: {
|
|
27
|
+
ok: false;
|
|
28
|
+
error: string;
|
|
29
|
+
};
|
|
30
|
+
} | {
|
|
31
|
+
status: 200;
|
|
32
|
+
body: {
|
|
33
|
+
ok: true;
|
|
34
|
+
changed: {
|
|
35
|
+
sessions: number;
|
|
36
|
+
tools: number;
|
|
37
|
+
};
|
|
38
|
+
manifests?: Array<{
|
|
39
|
+
name: string;
|
|
40
|
+
description?: string;
|
|
41
|
+
inputSchema?: unknown;
|
|
42
|
+
}>;
|
|
43
|
+
message?: string;
|
|
44
|
+
};
|
|
45
|
+
} | {
|
|
46
|
+
status: 500;
|
|
47
|
+
body: {
|
|
48
|
+
ok: false;
|
|
49
|
+
error: string;
|
|
50
|
+
};
|
|
51
|
+
}>;
|
|
52
|
+
|
|
53
|
+
export declare function handleCapabilityToolCallRequest(input: {
|
|
54
|
+
agentId: string;
|
|
55
|
+
capability: string;
|
|
56
|
+
tool: string;
|
|
57
|
+
args: Record<string, unknown>;
|
|
58
|
+
|
|
59
|
+
resolveSession?: () => {
|
|
60
|
+
agentId: string;
|
|
61
|
+
providerId: string;
|
|
62
|
+
} | undefined;
|
|
63
|
+
resolveAdapter?: (providerId: string) => {
|
|
64
|
+
callBuiltInCapabilityTool?: (agentId: string, capability: string, toolName: string, args: Record<string, unknown>) => Promise<{
|
|
65
|
+
ok: boolean;
|
|
66
|
+
result?: unknown;
|
|
67
|
+
error?: string;
|
|
68
|
+
}>;
|
|
69
|
+
};
|
|
70
|
+
}): Promise<{
|
|
71
|
+
status: 400;
|
|
72
|
+
body: {
|
|
73
|
+
ok: false;
|
|
74
|
+
error: string;
|
|
75
|
+
};
|
|
76
|
+
} | {
|
|
77
|
+
status: 200;
|
|
78
|
+
body: {
|
|
79
|
+
ok: boolean;
|
|
80
|
+
result?: unknown;
|
|
81
|
+
error?: string;
|
|
82
|
+
};
|
|
83
|
+
} | {
|
|
84
|
+
status: 500;
|
|
85
|
+
body: {
|
|
86
|
+
ok: false;
|
|
87
|
+
error: string;
|
|
88
|
+
};
|
|
89
|
+
}>;
|
|
90
|
+
|
|
4
91
|
export declare function resolveActiveSdkSessionSnapshotStatus(adapterStatus?: string, currentRuntimeStatus?: string, currentRuntimeActionType?: string): string;
|
package/dist/routes/sessions.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{execSync as b}from"node:child_process";import{Router as R}from"express";import{adapterRegistry as I}from"../adapter/index.js";import{validateToken as S,validateTokenOrLoopback as T}from"../middleware/auth.js";import{isProcessRunning as w,findOrphanProcessByAgentId as P,findOrphanProcessByWorkspace as F}from"../services/process-detector.js";import{findPersistedSessionByAgentId as k,loadPersistedSessions as K,removePersistedSession as A}from"../services/terminal-persistence.js";import{createLogger as E}from"../utils/logger.js";import{sdkSessions as g,cleanupSdkSessionByAgentId as C}from"./terminal.js";const c=E("sessions"),h=R();h.post("/sessions/:agentId/notify-force-message",T,(u,n)=>{const e=String(u.params.agentId??"").trim();if(!e){n.status(400).json({ok:!1,error:"agentId is required"});return}const r=Array.from(g.entries()).find(([,i])=>i.agentId===e);if(!r){n.json({ok:!0,notified:!1,message:"No active SDK session for this agentId"});return}const[o,s]=r,t=I.get(s.providerId||"claude-code");if(typeof t.notifyForceMessage=="function"){const i=t.notifyForceMessage(o);n.json({ok:!0,notified:i})}else n.json({ok:!0,notified:!1,message:"Adapter does not support force message notification"})});function j(u,n,e){const r=String(u||"").trim();if(r){const s=String(n||"").trim(),t=String(e||"").trim().toLowerCase();return r.toLowerCase()==="tool_using"&&s.toLowerCase()==="waiting_input"&&t==="idle"?s:r}return String(n||"").trim()||"running"}h.get("/sessions",S,async(u,n)=>{try{const r=Array.from(g.entries()).map(([d,p])=>{const m=I.get(p.providerId||"claude-code"),a=j(m.getSessionStatus(d),p.currentRuntimeStatus,p.currentRuntimeActionType);return{sessionId:d,agentId:p.agentId,workspacePath:p.workspacePath,status:a,runtimeStatus:a,runtimeActionType:p.currentRuntimeActionType,runtimeActionLabel:p.currentRuntimeActionLabel,runtimeActionDetail:p.currentRuntimeActionDetail,mode:"sdk",startedAt:null}}),o=await K(),s=new Set(r.map(d=>d.sessionId)),t=o.filter(d=>!s.has(d.sessionId)),i={ok:!0,active:r,persisted:t};n.json(i)}catch(e){const r=e;n.status(500).json({error:r.message})}}),h.post("/sessions/recover",S,async(u,n)=>{const{agentId:e,workspacePath:r,command:o}=u.body;if(!e){n.status(400).json({error:"agentId is required"});return}try{const s=Array.from(g.entries()).find(([,l])=>l.agentId===e);if(s){const l=I.get(s[1].providerId||"claude-code"),v=j(l.getSessionStatus(s[0]),s[1].currentRuntimeStatus,s[1].currentRuntimeActionType);n.json({ok:!0,sessionId:s[0],agentId:e,workspacePath:s[1].workspacePath,command:s[1].config.command,status:v,runtimeStatus:v,runtimeActionType:s[1].currentRuntimeActionType,runtimeActionLabel:s[1].currentRuntimeActionLabel,runtimeActionDetail:s[1].currentRuntimeActionDetail,mode:"sdk",recovered:!1,message:"SDK session already active"});return}const t=await k(e);let i=!1,d;if(t?.pid&&w(t.pid))i=!0,d=t.pid,c.info(`[Recover] Detected orphan process for agentId=${e}, pid=${t.pid}`);else if(t?.mode==="sdk"||!t?.pid){const l=await P(e);l&&(i=!0,d=l.pid,c.info(`[Recover] Found orphan process by agentId search: agentId=${e}, pid=${l.pid}`))}const p=r||t?.workspacePath,m=o||t?.command||"acode",a=t?.mode||"sdk";if(!p){n.status(400).json({error:"workspacePath is required (not found in persisted session)"});return}if(i&&d){c.info(`[Recover] Returning orphan process info for agentId=${e}`),n.json({ok:!0,sessionId:t?.sessionId||"",agentId:e,workspacePath:p,command:m,status:"orphan_detected",runtimeStatus:t?.runtimeStatus,runtimeActionType:t?.runtimeActionType,runtimeActionLabel:t?.runtimeActionLabel,runtimeActionDetail:t?.runtimeActionDetail,recovered:!1,orphan:{pid:d,message:"Found orphan process still running. Manual intervention may be required."},mode:a});return}await A(t?.sessionId||"");const f={ok:!1,sessionId:t?.sessionId||"",agentId:e,workspacePath:p,command:m,status:"stopped",recovered:!1,message:"No active SDK session found; start a new SDK runtime session instead."};n.json(f)}catch(s){const t=s;c.error("Error:",t),n.status(500).json({error:t.message})}}),h.post("/search-orphan",S,async(u,n)=>{const{agentId:e,workspacePath:r}=u.body;if(!e){n.status(400).json({error:"agentId is required"});return}try{const o=Array.from(g.entries()).find(([,a])=>a.agentId===e);let s=!1,t,i;if(o){const[a,f]=o,l=I.get(f.providerId||"claude-code");t=l.getSessionPid?.(a),i=f.config?.command;const v=t?w(t):!1,y=l.getSessionStatus(a),D=y==="completed"||y==="terminated"||y==="error";if(v)s=!0;else if(t&&!v)c.info(`[search-orphan] Cleaning up stale SDK session (process dead): agentId=${e}, sessionId=${a}, pid=${t}`),g.delete(a),await A(a);else if(D){c.info(`[search-orphan] Cleaning up stale in-process SDK session (status=${y}): agentId=${e}, sessionId=${a}`);try{await l.terminateSession(a)}catch($){c.warn(`[search-orphan] Failed to terminate stale in-process session: ${$}`)}g.delete(a),await A(a)}else{c.info(`[search-orphan] Terminating unreachable in-process SDK session: agentId=${e}, sessionId=${a}, status=${y||"unknown"}`);try{await l.abortCurrentTurn(a).catch(()=>{}),await l.terminateSession(a)}catch($){c.warn(`[search-orphan] Failed to terminate in-process session: ${$}`)}g.delete(a),await A(a)}}const d=await P(e);if(d){c.info(`[search-orphan] Found orphan process for agentId=${e}, pid=${d.pid}`),n.json({ok:!0,agentId:e,hasActiveSession:s,found:!0,orphan:{pid:d.pid,command:d.command,cwd:d.cwd,startedAt:d.startedAt,message:"Found orphan process. Click terminate to stop it."}});return}if(s&&t){c.info(`[search-orphan] Active session process still running, reporting as terminable orphan: agentId=${e}, pid=${t}`),n.json({ok:!0,agentId:e,hasActiveSession:!0,found:!0,orphan:{pid:t,command:i||"(active SDK session)",message:"Found active SDK session process. Click terminate to stop it."}});return}const p=await k(e);if(p?.pid&&w(p.pid)){c.info(`[search-orphan] Found orphan by persisted PID: agentId=${e}, pid=${p.pid}`),n.json({ok:!0,agentId:e,hasActiveSession:s,found:!0,orphan:{pid:p.pid,command:p.command||"(persisted session)",message:"Found orphan process by persisted PID. Click terminate to stop it."}});return}const m=r||p?.workspacePath;if(m){const a=await F(m);if(a){c.info(`[search-orphan] Found orphan by workspace: agentId=${e}, pid=${a.pid}, workspace=${m}`),n.json({ok:!0,agentId:e,hasActiveSession:s,found:!0,orphan:{pid:a.pid,command:a.command,message:"Found orphan process by workspace path. Click terminate to stop it."}});return}}c.info(`[search-orphan] No orphan process found for agentId=${e}, hasActiveSession=${!!s}`),n.json({ok:!0,agentId:e,hasActiveSession:!!s,found:!1,orphan:null,message:s?"Agent has active session in runtime-bridge":"No orphan process and no active session found"})}catch(o){const s=o;c.error("[search-orphan] Error:",s),n.status(500).json({error:s.message})}}),h.post("/terminate-orphan",S,async(u,n)=>{const{agentId:e,pid:r}=u.body;if(!e||!r){n.status(400).json({error:"agentId and pid are required"});return}try{const o=Array.from(g.entries()).find(([,i])=>i.agentId===e);if(o){const[i,d]=o,p=I.get(d.providerId||"claude-code");try{await p.terminateSession(i)}catch(m){c.warn(`[terminate-orphan] Failed to terminate SDK session for agentId=${e}:`,m)}g.delete(i),await A(i),c.info(`[terminate-orphan] Cleaned up SDK session for agentId=${e}, sessionId=${i}`)}if(!w(r)){n.json({ok:!0,agentId:e,pid:r,terminated:!1,message:"Process already terminated"});return}const s=process.platform;let t=!1;if(s==="win32")try{b(`taskkill /PID ${r} /T /F`,{encoding:"utf8",timeout:5e3}),t=!0}catch(i){c.warn(`[terminate-orphan] taskkill failed for pid=${r}:`,i)}else try{process.kill(r,"SIGTERM"),t=!0}catch(i){c.warn(`[terminate-orphan] kill failed for pid=${r}:`,i)}t?(c.info(`[terminate-orphan] Terminated orphan process for agentId=${e}, pid=${r}`),n.json({ok:!0,agentId:e,pid:r,terminated:!0,message:"Orphan process terminated successfully"})):n.json({ok:!0,agentId:e,pid:r,terminated:!1,message:"Failed to terminate process"})}catch(o){const s=o;c.error("[terminate-orphan] Error:",s),n.status(500).json({error:s.message})}}),h.get("/sessions/by-agent/:agentId",S,async(u,n)=>{const e=u.params.agentId,r=Array.isArray(e)?e[0]:e;if(!r){n.status(400).json({error:"agentId is required"});return}try{const o=Array.from(g.entries()).find(([,t])=>t.agentId===r);if(o){const t=I.get(o[1].providerId||"claude-code"),i=t.getSessionPid?.(o[0]),d=j(t.getSessionStatus(o[0]),o[1].currentRuntimeStatus,o[1].currentRuntimeActionType);n.json({ok:!0,sessionId:o[0],agentId:r,workspacePath:o[1].workspacePath,status:d,runtimeStatus:d,isActive:!0,mode:"sdk",pid:i,isManaged:!0,providerId:o[1].providerId});return}const s=await k(r);if(s){const{isProcessRunning:t}=await import("../services/process-detector.js"),i=s.pid?t(s.pid):!1;n.json({ok:!0,sessionId:s.sessionId,agentId:r,workspacePath:s.workspacePath,command:s.command,status:i?"orphan":"stopped",runtimeStatus:s.runtimeStatus,runtimeActionType:s.runtimeActionType,runtimeActionLabel:s.runtimeActionLabel,runtimeActionDetail:s.runtimeActionDetail,startedAt:s.startedAt,isActive:!1,mode:s.mode,pid:s.pid,isManaged:!1,isProcessAlive:i,isOrphan:i});return}n.json({ok:!0,agentId:r,status:"none",isActive:!1,isManaged:!1})}catch(o){const s=o;c.error("[sessions/by-agent] Error:",s),n.status(500).json({error:s.message})}}),h.post("/takeover-session",S,async(u,n)=>{const{agentId:e}=u.body;if(!e){n.status(400).json({error:"agentId is required"});return}try{const r=Array.from(g.entries()).find(([,t])=>t.agentId===e);if(r){n.json({ok:!0,agentId:e,sessionId:r[0],mode:"sdk",status:"running",isActive:!0,recovered:!1,message:"SDK session already active"});return}const o=await k(e);if(!o){n.status(404).json({error:"No persisted session found for this agentId",agentId:e});return}let s=!1;if(o.mode==="sdk"&&(s=!!await P(e),!s&&o.pid&&(s=w(o.pid))),!s){c.info(`[takeover-session] Process not alive for agentId=${e}, mode=${o.mode}`),n.json({ok:!1,agentId:e,status:"process_not_alive",isActive:!1,message:"Agent process is no longer running"});return}if(c.info(`[takeover-session] Taking over session for agentId=${e}, mode=${o.mode}, pid=${o.pid}`),o.mode==="sdk"){const t=await P(e);t?(c.info(`[takeover-session] Found SDK process for agentId=${e}, pid=${t.pid}`),n.json({ok:!0,agentId:e,sessionId:o.sessionId,mode:"sdk",status:"running",isActive:!0,recovered:!0,pid:t.pid||o.pid,message:"SDK session process found, can be taken over by aws-mcp-server"})):n.json({ok:!1,agentId:e,status:"process_not_alive",isActive:!1,message:"SDK process not found"})}else n.status(410).json({error:"Session takeover is no longer supported; start a new SDK runtime session.",agentId:e,mode:"sdk"})}catch(r){const o=r;c.error("[takeover-session] Error:",o),n.status(500).json({error:o.message})}}),h.post("/terminate-tree",S,async(u,n)=>{const{agentId:e,sessionId:r}=u.body;if(!e){n.status(400).json({error:"agentId is required"});return}try{let o=r;if(!o){const f=await k(e);if(!f){n.status(404).json({error:"Session not found for this agentId"});return}o=f.sessionId}const s=g.get(o);let t,i;if(s)t=I.get(s.providerId||"claude-code").getSessionPid?.(o),i="sdk";else{const f=await k(e);if(!f?.pid){n.status(404).json({error:"Session PID not found"});return}t=f.pid,i=f.mode||"sdk"}const{terminateProcessTree:d,waitForProcessExit:p}=await import("../services/process-detector.js");if(!t){n.status(404).json({error:"PID not found"});return}const m=await d(t),a=await p(t,5e3);C(e),await import("../services/terminal-persistence.js").then(f=>f.removePersistedSession(o)),c.info(`[terminate-tree] Terminated process tree for agentId=${e}, pid=${t}, mode=${i}, terminated=${m.terminated}, failed=${m.failed}, exited=${a}`),n.json({ok:!0,agentId:e,pid:t,mode:i,terminated:m.terminated,failed:m.failed,exited:a,message:a?`Successfully terminated ${m.terminated} processes`:`Terminated ${m.terminated} processes, but process ${t} still running`})}catch(o){const s=o;c.error("[terminate-tree] Error:",s),n.status(500).json({error:s.message})}}),h.get("/health/:agentId",S,async(u,n)=>{const e=u.params.agentId,r=Array.isArray(e)?e[0]:e;if(!r){n.status(400).json({error:"agentId is required"});return}try{const o=await k(r);if(!o){n.status(404).json({error:"Session not found"});return}const s=g.get(o.sessionId),t=!!s,{checkProcessHealth:i}=await import("../services/process-detector.js"),d={sessionId:o.sessionId,mode:o.mode,workspacePath:o.workspacePath,isManaged:t,isActive:!!s};if(o.pid){const p=await i(o.pid,r);Object.assign(d,p)}else Object.assign(d,{pid:0,alive:!1,cpu:0,memoryMB:0,status:"dead",lastUpdate:new Date});n.json({agentId:r,...d})}catch(o){const s=o;c.error("[health] Error:",s),n.status(500).json({error:s.message})}});export{j as resolveActiveSdkSessionSnapshotStatus,h as sessionsRouter};
|
|
1
|
+
import{execSync as T}from"node:child_process";import{Router as R}from"express";import{adapterRegistry as y}from"../adapter/index.js";import{validateToken as I,validateTokenOrLoopback as P}from"../middleware/auth.js";import{isProcessRunning as b,findOrphanProcessByAgentId as A,findOrphanProcessByWorkspace as C}from"../services/process-detector.js";import{findPersistedSessionByAgentId as S,loadPersistedSessions as F,removePersistedSession as w}from"../services/terminal-persistence.js";import{createLogger as K}from"../utils/logger.js";import{sdkSessions as m,cleanupSdkSessionByAgentId as E}from"./terminal.js";const u=K("sessions"),h=R();h.post("/sessions/:agentId/notify-force-message",P,(i,t)=>{const e=String(i.params.agentId??"").trim();if(!e){t.status(400).json({ok:!1,error:"agentId is required"});return}const n=Array.from(m.entries()).find(([,c])=>c.agentId===e);if(!n){t.json({ok:!0,notified:!1,message:"No active SDK session for this agentId"});return}const[r,s]=n,o=y.get(s.providerId||"claude-code");if(typeof o.notifyForceMessage=="function"){const c=o.notifyForceMessage(r);t.json({ok:!0,notified:c})}else t.json({ok:!0,notified:!1,message:"Adapter does not support force message notification"})});async function x(i){const t=String(i.agentId??"").trim(),e=String(i.capability??"").trim(),n=i.action==="expand"||i.action==="collapse"?i.action:void 0;if(!t)return{status:400,body:{ok:!1,error:"agentId is required"}};if(e!=="browser"&&e!=="desktop")return{status:400,body:{ok:!1,error:'capability must be "browser" or "desktop"'}};if(n!=="expand"&&n!=="collapse")return{status:400,body:{ok:!1,error:'action must be "expand" or "collapse"'}};const s=(i.resolveSession??(()=>{const a=Array.from(m.entries()).find(([,d])=>d.agentId===t);return a?{agentId:a[1].agentId,providerId:a[1].providerId}:void 0}))();if(!s)return{status:200,body:{ok:!0,changed:{sessions:0,tools:0},message:"No active SDK session for this agentId"}};const o=i.resolveAdapter??(a=>y.get(a));let c;try{c=o(s.providerId||"claude-code")}catch(a){return{status:500,body:{ok:!1,error:a?.message||"adapter resolution failed"}}}if(typeof c.setBuiltInCapabilityTools!="function")return{status:200,body:{ok:!0,changed:{sessions:0,tools:0},message:"Adapter does not support built-in capability tool switching"}};try{const a=await c.setBuiltInCapabilityTools(t,e,n),{manifests:d,...l}=a;return{status:200,body:{ok:!0,changed:l,...d&&d.length>0?{manifests:d}:{}}}}catch(a){return u.error("[sessions] capability-tools \u6267\u884C\u5931\u8D25",{agentId:t,capability:e,action:n,error:a?.message||String(a)}),{status:500,body:{ok:!1,error:a?.message||"failed"}}}}async function L(i){const t=String(i.agentId??"").trim(),e=String(i.capability??"").trim(),n=String(i.tool??"").trim(),r=i.args&&typeof i.args=="object"&&!Array.isArray(i.args)?i.args:{};if(!t)return{status:400,body:{ok:!1,error:"agentId is required"}};if(e!=="browser"&&e!=="desktop")return{status:400,body:{ok:!1,error:'capability must be "browser" or "desktop"'}};if(!n)return{status:400,body:{ok:!1,error:"tool is required"}};const o=(i.resolveSession??(()=>{const d=Array.from(m.entries()).find(([,l])=>l.agentId===t);return d?{agentId:d[1].agentId,providerId:d[1].providerId}:void 0}))();if(!o)return{status:200,body:{ok:!1,error:"No active SDK session for this agentId"}};const c=i.resolveAdapter??(d=>y.get(d));let a;try{a=c(o.providerId||"claude-code")}catch(d){return{status:500,body:{ok:!1,error:d?.message||"adapter resolution failed"}}}if(typeof a.callBuiltInCapabilityTool!="function")return{status:200,body:{ok:!1,error:"Adapter does not support built-in capability tool dispatch"}};try{return{status:200,body:await a.callBuiltInCapabilityTool(t,e,n,r)}}catch(d){return u.error("[sessions] capability-tools/call \u6267\u884C\u5931\u8D25",{agentId:t,capability:e,tool:n,error:d?.message||String(d)}),{status:500,body:{ok:!1,error:d?.message||"failed"}}}}h.post("/sessions/:agentId/capability-tools",P,async(i,t)=>{const e=await x({agentId:String(i.params.agentId??""),capability:String(i.body?.capability??""),action:i.body?.action});t.status(e.status).json(e.body)}),h.post("/sessions/:agentId/capability-tools/call",P,async(i,t)=>{const e=await L({agentId:String(i.params.agentId??""),capability:String(i.body?.capability??""),tool:String(i.body?.tool??""),args:i.body?.arguments});t.status(e.status).json(e.body)});function $(i,t,e){const n=String(i||"").trim();if(n){const s=String(t||"").trim(),o=String(e||"").trim().toLowerCase();return n.toLowerCase()==="tool_using"&&s.toLowerCase()==="waiting_input"&&o==="idle"?s:n}return String(t||"").trim()||"running"}h.get("/sessions",I,async(i,t)=>{try{const n=Array.from(m.entries()).map(([a,d])=>{const l=y.get(d.providerId||"claude-code"),p=$(l.getSessionStatus(a),d.currentRuntimeStatus,d.currentRuntimeActionType);return{sessionId:a,agentId:d.agentId,workspacePath:d.workspacePath,status:p,runtimeStatus:p,runtimeActionType:d.currentRuntimeActionType,runtimeActionLabel:d.currentRuntimeActionLabel,runtimeActionDetail:d.currentRuntimeActionDetail,mode:"sdk",startedAt:null}}),r=await F(),s=new Set(n.map(a=>a.sessionId)),o=r.filter(a=>!s.has(a.sessionId)),c={ok:!0,active:n,persisted:o};t.json(c)}catch(e){const n=e;t.status(500).json({error:n.message})}}),h.post("/sessions/recover",I,async(i,t)=>{const{agentId:e,workspacePath:n,command:r}=i.body;if(!e){t.status(400).json({error:"agentId is required"});return}try{const s=Array.from(m.entries()).find(([,g])=>g.agentId===e);if(s){const g=y.get(s[1].providerId||"claude-code"),k=$(g.getSessionStatus(s[0]),s[1].currentRuntimeStatus,s[1].currentRuntimeActionType);t.json({ok:!0,sessionId:s[0],agentId:e,workspacePath:s[1].workspacePath,command:s[1].config.command,status:k,runtimeStatus:k,runtimeActionType:s[1].currentRuntimeActionType,runtimeActionLabel:s[1].currentRuntimeActionLabel,runtimeActionDetail:s[1].currentRuntimeActionDetail,mode:"sdk",recovered:!1,message:"SDK session already active"});return}const o=await S(e);let c=!1,a;if(o?.pid&&b(o.pid))c=!0,a=o.pid,u.info(`[Recover] Detected orphan process for agentId=${e}, pid=${o.pid}`);else if(o?.mode==="sdk"||!o?.pid){const g=await A(e);g&&(c=!0,a=g.pid,u.info(`[Recover] Found orphan process by agentId search: agentId=${e}, pid=${g.pid}`))}const d=n||o?.workspacePath,l=r||o?.command||"acode",p=o?.mode||"sdk";if(!d){t.status(400).json({error:"workspacePath is required (not found in persisted session)"});return}if(c&&a){u.info(`[Recover] Returning orphan process info for agentId=${e}`),t.json({ok:!0,sessionId:o?.sessionId||"",agentId:e,workspacePath:d,command:l,status:"orphan_detected",runtimeStatus:o?.runtimeStatus,runtimeActionType:o?.runtimeActionType,runtimeActionLabel:o?.runtimeActionLabel,runtimeActionDetail:o?.runtimeActionDetail,recovered:!1,orphan:{pid:a,message:"Found orphan process still running. Manual intervention may be required."},mode:p});return}await w(o?.sessionId||"");const f={ok:!1,sessionId:o?.sessionId||"",agentId:e,workspacePath:d,command:l,status:"stopped",recovered:!1,message:"No active SDK session found; start a new SDK runtime session instead."};t.json(f)}catch(s){const o=s;u.error("Error:",o),t.status(500).json({error:o.message})}}),h.post("/search-orphan",I,async(i,t)=>{const{agentId:e,workspacePath:n}=i.body;if(!e){t.status(400).json({error:"agentId is required"});return}try{const r=Array.from(m.entries()).find(([,p])=>p.agentId===e);let s=!1,o,c;if(r){const[p,f]=r,g=y.get(f.providerId||"claude-code");o=g.getSessionPid?.(p),c=f.config?.command;const k=o?b(o):!1,v=g.getSessionStatus(p),D=v==="completed"||v==="terminated"||v==="error";if(k)s=!0;else if(o&&!k)u.info(`[search-orphan] Cleaning up stale SDK session (process dead): agentId=${e}, sessionId=${p}, pid=${o}`),m.delete(p),await w(p);else if(D){u.info(`[search-orphan] Cleaning up stale in-process SDK session (status=${v}): agentId=${e}, sessionId=${p}`);try{await g.terminateSession(p)}catch(j){u.warn(`[search-orphan] Failed to terminate stale in-process session: ${j}`)}m.delete(p),await w(p)}else{u.info(`[search-orphan] Terminating unreachable in-process SDK session: agentId=${e}, sessionId=${p}, status=${v||"unknown"}`);try{await g.abortCurrentTurn(p).catch(()=>{}),await g.terminateSession(p)}catch(j){u.warn(`[search-orphan] Failed to terminate in-process session: ${j}`)}m.delete(p),await w(p)}}const a=await A(e);if(a){u.info(`[search-orphan] Found orphan process for agentId=${e}, pid=${a.pid}`),t.json({ok:!0,agentId:e,hasActiveSession:s,found:!0,orphan:{pid:a.pid,command:a.command,cwd:a.cwd,startedAt:a.startedAt,message:"Found orphan process. Click terminate to stop it."}});return}if(s&&o){u.info(`[search-orphan] Active session process still running, reporting as terminable orphan: agentId=${e}, pid=${o}`),t.json({ok:!0,agentId:e,hasActiveSession:!0,found:!0,orphan:{pid:o,command:c||"(active SDK session)",message:"Found active SDK session process. Click terminate to stop it."}});return}const d=await S(e);if(d?.pid&&b(d.pid)){u.info(`[search-orphan] Found orphan by persisted PID: agentId=${e}, pid=${d.pid}`),t.json({ok:!0,agentId:e,hasActiveSession:s,found:!0,orphan:{pid:d.pid,command:d.command||"(persisted session)",message:"Found orphan process by persisted PID. Click terminate to stop it."}});return}const l=n||d?.workspacePath;if(l){const p=await C(l);if(p){u.info(`[search-orphan] Found orphan by workspace: agentId=${e}, pid=${p.pid}, workspace=${l}`),t.json({ok:!0,agentId:e,hasActiveSession:s,found:!0,orphan:{pid:p.pid,command:p.command,message:"Found orphan process by workspace path. Click terminate to stop it."}});return}}u.info(`[search-orphan] No orphan process found for agentId=${e}, hasActiveSession=${!!s}`),t.json({ok:!0,agentId:e,hasActiveSession:!!s,found:!1,orphan:null,message:s?"Agent has active session in runtime-bridge":"No orphan process and no active session found"})}catch(r){const s=r;u.error("[search-orphan] Error:",s),t.status(500).json({error:s.message})}}),h.post("/terminate-orphan",I,async(i,t)=>{const{agentId:e,pid:n}=i.body;if(!e||!n){t.status(400).json({error:"agentId and pid are required"});return}try{const r=Array.from(m.entries()).find(([,c])=>c.agentId===e);if(r){const[c,a]=r,d=y.get(a.providerId||"claude-code");try{await d.terminateSession(c)}catch(l){u.warn(`[terminate-orphan] Failed to terminate SDK session for agentId=${e}:`,l)}m.delete(c),await w(c),u.info(`[terminate-orphan] Cleaned up SDK session for agentId=${e}, sessionId=${c}`)}if(!b(n)){t.json({ok:!0,agentId:e,pid:n,terminated:!1,message:"Process already terminated"});return}const s=process.platform;let o=!1;if(s==="win32")try{T(`taskkill /PID ${n} /T /F`,{encoding:"utf8",timeout:5e3}),o=!0}catch(c){u.warn(`[terminate-orphan] taskkill failed for pid=${n}:`,c)}else try{process.kill(n,"SIGTERM"),o=!0}catch(c){u.warn(`[terminate-orphan] kill failed for pid=${n}:`,c)}o?(u.info(`[terminate-orphan] Terminated orphan process for agentId=${e}, pid=${n}`),t.json({ok:!0,agentId:e,pid:n,terminated:!0,message:"Orphan process terminated successfully"})):t.json({ok:!0,agentId:e,pid:n,terminated:!1,message:"Failed to terminate process"})}catch(r){const s=r;u.error("[terminate-orphan] Error:",s),t.status(500).json({error:s.message})}}),h.get("/sessions/by-agent/:agentId",I,async(i,t)=>{const e=i.params.agentId,n=Array.isArray(e)?e[0]:e;if(!n){t.status(400).json({error:"agentId is required"});return}try{const r=Array.from(m.entries()).find(([,o])=>o.agentId===n);if(r){const o=y.get(r[1].providerId||"claude-code"),c=o.getSessionPid?.(r[0]),a=$(o.getSessionStatus(r[0]),r[1].currentRuntimeStatus,r[1].currentRuntimeActionType);t.json({ok:!0,sessionId:r[0],agentId:n,workspacePath:r[1].workspacePath,status:a,runtimeStatus:a,isActive:!0,mode:"sdk",pid:c,isManaged:!0,providerId:r[1].providerId});return}const s=await S(n);if(s){const{isProcessRunning:o}=await import("../services/process-detector.js"),c=s.pid?o(s.pid):!1;t.json({ok:!0,sessionId:s.sessionId,agentId:n,workspacePath:s.workspacePath,command:s.command,status:c?"orphan":"stopped",runtimeStatus:s.runtimeStatus,runtimeActionType:s.runtimeActionType,runtimeActionLabel:s.runtimeActionLabel,runtimeActionDetail:s.runtimeActionDetail,startedAt:s.startedAt,isActive:!1,mode:s.mode,pid:s.pid,isManaged:!1,isProcessAlive:c,isOrphan:c});return}t.json({ok:!0,agentId:n,status:"none",isActive:!1,isManaged:!1})}catch(r){const s=r;u.error("[sessions/by-agent] Error:",s),t.status(500).json({error:s.message})}}),h.post("/takeover-session",I,async(i,t)=>{const{agentId:e}=i.body;if(!e){t.status(400).json({error:"agentId is required"});return}try{const n=Array.from(m.entries()).find(([,o])=>o.agentId===e);if(n){t.json({ok:!0,agentId:e,sessionId:n[0],mode:"sdk",status:"running",isActive:!0,recovered:!1,message:"SDK session already active"});return}const r=await S(e);if(!r){t.status(404).json({error:"No persisted session found for this agentId",agentId:e});return}let s=!1;if(r.mode==="sdk"&&(s=!!await A(e),!s&&r.pid&&(s=b(r.pid))),!s){u.info(`[takeover-session] Process not alive for agentId=${e}, mode=${r.mode}`),t.json({ok:!1,agentId:e,status:"process_not_alive",isActive:!1,message:"Agent process is no longer running"});return}if(u.info(`[takeover-session] Taking over session for agentId=${e}, mode=${r.mode}, pid=${r.pid}`),r.mode==="sdk"){const o=await A(e);o?(u.info(`[takeover-session] Found SDK process for agentId=${e}, pid=${o.pid}`),t.json({ok:!0,agentId:e,sessionId:r.sessionId,mode:"sdk",status:"running",isActive:!0,recovered:!0,pid:o.pid||r.pid,message:"SDK session process found, can be taken over by aws-mcp-server"})):t.json({ok:!1,agentId:e,status:"process_not_alive",isActive:!1,message:"SDK process not found"})}else t.status(410).json({error:"Session takeover is no longer supported; start a new SDK runtime session.",agentId:e,mode:"sdk"})}catch(n){const r=n;u.error("[takeover-session] Error:",r),t.status(500).json({error:r.message})}}),h.post("/terminate-tree",I,async(i,t)=>{const{agentId:e,sessionId:n}=i.body;if(!e){t.status(400).json({error:"agentId is required"});return}try{let r=n;if(!r){const f=await S(e);if(!f){t.status(404).json({error:"Session not found for this agentId"});return}r=f.sessionId}const s=m.get(r);let o,c;if(s)o=y.get(s.providerId||"claude-code").getSessionPid?.(r),c="sdk";else{const f=await S(e);if(!f?.pid){t.status(404).json({error:"Session PID not found"});return}o=f.pid,c=f.mode||"sdk"}const{terminateProcessTree:a,waitForProcessExit:d}=await import("../services/process-detector.js");if(!o){t.status(404).json({error:"PID not found"});return}const l=await a(o),p=await d(o,5e3);E(e),await import("../services/terminal-persistence.js").then(f=>f.removePersistedSession(r)),u.info(`[terminate-tree] Terminated process tree for agentId=${e}, pid=${o}, mode=${c}, terminated=${l.terminated}, failed=${l.failed}, exited=${p}`),t.json({ok:!0,agentId:e,pid:o,mode:c,terminated:l.terminated,failed:l.failed,exited:p,message:p?`Successfully terminated ${l.terminated} processes`:`Terminated ${l.terminated} processes, but process ${o} still running`})}catch(r){const s=r;u.error("[terminate-tree] Error:",s),t.status(500).json({error:s.message})}}),h.get("/health/:agentId",I,async(i,t)=>{const e=i.params.agentId,n=Array.isArray(e)?e[0]:e;if(!n){t.status(400).json({error:"agentId is required"});return}try{const r=await S(n);if(!r){t.status(404).json({error:"Session not found"});return}const s=m.get(r.sessionId),o=!!s,{checkProcessHealth:c}=await import("../services/process-detector.js"),a={sessionId:r.sessionId,mode:r.mode,workspacePath:r.workspacePath,isManaged:o,isActive:!!s};if(r.pid){const d=await c(r.pid,n);Object.assign(a,d)}else Object.assign(a,{pid:0,alive:!1,cpu:0,memoryMB:0,status:"dead",lastUpdate:new Date});t.json({agentId:n,...a})}catch(r){const s=r;u.error("[health] Error:",s),t.status(500).json({error:s.message})}});export{L as handleCapabilityToolCallRequest,x as handleCapabilityToolsRequest,$ as resolveActiveSdkSessionSnapshotStatus,h as sessionsRouter};
|
|
2
2
|
|