aws-runtime-bridge 1.9.172 → 1.9.175

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.
Files changed (65) hide show
  1. package/CHANGELOG.md +126 -0
  2. package/dist/adapter/AcodeSdkAdapter.d.ts +5 -1
  3. package/dist/adapter/AcodeSdkAdapter.js +3 -3
  4. package/dist/adapter/types.d.ts +2 -0
  5. package/dist/index.js +1 -1
  6. package/dist/routes/bridge-temp-files.d.ts +1 -0
  7. package/dist/routes/bridge-temp-files.js +2 -0
  8. package/dist/routes/dashboard.js +35 -5
  9. package/dist/routes/file-browser.d.ts +4 -10
  10. package/dist/routes/file-browser.js +1 -1
  11. package/dist/routes/git.d.ts +42 -0
  12. package/dist/routes/git.js +34 -34
  13. package/dist/routes/sessions.js +1 -1
  14. package/dist/routes/tech-stack.d.ts +2 -0
  15. package/dist/routes/tech-stack.js +2 -0
  16. package/dist/routes/terminal.js +19 -19
  17. package/dist/services/agent-pty-manager.d.ts +2 -0
  18. package/dist/services/agent-pty-manager.js +5 -4
  19. package/dist/services/agent-startup-memory.js +4 -4
  20. package/dist/services/bridge-temp-files.d.ts +36 -0
  21. package/dist/services/bridge-temp-files.js +2 -0
  22. package/dist/services/fileSnapshotStore.d.ts +9 -0
  23. package/dist/services/fileSnapshotStore.js +1 -1
  24. package/dist/services/gitignore.d.ts +12 -0
  25. package/dist/services/gitignore.js +2 -0
  26. package/dist/services/log-retention.js +1 -1
  27. package/dist/services/open-doc-events.d.ts +21 -0
  28. package/dist/services/open-doc-events.js +2 -0
  29. package/dist/services/open-doc-registry.d.ts +24 -0
  30. package/dist/services/open-doc-registry.js +2 -0
  31. package/dist/services/request-invalid-dump.js +1 -1
  32. package/dist/services/runtime-resources-snapshot.js +2 -2
  33. package/dist/services/snapshot-retention.d.ts +7 -0
  34. package/dist/services/snapshot-retention.js +2 -0
  35. package/dist/services/tech-stack-scanner.d.ts +31 -0
  36. package/dist/services/tech-stack-scanner.js +2 -0
  37. package/dist/services/tunnel-client.d.ts +42 -0
  38. package/dist/services/tunnel-client.js +1 -1
  39. package/dist/services/workspaceTaskChangeWatcher.js +2 -2
  40. package/package/acode/dist/__tests__/summary-request-helper.d.ts +2 -0
  41. package/package/acode/dist/__tests__/summary-request-helper.js +2 -0
  42. package/package/acode/dist/cache-control.d.ts +26 -0
  43. package/package/acode/dist/cache-control.js +2 -0
  44. package/package/acode/dist/compaction.d.ts +35 -5
  45. package/package/acode/dist/compaction.js +19 -17
  46. package/package/acode/dist/microcompact.d.ts +57 -0
  47. package/package/acode/dist/microcompact.js +2 -0
  48. package/package/acode/dist/runtime.d.ts +4 -0
  49. package/package/acode/dist/runtime.js +40 -33
  50. package/package/acode/dist/token-estimator.d.ts +15 -0
  51. package/package/acode/dist/token-estimator.js +2 -0
  52. package/package/acode/dist/types.d.ts +13 -0
  53. package/package/aws-client-agent-mcp/dist/ability-market-tools.js +1 -1
  54. package/package/aws-client-agent-mcp/dist/agent-client.d.ts +15 -2
  55. package/package/aws-client-agent-mcp/dist/agent-client.js +1 -1
  56. package/package/aws-client-agent-mcp/dist/mcp-server.d.ts +5 -0
  57. package/package/aws-client-agent-mcp/dist/mcp-server.js +25 -23
  58. package/package/aws-client-agent-mcp/dist/mcp-tools.js +7 -7
  59. package/package/aws-client-agent-mcp/dist/memory-store.d.ts +21 -2
  60. package/package/aws-client-agent-mcp/dist/memory-store.js +27 -2
  61. package/package/aws-client-agent-mcp/dist/memory-tools.js +13 -9
  62. package/package/aws-client-agent-mcp/dist/server-memory-store.d.ts +1 -1
  63. package/package/aws-client-agent-mcp/dist/server-memory-store.js +1 -1
  64. package/package/aws-client-agent-mcp/dist/types.d.ts +51 -0
  65. package/package.json +1 -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 L,getActiveBridgeHttpPort as y,getAutoRegisterConfigFilePath as O,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{agentStateRouter as J}from"./routes/agent-state.js";import{aiSourcesRouter as Y}from"./routes/ai-sources.js";import{backgroundTasksRouter as Z}from"./routes/background-tasks.js";import{browserListenersRouter as q}from"./routes/browser-listeners.js";import{browserSessionsRouter as Q}from"./routes/browser-sessions.js";import{capabilitiesRouter as V}from"./routes/capabilities.js";import{computerRouter as X}from"./routes/computer.js";import{dashboardRouter as ee}from"./routes/dashboard.js";import{eventsRouter as re}from"./routes/events.js";import{fileBrowserRouter as te}from"./routes/file-browser.js";import{fileChangeDiffRouter as ie}from"./routes/file-change-diff.js";import{fileDiffRollbackRouter as oe}from"./routes/file-diff-rollback.js";import{fileSnapshotRouter as ne}from"./routes/file-snapshot.js";import{gitRouter as se}from"./routes/git.js";import{instanceRouter as ae,setGracefulShutdownFn as me}from"./routes/instance.js";import{jdksRouter as ue}from"./routes/jdks.js";import{launchRouter as ce}from"./routes/launch.js";import{attachLspWebSocketServer as de}from"./routes/lsp.js";import{ltrRouter as ge}from"./routes/ltr.js";import{debugMountRouter as pe}from"./routes/debug-mount.js";import{mcpExtraRouter as fe}from"./routes/mcp-extra.js";import{mcpRouter as le}from"./routes/mcp.js";import{pluginsRouter as be}from"./routes/plugins.js";import{processesRouter as he}from"./routes/processes.js";import{propertiesRouter as we}from"./routes/properties.js";import{attachPtyWebSocketServer as Re,closeAllPtySessions as Se,ptyRouter as Pe,ptySessions as ye}from"./routes/pty.js";import{runtimeBindingRouter as Ie,logRuntimeBindingStartupState as $e}from"./routes/runtime-binding.js";import{sessionsRouter as ke}from"./routes/sessions.js";import{skillsRouter as Ae}from"./routes/skills.js";import{subAgentsRouter as Ce}from"./routes/sub-agents.js";import{systemMetricsRouter as ve}from"./routes/system-metrics.js";import{taskContextRouter as Be}from"./routes/task-context.js";import{terminalRouter as Te,sdkSessions as w}from"./routes/terminal.js";import{ymlRouter as De}from"./routes/yml.js";import{accessControlMiddleware as Me}from"./services/access-control.js";import{ensureAcodePackageReleased as Ee,getReleasedAcodeEntryPath as xe}from"./services/acode-package.js";import{getAgentProcessManager as I}from"./services/agent-process-manager.js";import{autoRegister as Fe,unregister as Ge,bridgeRestartCleanup as Le,cancelBackgroundRegisterRetries as Oe}from"./services/auto-register.js";import{ensureAwsClientAgentMcpReleased as _e}from"./services/aws-client-agent-mcp.js";import{disposeBrowserSessionManager as je}from"./services/browser-session-manager.js";import{handleCliCommand as Ke}from"./services/cli-commands.js";import{disposeDesktopMcpManager as Ne}from"./services/desktop-mcp-manager.js";import{getLaunchManager as We}from"./services/launch-manager.js";import{migrateOldPathsOnStartup as He}from"./services/legacy-path-migration.js";import{deliverPendingBridgeLifecycleNotifications as Ue}from"./services/lifecycle-state.js";import{startOrphanMonitor as ze,stopOrphanMonitor as Je}from"./services/orphan-monitor.js";import{pluginManager as Ye}from"./services/plugin-manager.js";import{detectOrphanProcesses as Ze}from"./services/process-detector.js";import{buildGracefulShutdownPlan as qe,shouldCleanupPersistedSessionsOnStartup as Qe}from"./services/runtime-lifecycle-policy.js";import{ensureStartupConfig as Ve}from"./services/startup-config-wizard.js";import{subAgentStore as Xe}from"./services/sub-agent-manager-instance.js";import{startLogRetention as er}from"./services/log-retention.js";import{loadPersistedSessions as $,savePersistedSessions as k}from"./services/terminal-persistence.js";import{stopTunnelClient as rr}from"./services/tunnel-client.js";import{logger as e}from"./utils/logger.js";const A=await Ke();A.handled&&process.exit(A.exitCode),await Ve(),W(),_e(),Ee(),He(),$e(),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): ${L()}`),e.info(`[runtime-bridge] Bridge \u6570\u636E\u76EE\u5F55: ${_()}`),e.info(`[runtime-bridge] \u6A21\u677F\u914D\u7F6E: ${K()}`);async function tr(){try{if(await Fe())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 ${O()}`))}}catch(r){const o=r;e.warn("[runtime-bridge] \u81EA\u52A8\u6CE8\u518C\u51FA\u9519:",o.message)}}tr().then(()=>ir()).then(()=>Ue()).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 ir(){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 Le();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 or(){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)}}or().catch(r=>{e.warn("[runtime-bridge] \u8FDB\u7A0B\u6CE8\u518C\u8868\u91CD\u5EFA\u5931\u8D25:",r)}),import(E(S.join(xe(),"..","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 nr(){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(!Qe(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)}}nr().catch(r=>{e.warn("[runtime-bridge] \u5B64\u513F\u8FDB\u7A0B\u68C0\u6D4B\u51FA\u9519:",r)}),ze().catch(r=>{e.warn("[runtime-bridge] \u542F\u52A8\u5B64\u513F\u8FDB\u7A0B\u76D1\u63A7\u5931\u8D25:",r)});const i=P();i.use(Me),i.use(x()),i.use(P.json({limit:"1mb"})),i.use("/runtime",Ie),i.use("/runtime",we),i.use("/runtime",De),i.use("/runtime",ae),i.use("/runtime",Ae),i.use("/runtime",le),i.use("/runtime",V),i.use("/runtime",Te),i.use("/runtime",ke),i.use("/runtime",he),i.use("/runtime",ce),i.use("/runtime",ue),i.use("/runtime",ve),i.use("/runtime",re),i.use("/runtime",se),i.use("/runtime",ne),i.use("/runtime",z),i.use("/runtime",J),i.use("/runtime",Z),i.use("/runtime",Ce),i.use("/runtime",Q),i.use("/runtime",q),i.use("/runtime",be),i.use("/runtime",fe),i.use("/runtime",pe),i.use("/runtime",Y),i.use("/runtime",Be),i.use("/runtime",oe),i.use("/runtime",ie),i.use("/runtime/computer",X),i.use("/pty",Pe),i.use("/",ee),i.use("/api/file-browser",te),i.use("/api/ltr",ge);function sr(){const r=y(),o=i.listen(r,()=>{e.info(`[runtime-bridge] listening on ${r}`)});return Re(o),U(o),G(o),de(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=qe(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=ye.size;u.closePtySessions?(e.info(`[runtime-bridge] \u6B63\u5728\u505C\u6B62 ${l} \u4E2A PTY \u4F1A\u8BDD...`),Se("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 We().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(Je(),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 Ge()}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(Oe(),u.stopTunnelClient&&(e.info("[runtime-bridge] \u6B63\u5728\u5173\u95ED\u96A7\u9053\u5BA2\u6237\u7AEF..."),rr()),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 je(),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 Ne(),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 Ye.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)}}Xe.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=sr();er();const 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}me(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 B,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 L,getActiveBridgeHttpPort as y,getAutoRegisterConfigFilePath as O,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{agentStateRouter as J}from"./routes/agent-state.js";import{aiSourcesRouter as Y}from"./routes/ai-sources.js";import{backgroundTasksRouter as Z}from"./routes/background-tasks.js";import{bridgeTempFilesRouter as q}from"./routes/bridge-temp-files.js";import{browserListenersRouter as Q}from"./routes/browser-listeners.js";import{browserSessionsRouter as V}from"./routes/browser-sessions.js";import{capabilitiesRouter as X}from"./routes/capabilities.js";import{computerRouter as ee}from"./routes/computer.js";import{dashboardRouter as re}from"./routes/dashboard.js";import{debugMountRouter as te}from"./routes/debug-mount.js";import{eventsRouter as ie}from"./routes/events.js";import{fileBrowserRouter as oe}from"./routes/file-browser.js";import{fileChangeDiffRouter as ne}from"./routes/file-change-diff.js";import{fileDiffRollbackRouter as se}from"./routes/file-diff-rollback.js";import{fileSnapshotRouter as ae}from"./routes/file-snapshot.js";import{gitRouter as me}from"./routes/git.js";import{instanceRouter as ue,setGracefulShutdownFn as ce}from"./routes/instance.js";import{jdksRouter as de}from"./routes/jdks.js";import{launchRouter as ge}from"./routes/launch.js";import{attachLspWebSocketServer as pe}from"./routes/lsp.js";import{ltrRouter as fe}from"./routes/ltr.js";import{mcpExtraRouter as le}from"./routes/mcp-extra.js";import{mcpRouter as be}from"./routes/mcp.js";import{pluginsRouter as he}from"./routes/plugins.js";import{processesRouter as we}from"./routes/processes.js";import{propertiesRouter as Re}from"./routes/properties.js";import{attachPtyWebSocketServer as Se,closeAllPtySessions as Pe,ptyRouter as ye,ptySessions as Ie}from"./routes/pty.js";import{runtimeBindingRouter as $e,logRuntimeBindingStartupState as ke}from"./routes/runtime-binding.js";import{sessionsRouter as Ae}from"./routes/sessions.js";import{skillsRouter as Ce}from"./routes/skills.js";import{subAgentsRouter as ve}from"./routes/sub-agents.js";import{systemMetricsRouter as Te}from"./routes/system-metrics.js";import{taskContextRouter as Be}from"./routes/task-context.js";import{techStackRouter as De}from"./routes/tech-stack.js";import{terminalRouter as Me,sdkSessions as w}from"./routes/terminal.js";import{ymlRouter as Ee}from"./routes/yml.js";import{accessControlMiddleware as xe}from"./services/access-control.js";import{ensureAcodePackageReleased as Fe,getReleasedAcodeEntryPath as Ge}from"./services/acode-package.js";import{getAgentProcessManager as I}from"./services/agent-process-manager.js";import{autoRegister as Le,unregister as Oe,bridgeRestartCleanup as _e,cancelBackgroundRegisterRetries as je}from"./services/auto-register.js";import{ensureAwsClientAgentMcpReleased as Ke}from"./services/aws-client-agent-mcp.js";import{disposeBrowserSessionManager as Ne}from"./services/browser-session-manager.js";import{handleCliCommand as We}from"./services/cli-commands.js";import{disposeDesktopMcpManager as He}from"./services/desktop-mcp-manager.js";import{getLaunchManager as Ue}from"./services/launch-manager.js";import{migrateOldPathsOnStartup as ze}from"./services/legacy-path-migration.js";import{deliverPendingBridgeLifecycleNotifications as Je}from"./services/lifecycle-state.js";import{startLogRetention as Ye}from"./services/log-retention.js";import{startOrphanMonitor as Ze,stopOrphanMonitor as qe}from"./services/orphan-monitor.js";import{pluginManager as Qe}from"./services/plugin-manager.js";import{detectOrphanProcesses as Ve}from"./services/process-detector.js";import{buildGracefulShutdownPlan as Xe,shouldCleanupPersistedSessionsOnStartup as er}from"./services/runtime-lifecycle-policy.js";import{ensureStartupConfig as rr}from"./services/startup-config-wizard.js";import{subAgentStore as tr}from"./services/sub-agent-manager-instance.js";import{loadPersistedSessions as $,savePersistedSessions as k}from"./services/terminal-persistence.js";import{stopTunnelClient as ir}from"./services/tunnel-client.js";import{logger as e}from"./utils/logger.js";const A=await We();A.handled&&process.exit(A.exitCode),await rr(),W(),Ke(),Fe(),ze(),ke(),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): ${L()}`),e.info(`[runtime-bridge] Bridge \u6570\u636E\u76EE\u5F55: ${_()}`),e.info(`[runtime-bridge] \u6A21\u677F\u914D\u7F6E: ${K()}`);async function or(){try{if(await Le())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 ${O()}`))}}catch(r){const o=r;e.warn("[runtime-bridge] \u81EA\u52A8\u6CE8\u518C\u51FA\u9519:",o.message)}}or().then(()=>nr()).then(()=>Je()).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 nr(){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 _e();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 sr(){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)}}sr().catch(r=>{e.warn("[runtime-bridge] \u8FDB\u7A0B\u6CE8\u518C\u8868\u91CD\u5EFA\u5931\u8D25:",r)}),import(E(S.join(Ge(),"..","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 ar(){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(!er(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 Ve(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)}}ar().catch(r=>{e.warn("[runtime-bridge] \u5B64\u513F\u8FDB\u7A0B\u68C0\u6D4B\u51FA\u9519:",r)}),Ze().catch(r=>{e.warn("[runtime-bridge] \u542F\u52A8\u5B64\u513F\u8FDB\u7A0B\u76D1\u63A7\u5931\u8D25:",r)});const i=P();i.use(xe),i.use(x()),i.use(P.json({limit:"1mb"})),i.use("/runtime",$e),i.use("/runtime",Re),i.use("/runtime",Ee),i.use("/runtime",ue),i.use("/runtime",Ce),i.use("/runtime",be),i.use("/runtime",X),i.use("/runtime",Me),i.use("/runtime",Ae),i.use("/runtime",we),i.use("/runtime",ge),i.use("/runtime",de),i.use("/runtime",De),i.use("/runtime",Te),i.use("/runtime",ie),i.use("/runtime",me),i.use("/runtime",ae),i.use("/runtime",z),i.use("/runtime",J),i.use("/runtime",Z),i.use("/runtime",ve),i.use("/runtime",V),i.use("/runtime",Q),i.use("/runtime",he),i.use("/runtime",le),i.use("/runtime",te),i.use("/runtime",Y),i.use("/runtime",Be),i.use("/runtime",se),i.use("/runtime",ne),i.use("/runtime/computer",ee),i.use("/pty",ye),i.use("/",re),i.use("/api/file-browser",oe),i.use("/api/ltr",fe),i.use("/api/bridge-temp-files",q);function mr(){const r=y(),o=i.listen(r,()=>{e.info(`[runtime-bridge] listening on ${r}`)});return Se(o),U(o),G(o),pe(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=Xe(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=Ie.size;u.closePtySessions?(e.info(`[runtime-bridge] \u6B63\u5728\u505C\u6B62 ${l} \u4E2A PTY \u4F1A\u8BDD...`),Pe("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 Ue().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(qe(),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 T=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 ${T.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 Oe()}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(je(),u.stopTunnelClient&&(e.info("[runtime-bridge] \u6B63\u5728\u5173\u95ED\u96A7\u9053\u5BA2\u6237\u7AEF..."),ir()),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 Ne(),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 He(),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 Qe.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)}}tr.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=mr();Ye();const v=S.join(M.tmpdir(),"agentswork-runtime-bridge",".preserve-sessions");function R(){try{if(B(v)){const r=D(v,"utf-8");return JSON.parse(r).preserveSessions===!0}}catch{}return!1}ce(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 @@
1
+ export declare const bridgeTempFilesRouter: import("express-serve-static-core").Router;
@@ -0,0 +1,2 @@
1
+ import{promises as d}from"node:fs";import m from"node:os";import p from"node:path";import{Router as f}from"express";import c from"multer";import{validateToken as n}from"../middleware/auth.js";import{BRIDGE_TEMP_MAX_BYTES as u,deleteBridgeTempFile as g,guessTempFileMediaType as y,readBridgeTempFile as h,writeBridgeTempFile as j}from"../services/bridge-temp-files.js";import{createLogger as b}from"../utils/logger.js";const a=b("bridge-temp-files"),l=f(),T=c({dest:p.join(m.tmpdir(),"agentswork-runtime-bridge-uploads"),limits:{files:1,fileSize:u}});async function w(o=[]){await Promise.all(o.map(async e=>{try{await d.rm(e.path,{force:!0})}catch{}}))}l.post("/upload",n,(o,e,r)=>{T.single("file")(o,e,t=>{if(t){const i=t;a.error("[bridge-temp-files] upload rejected:",i),e.status(400).json({error:i?.message||"upload failed",code:i?.code});return}r()})},async(o,e)=>{const r=o.files||[],t=o.file;try{if(!t){e.status(400).json({error:"file is required"});return}const i=await d.readFile(t.path),s=await j({originalName:t.originalname,bytes:i,mediaType:t.mimetype});e.json(s)}catch(i){const s=i;a.error("[bridge-temp-files] upload failed:",s),e.status(400).json({error:s.message})}finally{await w(r)}}),l.post("/read",n,async(o,e)=>{try{const{path:r}=o.body||{};if(!r||typeof r!="string"||!r.trim()){e.status(400).json({error:"path is required"});return}const t=await h(r.trim());if(!t){e.status(404).json({error:"temp file not found"});return}e.setHeader("Content-Type",y(r)),e.setHeader("Content-Length",String(t.length)),e.send(t)}catch(r){const t=r;a.error("[bridge-temp-files] read failed:",t),e.status(500).json({error:t.message})}}),l.post("/delete",n,async(o,e)=>{try{const{path:r}=o.body||{};if(!r||typeof r!="string"||!r.trim()){e.status(400).json({error:"path is required"});return}const t=await g(r.trim());e.json({ok:!0,deleted:t})}catch(r){const t=r;a.error("[bridge-temp-files] delete failed:",t),e.status(500).json({error:t.message})}});export{l as bridgeTempFilesRouter};
2
+
@@ -1035,6 +1035,16 @@ function t(k) {
1035
1035
  return ((_a = T[lang]) === null || _a === void 0 ? void 0 : _a[k]) || T.zh[k] || k;
1036
1036
  }
1037
1037
 
1038
+ // \u6309\u9762\u677F\u5F53\u524D\u8BED\u8A00\u683C\u5F0F\u5316\u65F6\u95F4\u3002
1039
+ // \u4E0D\u80FD\u76F4\u63A5\u7528 toLocaleString()\uFF08\u4E0D\u4F20\u53C2\u6570\uFF09\uFF1A\u90A3\u4F1A\u53D6\u6D4F\u89C8\u5668/OS \u7684\u8BED\u8A00\uFF0C\u4E0E\u9762\u677F\u81EA\u5DF1\u7684
1040
+ // \u4E2D\u82F1\u5207\u6362\u6309\u94AE\uFF08lang\uFF09\u8131\u8282\u2014\u2014\u7528\u6237\u5207\u5230 English \u540E\uFF0C\u65E5\u671F\u4ECD\u6309\u7CFB\u7EDF\u8BED\u8A00\u6E32\u67D3\uFF0C\u4E2D\u82F1\u5939\u6742\u3002
1041
+ function fmtTime(value) {
1042
+ var _a;
1043
+ var date = value ? new Date(value) : null;
1044
+ if (!date || isNaN(date.getTime())) return "-";
1045
+ return date.toLocaleString(lang === "en" ? "en-US" : "zh-CN", { hour12: false });
1046
+ }
1047
+
1038
1048
  function toggleLang() {
1039
1049
  lang = lang === "zh" ? "en" : "zh";
1040
1050
  localStorage.setItem("dashboard-lang", lang);
@@ -1082,7 +1092,20 @@ function escHtml(s) {
1082
1092
  }
1083
1093
  function fmtShortDate(iso) {
1084
1094
  if (!iso) return "-";
1085
- return iso.slice(0, 19).replace("T", " ");
1095
+ // \u4E0D\u80FD\u76F4\u63A5\u5207\u5B57\u7B26\u4E32\uFF1A\u90A3\u6837\u663E\u793A\u7684\u662F UTC \u6302\u949F\u503C\uFF08\u5982 2026-08-18 04:35:45\uFF09\uFF0C
1096
+ // \u4E0E\u6D4F\u89C8\u5668\u6240\u5728\u65F6\u533A\u7684\u672C\u5730\u65F6\u95F4\u76F8\u5DEE\u4E00\u4E2A\u504F\u79FB\u3002\u8FD9\u91CC\u8F6C\u6210 Date \u518D\u6309\u672C\u5730\u65F6\u533A\u6E32\u67D3\uFF0C
1097
+ // \u8BA9\u9762\u677F\u663E\u793A\u7684\u523B\u4E0E\u7528\u6237\u5B9E\u9645\u611F\u77E5\u7684\u4E00\u81F4\u3002
1098
+ var date = new Date(iso);
1099
+ if (isNaN(date.getTime())) return String(iso).slice(0, 19).replace("T", " ");
1100
+ return date.toLocaleString(lang === "en" ? "en-US" : "zh-CN", {
1101
+ year: "numeric",
1102
+ month: "2-digit",
1103
+ day: "2-digit",
1104
+ hour: "2-digit",
1105
+ minute: "2-digit",
1106
+ second: "2-digit",
1107
+ hour12: false,
1108
+ });
1086
1109
  }
1087
1110
  function fmtShortPath(p) {
1088
1111
  if (!p) return "-";
@@ -1120,7 +1143,7 @@ function barColor(pct) {
1120
1143
  // \u2500\u2500 \u6E32\u67D3 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
1121
1144
  function render(data) {
1122
1145
  lastData = data;
1123
- document.getElementById("refreshTime").textContent = new Date(data.collectedAt).toLocaleString();
1146
+ document.getElementById("refreshTime").textContent = fmtTime(data.collectedAt);
1124
1147
  document.getElementById("bridgeHostname").textContent = data.bridge?.hostname || "-";
1125
1148
  document.getElementById("bridgeVersion").textContent = "v" + (data.bridge?.version || "-");
1126
1149
  document.getElementById("langBtn").textContent = t("langName");
@@ -1151,7 +1174,7 @@ function render(data) {
1151
1174
  { title: t("cardRegistration"), items: [
1152
1175
  [t("fldStatus"), '<span class="' + statusClass(r.registered) + '">' + (r.registered ? t("stRegistered") : t("stNotRegistered")) + "</span>"],
1153
1176
  [t("fldInstanceId"), r.instanceId || "-"],
1154
- [t("fldLastAttempt"), r.lastAttempt ? new Date(r.lastAttempt).toLocaleString() : "-"],
1177
+ [t("fldLastAttempt"), fmtTime(r.lastAttempt)],
1155
1178
  [t("fldError"), r.error ? '<span class="status-red">' + r.error + "</span>" : t("stNone")],
1156
1179
  ]},
1157
1180
  { title: t("cardBinding"), items: [
@@ -1298,7 +1321,7 @@ function render(data) {
1298
1321
  '<tr><td>' + s.agentId + '</td><td>' + (s.status || "stopped") + '</td>'
1299
1322
  + '<td title="' + s.workspacePath + '">' + (s.workspacePath ? s.workspacePath.replace(/\\\\/g, "/").split("/").pop() : "-") + '</td>'
1300
1323
  + '<td>' + (s.command || "-") + '</td>'
1301
- + '<td>' + (s.startedAt ? new Date(s.startedAt).toLocaleString() : "-") + '</td></tr>'
1324
+ + '<td>' + fmtTime(s.startedAt) + '</td></tr>'
1302
1325
  ).join("") +
1303
1326
  '</tbody></table>';
1304
1327
  }
@@ -1345,12 +1368,16 @@ const UPDATE_LABELS = {
1345
1368
  label_installing: "\u5B89\u88C5\u4E2D...",
1346
1369
  label_restart: "\u91CD\u542F",
1347
1370
  label_failed: "\u66F4\u65B0\u5931\u8D25",
1371
+ confirm_title: "\u786E\u8BA4\u66F4\u65B0\u5E76\u91CD\u542F Bridge",
1372
+ confirm_message: "\u66F4\u65B0\u540E\u5C06\u91CD\u65B0\u542F\u52A8\u5B9E\u4F8B Bridge\uFF0C\u6B63\u5728\u8FD0\u884C\u7684 agent \u5B9E\u4F8B\u4F1A\u505C\u6B62\uFF0C\u8FDB\u884C\u4E2D\u7684\u4EFB\u52A1\u4F1A\u4E2D\u65AD\u3002\u786E\u8BA4\u73B0\u5728\u66F4\u65B0\uFF1F",
1348
1373
  },
1349
1374
  en: {
1350
1375
  label_available: "\u2192 {v}",
1351
1376
  label_installing: "installing...",
1352
1377
  label_restart: "restart",
1353
1378
  label_failed: "failed",
1379
+ confirm_title: "Confirm update and restart Bridge",
1380
+ confirm_message: "The update will restart the Bridge. Running agent instances will stop and in-progress tasks will be interrupted. Update now?",
1354
1381
  },
1355
1382
  };
1356
1383
 
@@ -1389,6 +1416,9 @@ function showUpdateAvailable(data) {
1389
1416
 
1390
1417
  async function doInstallUpdate() {
1391
1418
  const indicator = document.getElementById("updateIndicator");
1419
+ if (!confirm(ul("confirm_title") + "\\n\\n" + ul("confirm_message"))) {
1420
+ return;
1421
+ }
1392
1422
  updateState.installing = true;
1393
1423
  indicator.className = "update-indicator installing";
1394
1424
  indicator.textContent = ul("label_installing");
@@ -1660,7 +1690,7 @@ function refreshLogs() {
1660
1690
  var html = "";
1661
1691
  for (var i = 0; i < d.logs.length; i++) {
1662
1692
  var e = d.logs[i];
1663
- html += '<div class="s-log-entry"><span class="ts">' + escHtml(e.timestamp.slice(0, 19).replace("T", " ")) + '</span> <span class="ll ' + e.level.toUpperCase() + '">[' + e.level.toUpperCase() + ']</span>';
1693
+ html += '<div class="s-log-entry"><span class="ts">' + escHtml(fmtShortDate(e.timestamp)) + '</span> <span class="ll ' + e.level.toUpperCase() + '">[' + e.level.toUpperCase() + ']</span>';
1664
1694
  if (e.prefix) html += ' [' + escHtml(e.prefix) + ']';
1665
1695
  html += ' ' + escHtml(e.message) + '</div>';
1666
1696
  }
@@ -2,6 +2,8 @@
2
2
  import multer from 'multer';
3
3
  export declare const fileBrowserRouter: import("express-serve-static-core").Router;
4
4
  export declare const WORKSPACE_UPLOAD_FILE_LIMIT = 2000;
5
+
6
+ export declare const WORKSPACE_UPLOAD_MAX_FILE_SIZE_BYTES: number;
5
7
  interface FileBrowserItem {
6
8
  name: string;
7
9
  path: string;
@@ -21,13 +23,6 @@ interface DirectoryTreeResponse extends FileBrowserResponse {
21
23
  maxItemsPerDirectory: number;
22
24
  tree: DirectoryTreeItem[];
23
25
  }
24
- interface GitIgnoreRule {
25
- pattern: string;
26
- negated: boolean;
27
- directoryOnly: boolean;
28
- anchored: boolean;
29
- hasSlash: boolean;
30
- }
31
26
  export declare function createWorkspaceUploadLimitResponse(error: multer.MulterError): {
32
27
  status: number;
33
28
  body: {
@@ -38,6 +33,5 @@ export declare function createWorkspaceUploadLimitResponse(error: multer.MulterE
38
33
  export declare function parseWorkspaceUploadRelativePaths(body: Record<string, unknown>): string[];
39
34
 
40
35
  export declare function listHostDirectoryTree(requestPath?: string): Promise<DirectoryTreeResponse>;
41
- export declare function parseGitIgnoreRules(content: string): GitIgnoreRule[];
42
- export declare function isIgnoredByGitIgnore(relativePath: string, isDirectory: boolean, rules: GitIgnoreRule[]): boolean;
43
- export {};
36
+
37
+ export { isIgnoredByGitIgnore, loadGitIgnoreRules, parseGitIgnoreRules, type GitIgnoreRule, } from '../services/gitignore.js';
@@ -1,2 +1,2 @@
1
- import{createReadStream as S,promises as u}from"node:fs";import x from"node:os";import w from"node:path";import{pipeline as _}from"node:stream/promises";import{Router as v}from"express";import j from"multer";import{allowHostFileBrowser as A}from"../config.js";import{validateToken as c}from"../middleware/auth.js";import{chmodWorkspaceEntry as N,createWorkspaceEntry as C,deleteWorkspaceEntry as z,extractWorkspaceArchive as F,getWorkspaceEntryProperties as B,listWorkspaceDirectory as L,moveWorkspaceEntry as H,previewWorkspaceDocument as M,readWorkspaceFile as O,renameWorkspaceEntry as U,replaceWorkspaceFiles as G,resolveWorkspaceDownloadTarget as $,searchWorkspaceFiles as X,searchWorkspacePaths as q,uploadWorkspaceFiles as J,writeWorkspaceFile as Y,zipWorkspaceDirectoryToTemp as K}from"../services/workspace-files.js";import{unwatchWorkspaceFile as Q,watchWorkspaceFile as V}from"../services/workspace-watch.js";import{createLogger as Z}from"../utils/logger.js";const h=Z("file-browser"),p=v(),g=new Map,tt=6e4,b=2e3,et=j({dest:w.join(x.tmpdir(),"agentswork-runtime-bridge-uploads"),limits:{files:b,fileSize:512*1024*1024}}),m=Number.MAX_SAFE_INTEGER,y=Number.MAX_SAFE_INTEGER;function k(a){return a===!0||a==="true"||a==="1"}function rt(a){return`attachment; filename="${a.replace(/[\\"\r\n]/g,"_").replace(/[^\x20-\x7E]/g,"_")}"; filename*=UTF-8''${encodeURIComponent(a)}`}async function at(a=[]){await Promise.all(a.map(e=>u.rm(e.path,{force:!0}).catch(()=>{})))}function ot(a){return{status:400,body:{error:a.code==="LIMIT_FILE_COUNT"?`\u4E00\u6B21\u6700\u591A\u4E0A\u4F20 ${b} \u4E2A\u6587\u4EF6\uFF0C\u8BF7\u62C6\u5206\u6587\u4EF6\u5939\u540E\u91CD\u8BD5\u3002`:a.message,code:a.code}}}function st(a){const e=a.relativePathsJson;if(typeof e=="string"&&e.trim()){const t=JSON.parse(e);if(!Array.isArray(t))throw new Error("relativePathsJson must be an array");return t.map(o=>String(o||""))}const r=a.relativePaths;return Array.isArray(r)?r.map(t=>String(t||"")):typeof r=="string"?[r]:[]}function nt(a,e,r){et.array("files")(a,e,t=>{if(!t){r();return}if(t instanceof j.MulterError){const o=ot(t);e.status(o.status).json(o.body);return}r(t)})}async function P(a=""){const r=process.platform==="win32";if(!a||a===""){if(r){const d=Array.from({length:24},(f,T)=>String.fromCharCode(67+T)+":\\");return{isWindows:!0,currentPath:"",items:(await Promise.all(d.map(async f=>{try{return await u.access(f),{name:f,path:f,isDirectory:!0}}catch{return null}}))).filter(f=>f!==null)}}return{isWindows:!1,currentPath:"/",items:(await u.readdir("/",{withFileTypes:!0})).filter(d=>d.isDirectory()).map(d=>({name:d.name,path:"/"+d.name,isDirectory:!0}))}}const t=w.normalize(a);let o;try{o=await u.stat(t)}catch{throw new Error("Path not found: "+t)}if(!o.isDirectory())throw new Error("Path is not a directory: "+t);const n=(await u.readdir(t,{withFileTypes:!0})).filter(i=>i.isDirectory()).map(i=>({name:i.name,path:w.join(t,i.name),isDirectory:!0}));return{isWindows:r,currentPath:t,items:n}}async function it(a=""){const e=await P(a),r=e.currentPath?await pt(e.currentPath):[];return e.currentPath?{...e,maxDepth:m,maxItemsPerDirectory:y,tree:await D(e.currentPath,e.currentPath,1,r)}:{...e,maxDepth:m,maxItemsPerDirectory:y,tree:e.items.slice(0,y)}}async function D(a,e,r,t){if(r>m)return[];const s=(await u.readdir(e,{withFileTypes:!0})).filter(i=>i.isDirectory()).filter(i=>!dt(a,w.join(e,i.name),t)).sort((i,l)=>i.name.localeCompare(l.name)).slice(0,y),n=[];for(const i of s){const l=w.join(e,i.name),d={name:i.name,path:l.replace(/\\/g,"/"),isDirectory:!0};if(r<m)try{d.children=await D(a,l,r+1,t)}catch{d.children=[]}else d.truncated=!0;n.push(d)}return n}function ct(a){return String(a||"").split(/\r?\n/).map(e=>e.trim()).filter(e=>e&&!e.startsWith("#")).map(e=>{const r=e.startsWith("!"),t=r?e.slice(1).trim():e,o=t.startsWith("/"),s=t.endsWith("/"),n=t.replace(/^\/+/,"").replace(/\/+$/,"").replace(/\\/g,"/");return{pattern:n,negated:r,directoryOnly:s,anchored:o,hasSlash:n.includes("/")}}).filter(e=>e.pattern.length>0)}async function pt(a){const e=[];let r=a;for(;;){try{const o=w.join(r,".gitignore"),s=await u.readFile(o,"utf8"),n=ct(s);e.unshift(...n)}catch{}const t=w.dirname(r);if(t===r)break;r=t}return e}function lt(a,e,r){const t=wt(a);if(!t)return!1;let o=!1;for(const s of r)s.directoryOnly&&!e||ht(t,s)&&(o=!s.negated);return o}function dt(a,e,r){if(r.length===0)return!1;const t=w.relative(a,e).replace(/\\/g,"/");return lt(t,!0,r)}function ht(a,e){if(!e.hasSlash&&!e.anchored)return a.split("/").some(t=>ut(t,e.pattern));const r=e.pattern;return e.anchored?E(a,r)||a.startsWith(r+"/"):E(a,r)||a.endsWith("/"+r)||a.includes("/"+r+"/")}function E(a,e){return new RegExp("^"+W(e)+"(?:/.*)?$").test(a)}function ut(a,e){return new RegExp("^"+W(e)+"$").test(a)}function W(a){return a.replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*\*/g,".*").replace(/\*/g,"[^/]*").replace(/\?/g,"[^/]")}function wt(a){return String(a||"").replace(/\\/g,"/").replace(/^\.\//,"").replace(/^\/+/,"").replace(/\/+$/,"")}async function R(a){const e=w.normalize(String(a||""));if(!(await u.stat(e)).isDirectory())throw new Error("Path is not a directory: "+e);return e}function I(a){const e=String(a||"").trim();if(!e)throw new Error("Folder name is required");if(e.includes("/")||e.includes("\\")||e==="."||e==="..")throw new Error("Folder name must not contain path separators");return e}async function gt(a,e){const r=await R(a),t=I(e),o=w.join(r,t);return await u.mkdir(o),{ok:!0,parentPath:a,targetPath:o.replace(/\\/g,"/"),entryName:t}}async function ft(a,e){const r=await R(a),t=I(e),o=w.join(w.dirname(r),t);return await u.rename(r,o),{ok:!0,sourcePath:r.replace(/\\/g,"/"),targetPath:o.replace(/\\/g,"/"),newName:t}}p.post("/list",c,async(a,e)=>{try{if(!A)return e.status(403).json({error:"Host filesystem browsing is disabled. Use /api/file-browser/workspace/list with a registered workspace, or set AWS_ALLOW_HOST_FILE_BROWSER=true for isolated local debugging."});const{path:r=""}=a.body||{};e.json(await P(String(r||"")))}catch(r){const t=r;e.status(500).json({error:t.message})}}),p.post("/directory-picker/list",c,async(a,e)=>{try{const{path:r=""}=a.body||{};e.json(await P(String(r||"")))}catch(r){const t=r;e.status(400).json({error:t.message})}}),p.post("/directory-picker/tree",c,async(a,e)=>{try{const{path:r=""}=a.body||{};e.json(await it(String(r||"")))}catch(r){const t=r;e.status(400).json({error:t.message})}}),p.post("/workspace/list",c,async(a,e)=>{try{const{workspacePath:r,path:t=""}=a.body||{},o=await L({workspacePath:String(r||""),targetPath:String(t||"")});e.json({isWindows:process.platform==="win32",currentPath:o.currentPath,workspacePath:o.workspacePath,items:o.items})}catch(r){const t=r;console.error("[file-browser] failed to list workspace directory:",t),e.status(400).json({error:t.message})}}),p.post("/workspace/read",c,async(a,e)=>{try{const{workspacePath:r,filePath:t}=a.body||{},o=await O({workspacePath:String(r||""),filePath:String(t||"")});e.json(o)}catch(r){const t=r;console.error("[file-browser] failed to read workspace file:",t),e.status(400).json({error:t.message})}}),p.post("/workspace/properties",c,async(a,e)=>{try{const{workspacePath:r,targetPath:t}=a.body||{};e.json(await B({workspacePath:String(r||""),targetPath:String(t||"")}))}catch(r){const t=r;h.error("failed to get workspace entry properties:",t),e.status(400).json({error:t.message})}}),p.post("/workspace/chmod",c,async(a,e)=>{try{const{workspacePath:r,targetPath:t,mode:o,recursive:s}=a.body||{};e.json(await N({workspacePath:String(r||""),targetPath:String(t||""),mode:String(o||""),recursive:!!s}))}catch(r){const t=r;h.error("failed to chmod workspace entry:",t),e.status(400).json({error:t.message})}}),p.post("/directory-picker/create",c,async(a,e)=>{try{const{path:r="",entryName:t}=a.body||{};e.json(await gt(String(r||""),String(t||"")))}catch(r){const t=r;h.error("failed to create directory from directory picker:",t),e.status(400).json({error:t.message})}}),p.post("/directory-picker/rename",c,async(a,e)=>{try{const{targetPath:r,newName:t}=a.body||{};e.json(await ft(String(r||""),String(t||"")))}catch(r){const t=r;h.error("failed to rename directory from directory picker:",t),e.status(400).json({error:t.message})}}),p.post("/workspace/preview",c,async(a,e)=>{try{const{workspacePath:r,filePath:t}=a.body||{},o=await M({workspacePath:String(r||""),filePath:String(t||"")});e.json(o)}catch(r){const t=r;h.error("failed to preview workspace document:",t),e.status(400).json({error:t.message})}}),p.post("/workspace/watch",c,async(a,e)=>{try{const{workspacePath:r,filePath:t}=a.body||{};e.json(await V({workspacePath:String(r||""),filePath:String(t||"")}))}catch(r){const t=r;h.error("failed to watch workspace file:",t),e.status(400).json({error:t.message})}}),p.post("/workspace/unwatch",c,async(a,e)=>{try{const{workspacePath:r,filePath:t}=a.body||{};e.json(await Q({workspacePath:String(r||""),filePath:String(t||"")}))}catch(r){const t=r;h.error("failed to unwatch workspace file:",t),e.status(400).json({error:t.message})}}),p.post("/workspace/write",c,async(a,e)=>{try{const{workspacePath:r,filePath:t,content:o}=a.body||{},s=await Y({workspacePath:String(r||""),filePath:String(t||""),content:String(o??"")});e.json(s)}catch(r){const t=r;console.error("[file-browser] failed to write workspace file:",t),e.status(400).json({error:t.message})}}),p.post("/workspace/create",c,async(a,e)=>{try{const{workspacePath:r,path:t="",entryName:o,isDirectory:s}=a.body||{},n=await C({workspacePath:String(r||""),targetPath:String(t||""),entryName:String(o||""),isDirectory:!!s});e.json(n)}catch(r){const t=r;h.error("failed to create workspace entry:",t),e.status(400).json({error:t.message})}}),p.post("/workspace/rename",c,async(a,e)=>{try{const{workspacePath:r,targetPath:t,newName:o}=a.body||{},s=await U({workspacePath:String(r||""),targetPath:String(t||""),newName:String(o||"")});e.json(s)}catch(r){const t=r;h.error("failed to rename workspace entry:",t),e.status(400).json({error:t.message})}}),p.post("/workspace/move",c,async(a,e)=>{try{const{workspacePath:r,targetPath:t,destinationPath:o}=a.body||{},s=await H({workspacePath:String(r||""),targetPath:String(t||""),destinationPath:String(o||"")});e.json(s)}catch(r){const t=r;h.error("failed to move workspace entry:",t),e.status(400).json({error:t.message})}}),p.post("/workspace/delete",c,async(a,e)=>{try{const{workspacePath:r,targetPath:t}=a.body||{},o=await z({workspacePath:String(r||""),targetPath:String(t||"")});e.json(o)}catch(r){const t=r;h.error("failed to delete workspace entry:",t),e.status(400).json({error:t.message})}}),p.post("/workspace/upload",c,nt,async(a,e)=>{const r=a.files||[];try{const{workspacePath:t,path:o="",extractArchives:s}=a.body||{},n=st(a.body||{}),i=await J({workspacePath:String(t||""),targetPath:String(o||""),extractArchives:k(s),files:r.map((l,d)=>({originalname:l.originalname,relativePath:n[d],path:l.path,size:l.size}))});e.json(i)}catch(t){const o=t;h.error("failed to upload workspace files:",o),e.status(400).json({error:o.message})}finally{await at(r)}}),p.post("/workspace/download",c,async(a,e)=>{let r;const t=String((a.body||{}).progressId||"").trim();try{const{workspacePath:o,targetPath:s}=a.body||{},n=await $({workspacePath:String(o||""),targetPath:String(s||"")});if(e.setHeader("Content-Type",n.contentType),e.setHeader("Content-Disposition",rt(n.fileName)),e.setHeader("X-Workspace-Path",encodeURIComponent(n.workspacePath)),e.setHeader("X-Workspace-Target-Path",encodeURIComponent(n.targetPath)),n.isDirectory){t&&g.set(t,{zippedBytes:0,totalBytes:null,done:!1,cancelled:!1,updatedAt:Date.now()}),r=await K(n.resolvedTargetPath,n.fileName,l=>{if(!t)return;const d=g.get(t);d&&(d.zippedBytes=l,d.updatedAt=Date.now())},()=>t?!!g.get(t)?.cancelled:!1);const i=await u.stat(r);if(t){const l=g.get(t);l&&(l.zippedBytes=i.size,l.totalBytes=i.size,l.done=!0,l.updatedAt=Date.now())}e.setHeader("Content-Length",String(i.size)),await _(S(r),e);return}n.size!==void 0&&e.setHeader("Content-Length",String(n.size)),S(n.resolvedTargetPath).pipe(e)}catch(o){const s=o;h.error("failed to download workspace entry:",s),e.headersSent?e.destroy(s):e.status(400).json({error:s.message})}finally{if(r&&await u.rm(r,{force:!0}).catch(()=>{}),t){const o=g.get(t);o&&(o.done=!0,o.totalBytes===null&&(o.totalBytes=0)),setTimeout(()=>g.delete(t),tt)}}}),p.post("/workspace/download-progress",c,(a,e)=>{const r=String((a.body||{}).progressId||"").trim();if(!r){e.status(400).json({error:"progressId is required"});return}const t=g.get(r);if(!t){e.status(404).json({error:"download progress not found"});return}e.json({zippedBytes:t.zippedBytes,totalBytes:t.totalBytes,done:t.done,cancelled:t.cancelled})}),p.post("/workspace/download-cancel",c,(a,e)=>{const r=String((a.body||{}).progressId||"").trim();if(!r){e.status(400).json({error:"progressId is required"});return}const t=g.get(r);t&&(t.cancelled=!0,t.done=!0,t.updatedAt=Date.now()),e.json({ok:!0})}),p.post("/workspace/extract",c,async(a,e)=>{try{const{workspacePath:r,archivePath:t,outputPath:o=""}=a.body||{},s=await F({workspacePath:String(r||""),archivePath:String(t||""),outputPath:String(o||"")});e.json(s)}catch(r){const t=r;h.error("failed to extract workspace archive:",t),e.status(400).json({error:t.message})}}),p.post("/workspace/path-search",c,async(a,e)=>{try{const{workspacePath:r,rootPath:t,keyword:o,ignoreCase:s,maxResults:n,maxDirectories:i}=a.body||{},l=await q({workspacePath:String(r||""),rootPath:t!==void 0?String(t):void 0,keyword:String(o||""),ignoreCase:k(s),maxResults:typeof n=="number"?n:void 0,maxDirectories:typeof i=="number"?i:void 0});e.json(l)}catch(r){const t=r;h.error("failed to search workspace paths:",t),e.status(400).json({error:t.message})}}),p.post("/workspace/search",c,async(a,e)=>{try{const{workspacePath:r,keyword:t,fileMask:o,ignoreCase:s,maxResults:n,mode:i}=a.body||{},l=await X({workspacePath:String(r||""),keyword:String(t||""),fileMask:o!==void 0?String(o):void 0,ignoreCase:k(s),maxResults:typeof n=="number"?n:void 0,mode:i==="filename"?"filename":"content"});e.json(l)}catch(r){const t=r;h.error("failed to search workspace files:",t),e.status(400).json({error:t.message})}}),p.post("/workspace/replace",c,async(a,e)=>{try{const{workspacePath:r,keyword:t,replacement:o,fileMask:s,ignoreCase:n,filePath:i}=a.body||{},l=await G({workspacePath:String(r||""),keyword:String(t||""),replacement:String(o??""),fileMask:s!==void 0?String(s):void 0,ignoreCase:k(n),filePath:i!==void 0?String(i):void 0});e.json(l)}catch(r){const t=r;h.error("failed to replace workspace files:",t),e.status(400).json({error:t.message})}});export{b as WORKSPACE_UPLOAD_FILE_LIMIT,ot as createWorkspaceUploadLimitResponse,p as fileBrowserRouter,lt as isIgnoredByGitIgnore,it as listHostDirectoryTree,ct as parseGitIgnoreRules,st as parseWorkspaceUploadRelativePaths};
1
+ import{createReadStream as S,promises as u}from"node:fs";import T from"node:os";import w from"node:path";import{pipeline as W}from"node:stream/promises";import{Router as R}from"express";import j from"multer";import{allowHostFileBrowser as v}from"../config.js";import{validateToken as c}from"../middleware/auth.js";import{isIgnoredByGitIgnore as A,loadGitIgnoreRules as N}from"../services/gitignore.js";import{chmodWorkspaceEntry as C,createWorkspaceEntry as x,deleteWorkspaceEntry as F,extractWorkspaceArchive as B,getWorkspaceEntryProperties as z,listWorkspaceDirectory as L,moveWorkspaceEntry as M,previewWorkspaceDocument as O,readWorkspaceFile as H,renameWorkspaceEntry as U,replaceWorkspaceFiles as G,resolveWorkspaceDownloadTarget as X,searchWorkspaceFiles as Y,searchWorkspacePaths as q,uploadWorkspaceFiles as J,writeWorkspaceFile as $,zipWorkspaceDirectoryToTemp as K}from"../services/workspace-files.js";import{unwatchWorkspaceFile as V,watchWorkspaceFile as Z}from"../services/workspace-watch.js";import{createLogger as Q}from"../utils/logger.js";const h=Q("file-browser"),p=R(),m=new Map,tt=6e4,b=2e3,et=Number.POSITIVE_INFINITY,rt=j({dest:w.join(T.tmpdir(),"agentswork-runtime-bridge-uploads"),limits:{files:b,fileSize:et}}),f=Number.MAX_SAFE_INTEGER,g=Number.MAX_SAFE_INTEGER;function P(o){return o===!0||o==="true"||o==="1"}function ot(o){return`attachment; filename="${o.replace(/[\\"\r\n]/g,"_").replace(/[^\x20-\x7E]/g,"_")}"; filename*=UTF-8''${encodeURIComponent(o)}`}async function at(o=[]){await Promise.all(o.map(e=>u.rm(e.path,{force:!0}).catch(()=>{})))}function st(o){return{status:400,body:{error:o.code==="LIMIT_FILE_COUNT"?`\u4E00\u6B21\u6700\u591A\u4E0A\u4F20 ${b} \u4E2A\u6587\u4EF6\uFF0C\u8BF7\u62C6\u5206\u6587\u4EF6\u5939\u540E\u91CD\u8BD5\u3002`:o.message,code:o.code}}}function nt(o){const e=o.relativePathsJson;if(typeof e=="string"&&e.trim()){const t=JSON.parse(e);if(!Array.isArray(t))throw new Error("relativePathsJson must be an array");return t.map(a=>String(a||""))}const r=o.relativePaths;return Array.isArray(r)?r.map(t=>String(t||"")):typeof r=="string"?[r]:[]}function it(o,e,r){rt.array("files")(o,e,t=>{if(!t){r();return}if(t instanceof j.MulterError){const a=st(t);e.status(a.status).json(a.body);return}r(t)})}async function k(o=""){const r=process.platform==="win32";if(!o||o===""){if(r){const d=Array.from({length:24},(y,_)=>String.fromCharCode(67+_)+":\\");return{isWindows:!0,currentPath:"",items:(await Promise.all(d.map(async y=>{try{return await u.access(y),{name:y,path:y,isDirectory:!0}}catch{return null}}))).filter(y=>y!==null)}}return{isWindows:!1,currentPath:"/",items:(await u.readdir("/",{withFileTypes:!0})).filter(d=>d.isDirectory()).map(d=>({name:d.name,path:"/"+d.name,isDirectory:!0}))}}const t=w.normalize(o);let a;try{a=await u.stat(t)}catch{throw new Error("Path not found: "+t)}if(!a.isDirectory())throw new Error("Path is not a directory: "+t);const i=(await u.readdir(t,{withFileTypes:!0})).filter(n=>n.isDirectory()).map(n=>({name:n.name,path:w.join(t,n.name),isDirectory:!0}));return{isWindows:r,currentPath:t,items:i}}async function ct(o=""){const e=await k(o),r=e.currentPath?await N(e.currentPath):[];return e.currentPath?{...e,maxDepth:f,maxItemsPerDirectory:g,tree:await D(e.currentPath,e.currentPath,1,r)}:{...e,maxDepth:f,maxItemsPerDirectory:g,tree:e.items.slice(0,g)}}async function D(o,e,r,t){if(r>f)return[];const s=(await u.readdir(e,{withFileTypes:!0})).filter(n=>n.isDirectory()).filter(n=>!pt(o,w.join(e,n.name),t)).sort((n,l)=>n.name.localeCompare(l.name)).slice(0,g),i=[];for(const n of s){const l=w.join(e,n.name),d={name:n.name,path:l.replace(/\\/g,"/"),isDirectory:!0};if(r<f)try{d.children=await D(o,l,r+1,t)}catch{d.children=[]}else d.truncated=!0;i.push(d)}return i}import{isIgnoredByGitIgnore as Tt,loadGitIgnoreRules as Wt,parseGitIgnoreRules as Rt}from"../services/gitignore.js";function pt(o,e,r){if(r.length===0)return!1;const t=w.relative(o,e).replace(/\\/g,"/");return A(t,!0,r)}async function E(o){const e=w.normalize(String(o||""));if(!(await u.stat(e)).isDirectory())throw new Error("Path is not a directory: "+e);return e}function I(o){const e=String(o||"").trim();if(!e)throw new Error("Folder name is required");if(e.includes("/")||e.includes("\\")||e==="."||e==="..")throw new Error("Folder name must not contain path separators");return e}async function lt(o,e){const r=await E(o),t=I(e),a=w.join(r,t);return await u.mkdir(a),{ok:!0,parentPath:o,targetPath:a.replace(/\\/g,"/"),entryName:t}}async function dt(o,e){const r=await E(o),t=I(e),a=w.join(w.dirname(r),t);return await u.rename(r,a),{ok:!0,sourcePath:r.replace(/\\/g,"/"),targetPath:a.replace(/\\/g,"/"),newName:t}}p.post("/list",c,async(o,e)=>{try{if(!v)return e.status(403).json({error:"Host filesystem browsing is disabled. Use /api/file-browser/workspace/list with a registered workspace, or set AWS_ALLOW_HOST_FILE_BROWSER=true for isolated local debugging."});const{path:r=""}=o.body||{};e.json(await k(String(r||"")))}catch(r){const t=r;e.status(500).json({error:t.message})}}),p.post("/directory-picker/list",c,async(o,e)=>{try{const{path:r=""}=o.body||{};e.json(await k(String(r||"")))}catch(r){const t=r;e.status(400).json({error:t.message})}}),p.post("/directory-picker/tree",c,async(o,e)=>{try{const{path:r=""}=o.body||{};e.json(await ct(String(r||"")))}catch(r){const t=r;e.status(400).json({error:t.message})}}),p.post("/workspace/list",c,async(o,e)=>{try{const{workspacePath:r,path:t=""}=o.body||{},a=await L({workspacePath:String(r||""),targetPath:String(t||"")});e.json({isWindows:process.platform==="win32",currentPath:a.currentPath,workspacePath:a.workspacePath,items:a.items})}catch(r){const t=r;console.error("[file-browser] failed to list workspace directory:",t),e.status(400).json({error:t.message})}}),p.post("/workspace/read",c,async(o,e)=>{try{const{workspacePath:r,filePath:t}=o.body||{},a=await H({workspacePath:String(r||""),filePath:String(t||"")});e.json(a)}catch(r){const t=r;console.error("[file-browser] failed to read workspace file:",t),e.status(400).json({error:t.message})}}),p.post("/workspace/properties",c,async(o,e)=>{try{const{workspacePath:r,targetPath:t}=o.body||{};e.json(await z({workspacePath:String(r||""),targetPath:String(t||"")}))}catch(r){const t=r;h.error("failed to get workspace entry properties:",t),e.status(400).json({error:t.message})}}),p.post("/workspace/chmod",c,async(o,e)=>{try{const{workspacePath:r,targetPath:t,mode:a,recursive:s}=o.body||{};e.json(await C({workspacePath:String(r||""),targetPath:String(t||""),mode:String(a||""),recursive:!!s}))}catch(r){const t=r;h.error("failed to chmod workspace entry:",t),e.status(400).json({error:t.message})}}),p.post("/directory-picker/create",c,async(o,e)=>{try{const{path:r="",entryName:t}=o.body||{};e.json(await lt(String(r||""),String(t||"")))}catch(r){const t=r;h.error("failed to create directory from directory picker:",t),e.status(400).json({error:t.message})}}),p.post("/directory-picker/rename",c,async(o,e)=>{try{const{targetPath:r,newName:t}=o.body||{};e.json(await dt(String(r||""),String(t||"")))}catch(r){const t=r;h.error("failed to rename directory from directory picker:",t),e.status(400).json({error:t.message})}}),p.post("/workspace/preview",c,async(o,e)=>{try{const{workspacePath:r,filePath:t}=o.body||{},a=await O({workspacePath:String(r||""),filePath:String(t||"")});e.json(a)}catch(r){const t=r;h.error("failed to preview workspace document:",t),e.status(400).json({error:t.message})}}),p.post("/workspace/watch",c,async(o,e)=>{try{const{workspacePath:r,filePath:t}=o.body||{};e.json(await Z({workspacePath:String(r||""),filePath:String(t||"")}))}catch(r){const t=r;h.error("failed to watch workspace file:",t),e.status(400).json({error:t.message})}}),p.post("/workspace/unwatch",c,async(o,e)=>{try{const{workspacePath:r,filePath:t}=o.body||{};e.json(await V({workspacePath:String(r||""),filePath:String(t||"")}))}catch(r){const t=r;h.error("failed to unwatch workspace file:",t),e.status(400).json({error:t.message})}}),p.post("/workspace/write",c,async(o,e)=>{try{const{workspacePath:r,filePath:t,content:a}=o.body||{},s=await $({workspacePath:String(r||""),filePath:String(t||""),content:String(a??"")});e.json(s)}catch(r){const t=r;console.error("[file-browser] failed to write workspace file:",t),e.status(400).json({error:t.message})}}),p.post("/workspace/create",c,async(o,e)=>{try{const{workspacePath:r,path:t="",entryName:a,isDirectory:s}=o.body||{},i=await x({workspacePath:String(r||""),targetPath:String(t||""),entryName:String(a||""),isDirectory:!!s});e.json(i)}catch(r){const t=r;h.error("failed to create workspace entry:",t),e.status(400).json({error:t.message})}}),p.post("/workspace/rename",c,async(o,e)=>{try{const{workspacePath:r,targetPath:t,newName:a}=o.body||{},s=await U({workspacePath:String(r||""),targetPath:String(t||""),newName:String(a||"")});e.json(s)}catch(r){const t=r;h.error("failed to rename workspace entry:",t),e.status(400).json({error:t.message})}}),p.post("/workspace/move",c,async(o,e)=>{try{const{workspacePath:r,targetPath:t,destinationPath:a}=o.body||{},s=await M({workspacePath:String(r||""),targetPath:String(t||""),destinationPath:String(a||"")});e.json(s)}catch(r){const t=r;h.error("failed to move workspace entry:",t),e.status(400).json({error:t.message})}}),p.post("/workspace/delete",c,async(o,e)=>{try{const{workspacePath:r,targetPath:t}=o.body||{},a=await F({workspacePath:String(r||""),targetPath:String(t||"")});e.json(a)}catch(r){const t=r;h.error("failed to delete workspace entry:",t),e.status(400).json({error:t.message})}}),p.post("/workspace/upload",c,it,async(o,e)=>{const r=o.files||[];try{const{workspacePath:t,path:a="",extractArchives:s}=o.body||{},i=nt(o.body||{}),n=await J({workspacePath:String(t||""),targetPath:String(a||""),extractArchives:P(s),files:r.map((l,d)=>({originalname:l.originalname,relativePath:i[d],path:l.path,size:l.size}))});e.json(n)}catch(t){const a=t;h.error("failed to upload workspace files:",a),e.status(400).json({error:a.message})}finally{await at(r)}}),p.post("/workspace/download",c,async(o,e)=>{let r;const t=String((o.body||{}).progressId||"").trim();try{const{workspacePath:a,targetPath:s}=o.body||{},i=await X({workspacePath:String(a||""),targetPath:String(s||"")});if(e.setHeader("Content-Type",i.contentType),e.setHeader("Content-Disposition",ot(i.fileName)),e.setHeader("X-Workspace-Path",encodeURIComponent(i.workspacePath)),e.setHeader("X-Workspace-Target-Path",encodeURIComponent(i.targetPath)),i.isDirectory){t&&m.set(t,{zippedBytes:0,totalBytes:null,done:!1,cancelled:!1,updatedAt:Date.now()}),r=await K(i.resolvedTargetPath,i.fileName,l=>{if(!t)return;const d=m.get(t);d&&(d.zippedBytes=l,d.updatedAt=Date.now())},()=>t?!!m.get(t)?.cancelled:!1);const n=await u.stat(r);if(t){const l=m.get(t);l&&(l.zippedBytes=n.size,l.totalBytes=n.size,l.done=!0,l.updatedAt=Date.now())}e.setHeader("Content-Length",String(n.size)),await W(S(r),e);return}i.size!==void 0&&e.setHeader("Content-Length",String(i.size)),S(i.resolvedTargetPath).pipe(e)}catch(a){const s=a;h.error("failed to download workspace entry:",s),e.headersSent?e.destroy(s):e.status(400).json({error:s.message})}finally{if(r&&await u.rm(r,{force:!0}).catch(()=>{}),t){const a=m.get(t);a&&(a.done=!0,a.totalBytes===null&&(a.totalBytes=0)),setTimeout(()=>m.delete(t),tt)}}}),p.post("/workspace/download-progress",c,(o,e)=>{const r=String((o.body||{}).progressId||"").trim();if(!r){e.status(400).json({error:"progressId is required"});return}const t=m.get(r);if(!t){e.status(404).json({error:"download progress not found"});return}e.json({zippedBytes:t.zippedBytes,totalBytes:t.totalBytes,done:t.done,cancelled:t.cancelled})}),p.post("/workspace/download-cancel",c,(o,e)=>{const r=String((o.body||{}).progressId||"").trim();if(!r){e.status(400).json({error:"progressId is required"});return}const t=m.get(r);t&&(t.cancelled=!0,t.done=!0,t.updatedAt=Date.now()),e.json({ok:!0})}),p.post("/workspace/extract",c,async(o,e)=>{try{const{workspacePath:r,archivePath:t,outputPath:a=""}=o.body||{},s=await B({workspacePath:String(r||""),archivePath:String(t||""),outputPath:String(a||"")});e.json(s)}catch(r){const t=r;h.error("failed to extract workspace archive:",t),e.status(400).json({error:t.message})}}),p.post("/workspace/path-search",c,async(o,e)=>{try{const{workspacePath:r,rootPath:t,keyword:a,ignoreCase:s,maxResults:i,maxDirectories:n}=o.body||{},l=await q({workspacePath:String(r||""),rootPath:t!==void 0?String(t):void 0,keyword:String(a||""),ignoreCase:P(s),maxResults:typeof i=="number"?i:void 0,maxDirectories:typeof n=="number"?n:void 0});e.json(l)}catch(r){const t=r;h.error("failed to search workspace paths:",t),e.status(400).json({error:t.message})}}),p.post("/workspace/search",c,async(o,e)=>{try{const{workspacePath:r,keyword:t,fileMask:a,ignoreCase:s,maxResults:i,mode:n}=o.body||{},l=await Y({workspacePath:String(r||""),keyword:String(t||""),fileMask:a!==void 0?String(a):void 0,ignoreCase:P(s),maxResults:typeof i=="number"?i:void 0,mode:n==="filename"?"filename":"content"});e.json(l)}catch(r){const t=r;h.error("failed to search workspace files:",t),e.status(400).json({error:t.message})}}),p.post("/workspace/replace",c,async(o,e)=>{try{const{workspacePath:r,keyword:t,replacement:a,fileMask:s,ignoreCase:i,filePath:n}=o.body||{},l=await G({workspacePath:String(r||""),keyword:String(t||""),replacement:String(a??""),fileMask:s!==void 0?String(s):void 0,ignoreCase:P(i),filePath:n!==void 0?String(n):void 0});e.json(l)}catch(r){const t=r;h.error("failed to replace workspace files:",t),e.status(400).json({error:t.message})}});export{b as WORKSPACE_UPLOAD_FILE_LIMIT,et as WORKSPACE_UPLOAD_MAX_FILE_SIZE_BYTES,st as createWorkspaceUploadLimitResponse,p as fileBrowserRouter,Tt as isIgnoredByGitIgnore,ct as listHostDirectoryTree,Wt as loadGitIgnoreRules,Rt as parseGitIgnoreRules,nt as parseWorkspaceUploadRelativePaths};
2
2
 
@@ -26,6 +26,46 @@ interface GitDiffSummaryFile {
26
26
  deletions: number;
27
27
  staged: boolean;
28
28
  }
29
+ interface GitCommitItem {
30
+ hash: string;
31
+ shortHash: string;
32
+ authorName: string;
33
+ authorDate: string;
34
+ subject: string;
35
+
36
+ body: string;
37
+
38
+ parents: string[];
39
+
40
+ isRemote: boolean;
41
+ }
42
+
43
+ export declare function resolveCommitPageLimit(rawLimit: unknown, graphMode: boolean): number;
44
+
45
+ export declare function resolveCommitPageSkip(rawSkip: unknown): number;
46
+
47
+ export interface CommitPageResult<T> {
48
+ page: T[];
49
+ hasMore: boolean;
50
+ nextSkip: number;
51
+ }
52
+
53
+ export declare function sliceCommitPage<T>(fetched: T[], limit: number, skip: number): CommitPageResult<T>;
54
+ interface GitCommitLogQuery {
55
+
56
+ limit: number;
57
+
58
+ skip: number;
59
+ graphMode: boolean;
60
+
61
+ focusedRef: string;
62
+
63
+ relativeWorkspacePath: string;
64
+
65
+ graphHeadRef?: string | null;
66
+ }
67
+
68
+ export declare function buildGitCommitLogArgs(query: GitCommitLogQuery): string[];
29
69
  export interface GitBranchItem {
30
70
 
31
71
  name: string;
@@ -75,6 +115,8 @@ export declare function normalizeGitCommitMessage(message: unknown): string;
75
115
  export declare function createScopedGitPathspecArgs(context: Pick<GitRepositoryContext, 'relativeWorkspacePath'>): string[];
76
116
  export declare function createScopedFilePathspecArgs(filePath: string, context: Pick<GitRepositoryContext, 'relativeWorkspacePath'>): string[];
77
117
 
118
+ export declare function parseGitCommitLog(output: string): Omit<GitCommitItem, 'isRemote'>[];
119
+
78
120
  export declare function resolveRemoteCommitHashes(repoRootPath: string): Promise<Set<string>>;
79
121
 
80
122
  export declare function resolveCurrentBranchName(repoRootPath: string): Promise<string>;