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.
- package/CHANGELOG.md +126 -0
- package/dist/adapter/AcodeSdkAdapter.d.ts +5 -1
- package/dist/adapter/AcodeSdkAdapter.js +3 -3
- package/dist/adapter/types.d.ts +2 -0
- package/dist/index.js +1 -1
- package/dist/routes/bridge-temp-files.d.ts +1 -0
- package/dist/routes/bridge-temp-files.js +2 -0
- package/dist/routes/dashboard.js +35 -5
- package/dist/routes/file-browser.d.ts +4 -10
- package/dist/routes/file-browser.js +1 -1
- package/dist/routes/git.d.ts +42 -0
- package/dist/routes/git.js +34 -34
- package/dist/routes/sessions.js +1 -1
- package/dist/routes/tech-stack.d.ts +2 -0
- package/dist/routes/tech-stack.js +2 -0
- package/dist/routes/terminal.js +19 -19
- package/dist/services/agent-pty-manager.d.ts +2 -0
- package/dist/services/agent-pty-manager.js +5 -4
- package/dist/services/agent-startup-memory.js +4 -4
- package/dist/services/bridge-temp-files.d.ts +36 -0
- package/dist/services/bridge-temp-files.js +2 -0
- package/dist/services/fileSnapshotStore.d.ts +9 -0
- package/dist/services/fileSnapshotStore.js +1 -1
- package/dist/services/gitignore.d.ts +12 -0
- package/dist/services/gitignore.js +2 -0
- package/dist/services/log-retention.js +1 -1
- package/dist/services/open-doc-events.d.ts +21 -0
- package/dist/services/open-doc-events.js +2 -0
- package/dist/services/open-doc-registry.d.ts +24 -0
- package/dist/services/open-doc-registry.js +2 -0
- package/dist/services/request-invalid-dump.js +1 -1
- package/dist/services/runtime-resources-snapshot.js +2 -2
- package/dist/services/snapshot-retention.d.ts +7 -0
- package/dist/services/snapshot-retention.js +2 -0
- package/dist/services/tech-stack-scanner.d.ts +31 -0
- package/dist/services/tech-stack-scanner.js +2 -0
- package/dist/services/tunnel-client.d.ts +42 -0
- package/dist/services/tunnel-client.js +1 -1
- package/dist/services/workspaceTaskChangeWatcher.js +2 -2
- package/package/acode/dist/__tests__/summary-request-helper.d.ts +2 -0
- package/package/acode/dist/__tests__/summary-request-helper.js +2 -0
- package/package/acode/dist/cache-control.d.ts +26 -0
- package/package/acode/dist/cache-control.js +2 -0
- package/package/acode/dist/compaction.d.ts +35 -5
- package/package/acode/dist/compaction.js +19 -17
- package/package/acode/dist/microcompact.d.ts +57 -0
- package/package/acode/dist/microcompact.js +2 -0
- package/package/acode/dist/runtime.d.ts +4 -0
- package/package/acode/dist/runtime.js +40 -33
- package/package/acode/dist/token-estimator.d.ts +15 -0
- package/package/acode/dist/token-estimator.js +2 -0
- package/package/acode/dist/types.d.ts +13 -0
- package/package/aws-client-agent-mcp/dist/ability-market-tools.js +1 -1
- package/package/aws-client-agent-mcp/dist/agent-client.d.ts +15 -2
- package/package/aws-client-agent-mcp/dist/agent-client.js +1 -1
- package/package/aws-client-agent-mcp/dist/mcp-server.d.ts +5 -0
- package/package/aws-client-agent-mcp/dist/mcp-server.js +25 -23
- package/package/aws-client-agent-mcp/dist/mcp-tools.js +7 -7
- package/package/aws-client-agent-mcp/dist/memory-store.d.ts +21 -2
- package/package/aws-client-agent-mcp/dist/memory-store.js +27 -2
- package/package/aws-client-agent-mcp/dist/memory-tools.js +13 -9
- package/package/aws-client-agent-mcp/dist/server-memory-store.d.ts +1 -1
- package/package/aws-client-agent-mcp/dist/server-memory-store.js +1 -1
- package/package/aws-client-agent-mcp/dist/types.d.ts +51 -0
- 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
|
+
|
package/dist/routes/dashboard.js
CHANGED
|
@@ -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
|
-
|
|
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 =
|
|
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"),
|
|
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
|
|
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
|
|
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
|
-
|
|
42
|
-
export
|
|
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
|
|
package/dist/routes/git.d.ts
CHANGED
|
@@ -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>;
|