aws-runtime-bridge 1.9.150 → 1.9.151
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 +24 -0
- package/dist/index.js +1 -1
- package/dist/routes/lsp.d.ts +6 -0
- package/dist/routes/lsp.js +4 -0
- package/dist/services/lsp-stdio-bridge.d.ts +48 -0
- package/dist/services/lsp-stdio-bridge.js +6 -0
- package/package.json +3 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,30 @@ files 白名单),供调度中心「查看本次更新内容」弹窗按 `##
|
|
|
5
5
|
展示。发布新版本时须在仓库中先写好 `## v<version>` 段(prepack-guard 校验缺段
|
|
6
6
|
即阻断发布);Bridge 自更新成功后的运行时追加仅作为包内缺段时的兜底。
|
|
7
7
|
|
|
8
|
+
## v1.9.151
|
|
9
|
+
|
|
10
|
+
_发布日期:2026-09-07_
|
|
11
|
+
|
|
12
|
+
- 工作区 LSP(TypeScript/JavaScript 语言服务)全链路接入:Dashboard 文件编辑器可对实例工作区的
|
|
13
|
+
TS/TSX/JS/JSX 文件提供语义级定义跳转与引用查找,不再依赖字符串搜索。
|
|
14
|
+
- runtime-bridge:新增 `typescript-language-server` 与 `typescript` 运行时依赖;`src/services/lsp-stdio-bridge.ts`
|
|
15
|
+
封装 LSP stdio 帧编解码(Content-Length 增量解析、畸形流防护)与子进程桥(自动解析 tls 入口、注入
|
|
16
|
+
TSSERVER_PATH 保证 tsserver 可启动);`src/routes/lsp.ts` 暴露 `/ws/lsp` WebSocket——单 workspace 单进程
|
|
17
|
+
复用、60s 空闲回收、复用进程再次收到 initialize 时重建进程(避免 tsserver 沿用旧文档状态陷入
|
|
18
|
+
"No Project"、跳转恒空)。
|
|
19
|
+
- aws-mcp-server:`WorkspaceLspProxyService` 在 HTTP 侧校验 workspace 归属后签发 5 分钟一次性令牌
|
|
20
|
+
(TTL 放宽覆盖慢建连、消费即失效防重放);`WorkspaceLspWebSocketHandler` 把浏览器 `/ws/workspace-lsp/{token}`
|
|
21
|
+
双向转发到 bridge `/ws/lsp`,隧道模式经 BridgeTunnelService 虚拟流、直连模式带 X-Runtime-Token 握手头;
|
|
22
|
+
`FileBrowserProxyService.resolveWorkspaceLspBridge` 解析 bridge 目标(保留隧道实例前缀)与鉴权令牌。
|
|
23
|
+
- aws-dashboard:`workspaceLsp.ts` 封装 CodeMirror LSP 会话——同一 bridge+workspace 仅建立一条 WS 与
|
|
24
|
+
一次 initialize,切换文件仅替换 per-file 句柄(didOpen/didClose),避免重复 initialize 导致跳转失效;
|
|
25
|
+
补充库未内置的 textDocument/references 与 definition 请求、自定义 transport 占位。`WorkspacePanel.vue`
|
|
26
|
+
接入 LSP 扩展、Ctrl+点击/快捷键跳转定义与引用查找;对 Windows 盘符修正 file:// 三层斜杠与 URI 归一比较。
|
|
27
|
+
- 确认弹窗交互调整:确认按钮移至取消按钮左侧并作为默认焦点,Enter 键即触发确认,Tab 焦点循环顺序与
|
|
28
|
+
视觉排布一致(确认左、取消右)。
|
|
29
|
+
- 工作区面板媒体预览:图片 / SVG / 视频预览改为经下载接口生成 object URL 展示,支持 B 站式画面缩放
|
|
30
|
+
(Ctrl+滚轮 / 缩放按钮)与按住空格+拖动平移放大后画面,双击复位;预览状态栏同步显示媒体尺寸与状态。
|
|
31
|
+
|
|
8
32
|
## v1.9.150
|
|
9
33
|
|
|
10
34
|
_发布日期:2026-09-07_
|
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
|
+
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
|
|
2
|
+
export declare function encodeLspStdioFrame(jsonText: string): Buffer;
|
|
3
|
+
|
|
4
|
+
export declare class LspStdioFrameReader {
|
|
5
|
+
private buffer;
|
|
6
|
+
|
|
7
|
+
private headerDone;
|
|
8
|
+
private contentLength;
|
|
9
|
+
|
|
10
|
+
private static readonly MAX_HEADER_BYTES;
|
|
11
|
+
|
|
12
|
+
push(chunk: Buffer): string[];
|
|
13
|
+
reset(): void;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export declare function resolveTypeScriptLanguageServerEntry(): string;
|
|
17
|
+
|
|
18
|
+
export declare function resolveTsserverPath(): string;
|
|
19
|
+
export interface LspProcessBridgeCallbacks {
|
|
20
|
+
|
|
21
|
+
onMessage: (message: unknown) => void;
|
|
22
|
+
|
|
23
|
+
onStderr?: (chunk: string) => void;
|
|
24
|
+
|
|
25
|
+
onExit?: (code: number | null, signal: NodeJS.Signals | null) => void;
|
|
26
|
+
|
|
27
|
+
onError?: (error: Error) => void;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export declare class LspProcessBridge {
|
|
31
|
+
readonly callbacks: LspProcessBridgeCallbacks;
|
|
32
|
+
readonly workspacePath: string;
|
|
33
|
+
readonly language: string;
|
|
34
|
+
private child;
|
|
35
|
+
private readonly reader;
|
|
36
|
+
private disposed;
|
|
37
|
+
constructor(options: {
|
|
38
|
+
workspacePath: string;
|
|
39
|
+
language: string;
|
|
40
|
+
}, callbacks: LspProcessBridgeCallbacks);
|
|
41
|
+
get running(): boolean;
|
|
42
|
+
|
|
43
|
+
start(): void;
|
|
44
|
+
|
|
45
|
+
send(message: unknown): void;
|
|
46
|
+
|
|
47
|
+
dispose(): void;
|
|
48
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import{spawn as f}from"node:child_process";import d from"node:fs";import{createRequire as p}from"node:module";import c from"node:path";import{createLogger as u}from"../utils/logger.js";const i=u("lsp-stdio-bridge"),l=p(import.meta.url);function g(n){const e=Buffer.from(n,"utf8"),t=`Content-Length: ${e.length}\r
|
|
2
|
+
\r
|
|
3
|
+
`;return Buffer.concat([Buffer.from(t,"ascii"),e])}class a{constructor(){this.buffer=Buffer.alloc(0),this.headerDone=!1,this.contentLength=0}push(e){this.buffer=this.buffer.length===0?e:Buffer.concat([this.buffer,e]);const t=[];for(;;){if(!this.headerDone){const s=this.buffer.indexOf(`\r
|
|
4
|
+
\r
|
|
5
|
+
`);if(s===-1){if(this.buffer.length>a.MAX_HEADER_BYTES)throw new Error(`lsp stdio: header too large (${this.buffer.length} bytes), stream is malformed`);break}const o=this.buffer.subarray(0,s).toString("ascii"),h=/^Content-Length:\s*(\d+)/i.exec(o);if(!h)throw new Error(`lsp stdio: invalid header: ${o.slice(0,120)}`);if(this.contentLength=parseInt(h[1],10),this.contentLength<0||this.contentLength>512*1024*1024)throw new Error(`lsp stdio: implausible content length ${this.contentLength}`);this.buffer=this.buffer.subarray(s+4),this.headerDone=!0}if(this.buffer.length<this.contentLength)break;const r=this.buffer.subarray(0,this.contentLength).toString("utf8");this.buffer=this.buffer.subarray(this.contentLength),this.headerDone=!1,this.contentLength=0,t.push(r)}return t}reset(){this.buffer=Buffer.alloc(0),this.headerDone=!1,this.contentLength=0}}a.MAX_HEADER_BYTES=64*1024;function b(){const n=l.resolve("typescript-language-server/package.json"),e=JSON.parse(d.readFileSync(n,"utf8"));if(!e.bin)throw new Error("typescript-language-server package.json has no bin entry");const t=typeof e.bin=="string"?e.bin:Object.values(e.bin)[0];return c.join(c.dirname(n),t)}function m(){return l.resolve("typescript/lib/tsserver.js")}class L{constructor(e,t){this.callbacks=t,this.child=null,this.reader=new a,this.disposed=!1,this.workspacePath=e.workspacePath,this.language=e.language}get running(){return this.child!==null&&this.child.exitCode===null&&this.child.signalCode===null}start(){if(this.disposed)return;let e;try{e=b()}catch(t){i.warn(`[lsp-stdio] \u89E3\u6790 typescript-language-server \u5165\u53E3\u5931\u8D25: ${t.message}`),this.callbacks.onError?.(t);return}try{const t=f(process.execPath,[e,"--stdio"],{cwd:this.workspacePath,env:{...process.env,TSSERVER_PATH:m()},stdio:["pipe","pipe","pipe"]});this.child=t,t.on("error",r=>{i.warn(`[lsp-stdio] \u8BED\u8A00\u670D\u52A1\u8FDB\u7A0B error: ${r.message}`),this.callbacks.onError?.(r)}),t.on("exit",(r,s)=>{this.child===t&&(this.child=null),i.info(`[lsp-stdio] \u8BED\u8A00\u670D\u52A1\u8FDB\u7A0B\u9000\u51FA: code=${r}, signal=${String(s)}`),this.callbacks.onExit?.(r,s)}),t.stdout?.on("data",r=>{if(!this.disposed)try{for(const s of this.reader.push(r))try{this.callbacks.onMessage(JSON.parse(s))}catch(o){i.warn(`[lsp-stdio] \u65E0\u6CD5\u89E3\u6790 server \u6D88\u606F: ${s.slice(0,200)} err=${o.message}`)}}catch(s){i.warn(`[lsp-stdio] \u89E3\u6790 server \u8F93\u51FA\u5931\u8D25: ${s.message}`),this.callbacks.onError?.(s)}}),t.stderr?.on("data",r=>{this.disposed||this.callbacks.onStderr?.(r.toString("utf8"))}),i.info(`[lsp-stdio] \u8BED\u8A00\u670D\u52A1\u8FDB\u7A0B\u5DF2\u542F\u52A8 workspace=${this.workspacePath} pid=${t.pid}`)}catch(t){i.warn(`[lsp-stdio] \u542F\u52A8\u8BED\u8A00\u670D\u52A1\u8FDB\u7A0B\u5931\u8D25: ${t.message}`),this.callbacks.onError?.(t)}}send(e){const t=this.child;if(!t||!t.stdin?.writable){i.warn("[lsp-stdio] \u8FDB\u7A0B\u672A\u5C31\u7EEA\uFF0C\u4E22\u5F03\u6D88\u606F");return}t.stdin.write(g(JSON.stringify(e)))}dispose(){if(this.disposed)return;this.disposed=!0;const e=this.child;this.child=null,this.reader.reset(),e&&e.exitCode===null&&e.signalCode===null&&(i.info(`[lsp-stdio] \u7EC8\u6B62\u8BED\u8A00\u670D\u52A1\u8FDB\u7A0B pid=${e.pid}`),e.kill())}}export{L as LspProcessBridge,a as LspStdioFrameReader,g as encodeLspStdioFrame,m as resolveTsserverPath,b as resolveTypeScriptLanguageServerEntry};
|
|
6
|
+
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aws-runtime-bridge",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.151",
|
|
4
4
|
"description": "AgentsWorkStudio runtime bridge service for machine-level agent runtime integration",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -74,6 +74,8 @@
|
|
|
74
74
|
"node-screenshots": "^0.2.8",
|
|
75
75
|
"playwright": "^1.62.0",
|
|
76
76
|
"tar": "^7.5.15",
|
|
77
|
+
"typescript": "^5.9.3",
|
|
78
|
+
"typescript-language-server": "^4.3.4",
|
|
77
79
|
"unzipper": "^0.12.3",
|
|
78
80
|
"uuid": "^11.0.3",
|
|
79
81
|
"web-tree-sitter": "^0.25.4",
|