aws-runtime-bridge 1.9.162 → 1.9.169

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 (123) hide show
  1. package/CHANGELOG.md +324 -0
  2. package/dist/adapter/AcodeSdkAdapter.d.ts +31 -3
  3. package/dist/adapter/AcodeSdkAdapter.js +4 -9
  4. package/dist/adapter/ClaudeSdkAdapter.d.ts +2 -0
  5. package/dist/adapter/ClaudeSdkAdapter.js +3 -3
  6. package/dist/adapter/CodexSdkAdapter.d.ts +2 -0
  7. package/dist/adapter/CodexSdkAdapter.js +3 -3
  8. package/dist/adapter/OpencodeSdkAdapter.d.ts +2 -0
  9. package/dist/adapter/OpencodeSdkAdapter.js +3 -3
  10. package/dist/adapter/prompts.d.ts +1 -1
  11. package/dist/adapter/prompts.js +1 -1
  12. package/dist/adapter/types.d.ts +41 -4
  13. package/dist/adapter/types.js +1 -1
  14. package/dist/browser/frame-encode.d.ts +25 -0
  15. package/dist/browser/frame-encode.js +2 -0
  16. package/dist/browser/screencast-differ.d.ts +2 -3
  17. package/dist/browser/screencast-differ.js +1 -1
  18. package/dist/browser/screencast-manager.js +1 -1
  19. package/dist/browser/types.d.ts +5 -1
  20. package/dist/browser/types.js +1 -1
  21. package/dist/desktop/desktop-mcp-client.js +2 -2
  22. package/dist/routes/background-tasks.js +3 -3
  23. package/dist/routes/capabilities.js +1 -1
  24. package/dist/routes/dashboard.d.ts +2 -0
  25. package/dist/routes/dashboard.js +4 -4
  26. package/dist/routes/git.js +22 -22
  27. package/dist/routes/instance.js +1 -1
  28. package/dist/routes/launch.js +10 -10
  29. package/dist/routes/mcp-extra.js +2 -2
  30. package/dist/routes/mcp.d.ts +4 -0
  31. package/dist/routes/mcp.js +1 -1
  32. package/dist/routes/plugins.js +1 -1
  33. package/dist/routes/pty.d.ts +11 -3
  34. package/dist/routes/pty.js +3 -3
  35. package/dist/routes/runtime-binding.js +1 -1
  36. package/dist/routes/sessions.js +1 -1
  37. package/dist/routes/skills.js +1 -1
  38. package/dist/routes/sub-agents.js +8 -8
  39. package/dist/routes/terminal.d.ts +16 -2
  40. package/dist/routes/terminal.js +34 -36
  41. package/dist/services/agent-process-manager.js +1 -1
  42. package/dist/services/agent-pty-manager.js +4 -4
  43. package/dist/services/aws-client-agent-mcp.js +2 -2
  44. package/dist/services/capability-config.d.ts +8 -0
  45. package/dist/services/capability-config.js +2 -2
  46. package/dist/services/desktop-mcp-manager.d.ts +3 -1
  47. package/dist/services/desktop-mcp-manager.js +1 -1
  48. package/dist/services/instance-ai-config-service.js +1 -1
  49. package/dist/services/instance-features.d.ts +10 -0
  50. package/dist/services/instance-features.js +1 -1
  51. package/dist/services/instance-init-service.js +1 -1
  52. package/dist/services/launch-manager.d.ts +9 -1
  53. package/dist/services/launch-manager.js +6 -6
  54. package/dist/services/launch-metrics.d.ts +1 -1
  55. package/dist/services/launch-metrics.js +4 -3
  56. package/dist/services/mcp-deploy.d.ts +4 -0
  57. package/dist/services/mcp-env-injector.d.ts +12 -0
  58. package/dist/services/mcp-env-injector.js +2 -0
  59. package/dist/services/mcp-launch-binding-queue.d.ts +8 -0
  60. package/dist/services/mcp-launch-binding-queue.js +1 -1
  61. package/dist/services/orphan-monitor.js +1 -1
  62. package/dist/services/panel-env.d.ts +6 -2
  63. package/dist/services/panel-env.js +1 -1
  64. package/dist/services/plugin-manager.js +9 -9
  65. package/dist/services/process-detector.d.ts +23 -3
  66. package/dist/services/process-detector.js +13 -13
  67. package/dist/services/runtime-resources-snapshot.d.ts +3 -0
  68. package/dist/services/runtime-resources-snapshot.js +3 -0
  69. package/dist/services/session-output.d.ts +13 -0
  70. package/dist/services/session-output.js +4 -4
  71. package/dist/services/tunnel-client.js +1 -1
  72. package/dist/services/workspace-files.js +1 -1
  73. package/dist/types.d.ts +4 -0
  74. package/dist/utils/env-safety.d.ts +15 -0
  75. package/dist/utils/env-safety.js +2 -0
  76. package/dist/utils/lifecycle-log.d.ts +2 -0
  77. package/dist/utils/lifecycle-log.js +3 -0
  78. package/dist/utils/mcp-utils.js +1 -1
  79. package/package/acode/dist/background-command-manager.js +4 -4
  80. package/package/acode/dist/built-in-file-tools.d.ts +13 -0
  81. package/package/acode/dist/built-in-file-tools.js +2 -2
  82. package/package/acode/dist/builtins/shellCommandPreparation.d.ts +2 -0
  83. package/package/acode/dist/builtins/shellCommandPreparation.js +2 -2
  84. package/package/acode/dist/compaction.d.ts +10 -0
  85. package/package/acode/dist/compaction.js +6 -6
  86. package/package/acode/dist/context-overflow.js +1 -1
  87. package/package/acode/dist/index.d.ts +1 -0
  88. package/package/acode/dist/index.js +1 -1
  89. package/package/acode/dist/mcpToolNames.d.ts +4 -0
  90. package/package/acode/dist/mcpToolNames.js +1 -1
  91. package/package/acode/dist/runtime-environment.d.ts +2 -0
  92. package/package/acode/dist/runtime-environment.js +3 -2
  93. package/package/acode/dist/runtime.d.ts +68 -8
  94. package/package/acode/dist/runtime.js +28 -27
  95. package/package/acode/dist/sub-agent-manager.js +1 -1
  96. package/package/acode/dist/tool-allocation.js +1 -1
  97. package/package/acode/dist/tool-group-manager.d.ts +12 -0
  98. package/package/acode/dist/tool-group-manager.js +8 -4
  99. package/package/acode/dist/types.d.ts +8 -0
  100. package/package/acode/package.json +1 -1
  101. package/package/aws-client-agent-mcp/README.md +1 -0
  102. package/package/aws-client-agent-mcp/dist/agent-client.d.ts +22 -8
  103. package/package/aws-client-agent-mcp/dist/agent-client.js +1 -1
  104. package/package/aws-client-agent-mcp/dist/http-client.d.ts +10 -0
  105. package/package/aws-client-agent-mcp/dist/http-client.js +1 -1
  106. package/package/aws-client-agent-mcp/dist/logger.d.ts +2 -1
  107. package/package/aws-client-agent-mcp/dist/logger.js +2 -2
  108. package/package/aws-client-agent-mcp/dist/mcp-server.d.ts +19 -2
  109. package/package/aws-client-agent-mcp/dist/mcp-server.js +18 -18
  110. package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts +15 -4
  111. package/package/aws-client-agent-mcp/dist/mcp-tools.js +79 -29
  112. package/package/aws-client-agent-mcp/dist/memory-store.d.ts +2 -0
  113. package/package/aws-client-agent-mcp/dist/memory-store.js +3 -3
  114. package/package/aws-client-agent-mcp/dist/message-buffer.js +1 -1
  115. package/package/aws-client-agent-mcp/dist/office/office-workspace.d.ts +15 -0
  116. package/package/aws-client-agent-mcp/dist/office/office-workspace.js +1 -1
  117. package/package/aws-client-agent-mcp/dist/status-reporter.js +1 -1
  118. package/package/aws-client-agent-mcp/dist/tool-groups.d.ts +4 -0
  119. package/package/aws-client-agent-mcp/dist/tool-groups.js +2 -2
  120. package/package/aws-client-agent-mcp/dist/types.d.ts +52 -1
  121. package/package/aws-client-agent-mcp/dist/websocket-client.js +1 -1
  122. package/package/aws-client-agent-mcp/package.json +1 -1
  123. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- import{spawn as E}from"node:child_process";import{EventEmitter as T}from"node:events";import*as S from"node:fs";import*as x from"node:net";import*as A from"node:os";import*as g from"node:path";import{v4 as P}from"uuid";import{getAcodeDataHome as _}from"../config.js";import{registerListenerWakeHook as M,unregisterListenerWakeHook as D}from"../services/browser-session-manager.js";import{logger as $}from"../utils/logger.js";import{BRIDGE_PACKAGE_ROOT as L,importBridgeSdkPackage as N}from"../utils/sdk-package-loader.js";import{IdlePollLoop as I}from"./idle-poll-loop.js";import{MESSAGE_POLLING_IDLE_PROMPT as R}from"./prompts.js";import{getToolActionInfo as C,redactTransientClipboardPastePaths as O,redactTransientClipboardPastePathsInValue as U}from"./types.js";function j(d){if(d&&g.isAbsolute(d)&&S.existsSync(d))return d;const t=d?.trim()||"opencode";if(process.platform==="win32"){const e=process.env.USERPROFILE||process.env.HOME||A.homedir(),s=process.env.LOCALAPPDATA||"",r=[g.join(s,"Volta","tools","shared","opencode-ai","node_modules","opencode-windows-x64","bin"),g.join(s,"Volta","tools","shared","opencode-ai","node_modules","opencode-windows-x64-baseline","bin")];for(const o of r){const n=g.join(o,"opencode.exe");if(S.existsSync(n))return n}const i=[g.join(e,"AppData","Roaming","npm"),g.join(e,"AppData","Local","Volta","bin")];for(const o of i)for(const n of["opencode.cmd","opencode.exe","opencode"]){const a=g.join(o,n);if(S.existsSync(a))return a}}return t}async function H(d=14096){for(let t=d;t<d+100;t++)if(await new Promise(s=>{const r=x.createServer();r.once("error",()=>s(!1)),r.once("listening",()=>{r.close(()=>s(!0))}),r.listen(t,"127.0.0.1")}))return t;throw new Error(`No available port found in range ${d}\u2013${d+99}`)}function W(d){return d instanceof Error&&"code"in d&&typeof d.code=="string"}function F(d,t){return W(d)&&d.code==="ERR_MODULE_NOT_FOUND"&&d.message.includes(t)}function v(d){if(!d||!d.trim())return;const t=d.trim(),e=t.indexOf("/");return e>0?{providerID:t.slice(0,e),modelID:t.slice(e+1)}:{modelID:t}}class Y extends T{constructor(){super(...arguments),this.providerId="opencode",this.displayName="OpenCode",this.sessions=new Map,this.listenerWakeHooks=new Map}async startSession(t,e){const s={adapterSession:{sessionId:t,status:"starting",messages:[],createdAt:new Date().toISOString(),totalUsage:{inputTokens:0,outputTokens:0}},config:e,sseActive:!1,pendingPermissions:new Map,emittedToolStarts:new Set,workingDirectory:e.workingDirectory,userMessageIds:new Set,currentAssistantText:"",seenTextPartIds:new Set};if(this.sessions.set(t,s),e.agentId){const r=()=>{this.sessions.get(t)?.idlePollLoop?.start()};this.listenerWakeHooks.set(t,r),M(e.agentId,r)}this.emit("status-change",t,"starting");try{const r=await H();s.port=r;const i=j(e.command),o=i.endsWith(".cmd")||i.endsWith(".CMD")||process.platform==="win32"&&!g.isAbsolute(i),n={...process.env,...e.envOverrides},a={},m=v(e.model),h=e.model;m?.modelID&&h!==null&&h!==void 0&&(a.model=h.trim()),e.systemPrompt&&typeof e.systemPrompt=="string"&&(a.systemPrompt=e.systemPrompt),Object.keys(a).length>0&&(n.OPENCODE_CONFIG_CONTENT=JSON.stringify(a),$.info(`[OpencodeSdkAdapter] OPENCODE_CONFIG_CONTENT keys=${Object.keys(a).join(",")}`));const l=E(i,["serve","--port",String(r)],{cwd:e.workingDirectory,stdio:["ignore","pipe","pipe"],env:n,shell:o});s.serverProcess=l,s.startupOutput=[],l.stdout?.on("data",u=>{const y=u.toString();this.recordStartupOutput(s,y)}),l.stderr?.on("data",u=>{const y=u.toString();this.recordStartupOutput(s,y)}),l.on("error",u=>{console.error("[OpencodeSdkAdapter] Server process error:",u),s.adapterSession.status!=="terminated"&&(s.adapterSession.status="error",this.emit("status-change",t,"error"),this.emitEvent({type:"error",sessionId:t,timestamp:new Date().toISOString(),data:{text:`OpenCode server error: ${u.message}`}}))}),l.on("exit",u=>{s.sseActive=!1});const c=new Promise(u=>{l.once("exit",(y,b)=>u({code:y,signal:b}))}),p=(await this.loadSdk()).createOpencodeClient({baseUrl:`http://127.0.0.1:${r}`});s.client=p,await Promise.race([this.waitForServer(p,e.workingDirectory,1e4,r),c.then(u=>{throw new Error(this.formatStartupExitMessage(u,s.startupOutput))})]);const k=(await p.session.create({body:{title:`aws-bridge-${t.slice(0,8)}`},query:{directory:e.workingDirectory}})).data;if(!k?.id)throw new Error("OpenCode session.create() did not return an ID");s.opencodeSessionId=k.id,s.adapterSession.providerSessionId=k.id,this.startSseLoop(t,s),s.adapterSession.status="waiting_input",this.emit("status-change",t,"waiting_input",{usage:s.adapterSession.totalUsage}),e.initialPrompt&&this.dispatchInitialPrompt(t,e.initialPrompt)}catch(r){e.agentId&&D(e.agentId,this.listenerWakeHooks.get(t)),this.listenerWakeHooks.delete(t);const i=r instanceof Error?r.message:String(r);throw console.error("[OpencodeSdkAdapter] startSession failed:",r),s.adapterSession.status="error",this.emit("status-change",t,"error"),this.emitEvent({type:"error",sessionId:t,timestamp:new Date().toISOString(),data:{text:`OpenCode start failed: ${i}`}}),r}}async sendMessage(t,e,s){const r=this.sessions.get(t);if(!r)throw new Error(`Session ${t} not found`);if(!r.client||!r.opencodeSessionId)throw new Error(`Session ${t} not ready`);const i={id:P(),sessionId:t,role:"user",content:e,timestamp:new Date().toISOString()};r.adapterSession.messages.push(i),this.emit("conversation-message",t,i),s?.keepWaitingStatus||(r.adapterSession.status="thinking",this.emit("status-change",t,"thinking"),this.stopIdleDetection(t));try{const o=v(r.config.model),n={parts:[{type:"text",text:e}]};o?.providerID&&o?.modelID&&(n.model={providerID:o.providerID,modelID:o.modelID}),await r.client.session.prompt({path:{id:r.opencodeSessionId},body:n,query:{directory:r.workingDirectory}})}catch(o){const n=o instanceof Error?o.message:String(o);this.emitEvent({type:"error",sessionId:t,timestamp:new Date().toISOString(),data:{text:n}})}}async sendConfirmation(t,e){const s=this.sessions.get(t);if(!s?.client||!s.opencodeSessionId)return;const r=e?"once":"reject",i=s.opencodeSessionId;for(const[o]of s.pendingPermissions)try{await s.client.postSessionIdPermissionsPermissionId({path:{id:i,permissionID:o},body:{response:r},query:{directory:s.workingDirectory}})}catch(n){console.warn("[OpencodeSdkAdapter] Permission response failed:",n)}s.pendingPermissions.clear()}async sendQuestionAnswer(t,e){}setIdleCommands(t,e){const s=this.sessions.get(t);s&&(s.idleCommands=e,s.adapterSession.status==="waiting_input"&&(e.idleInputCommand||e.nonInputCommand)&&this.startIdleDetection(t))}async abortCurrentTurn(t){const e=this.sessions.get(t);if(!(!e?.client||!e.opencodeSessionId))try{await e.client.session.abort({path:{id:e.opencodeSessionId},query:{directory:e.workingDirectory}})}catch(s){console.warn("[OpencodeSdkAdapter] Abort failed:",s)}}async terminateSession(t){const e=this.sessions.get(t);if(e){if(this.stopIdleDetection(t),e.sseActive=!1,e.sseAbortController?.abort(),e.serverProcess)try{e.serverProcess.kill()}catch{}e.adapterSession.status="terminated",this.emit("status-change",t,"terminated"),this.emitEvent({type:"session_complete",sessionId:t,timestamp:new Date().toISOString(),data:{exitCode:0}}),e.config.agentId&&D(e.config.agentId,this.listenerWakeHooks.get(t)),this.listenerWakeHooks.delete(t),this.sessions.delete(t)}}getConversation(t){return this.sessions.get(t)?.adapterSession.messages??[]}hasSession(t){return this.sessions.has(t)}getProviderSessionId(t){return this.sessions.get(t)?.opencodeSessionId}getSessionStatus(t){return this.sessions.get(t)?.adapterSession.status}getSessionPid(t){const e=this.sessions.get(t);if(e)return e.serverProcess?.pid}cleanup(){for(const[t]of this.sessions)try{this.terminateSession(t)}catch{}this.sessions.clear()}async loadSdk(){if(!this.sdkModule)try{this.sdkModule=await N("@opencode-ai/sdk")}catch(t){throw F(t,"@opencode-ai/sdk")?new Error(["OpenCode SDK provider is not installed.","","aws-runtime-bridge keeps Codex/OpenCode provider SDKs optional to reduce default install size.",'To use SDK mode with command "opencode", install the SDK into the aws-runtime-bridge package root:',"",` npm install --prefix "${L}" @opencode-ai/sdk@latest opencode-ai@latest`,"","If aws-runtime-bridge is installed locally, run the same command with that local package path.","",`Original error: ${t instanceof Error?t.message:String(t)}`].join(`
2
- `)):t}return this.sdkModule}async waitForServer(t,e,s,r){const i=Date.now()+s;for(;Date.now()<i;){try{if((await t.session.list({query:{directory:e}})).data!==void 0)return}catch{}await new Promise(o=>setTimeout(o,300))}throw new Error(`OpenCode server (port ${r}) did not start within ${s}ms`)}recordStartupOutput(t,e){const s=e.trim();s&&(t.startupOutput=[...t.startupOutput??[],s].slice(-8))}formatStartupExitMessage(t,e){const s=t.signal?`signal ${t.signal}`:`code ${t.code??"unknown"}`,r=(e??[]).join(`
3
- `).trim();return r?`OpenCode server exited during startup (${s}): ${r}`:`OpenCode server exited during startup (${s}). Please check whether opencode serve can run in this workspace.`}dispatchInitialPrompt(t,e){this.sendMessage(t,e).catch(s=>{const r=s instanceof Error?s.message:String(s);this.emitEvent({type:"error",sessionId:t,timestamp:new Date().toISOString(),data:{text:`OpenCode initial prompt failed: ${r}`}})})}startSseLoop(t,e){e.sseActive=!0;const s=new AbortController;e.sseAbortController=s,this.runSseLoop(t,e,s).catch(r=>{s.signal.aborted||console.error("[OpencodeSdkAdapter] SSE loop error:",r)})}async runSseLoop(t,e,s){if(e.client)try{const r=await e.client.event.subscribe({query:{directory:e.workingDirectory},signal:s.signal});for await(const i of r.stream){if(!e.sseActive||s.signal.aborted)break;this.handleOpenCodeEvent(t,e,i)}}catch(r){if(s.signal.aborted)return;console.error("[OpencodeSdkAdapter] SSE stream ended:",r)}}handleOpenCodeEvent(t,e,s){const r=new Date().toISOString(),i=e.opencodeSessionId;switch(s.type){case"message.updated":{const o=s.properties.info;if(o.sessionID!==i)break;if(o.role==="user")e.userMessageIds.add(o.id);else if(o.role==="assistant"){const n=o.tokens;n&&(e.adapterSession.totalUsage.inputTokens=Math.max(e.adapterSession.totalUsage.inputTokens,n.input),e.adapterSession.totalUsage.outputTokens=Math.max(e.adapterSession.totalUsage.outputTokens,n.output))}break}case"message.part.updated":{const{part:o,delta:n}=s.properties;if(o.sessionID!==i||e.userMessageIds.has(o.messageID))break;this.handlePartUpdate(t,e,o,n,r);break}case"session.idle":{if(s.properties.sessionID!==i)break;if(e.currentAssistantText){const a={id:P(),sessionId:t,role:"assistant",content:e.currentAssistantText,timestamp:r};e.adapterSession.messages.push(a),e.currentAssistantText=""}e.seenTextPartIds.clear(),this.emitEvent({type:"turn_complete",sessionId:t,timestamp:r,data:{usage:e.adapterSession.totalUsage}}),e.adapterSession.status="waiting_input";const o=e.idleCommands?.idleInputCommand;!!(o&&this.isMessagePollingIdleCommand(o))?this.emit("status-change",t,"waiting_input",{actionType:"idle",actionLabel:"\u76D1\u542C\u6D88\u606F",actionDetail:"aws-mcp/poll_message",usage:e.adapterSession.totalUsage}):this.emit("status-change",t,"waiting_input",{usage:e.adapterSession.totalUsage}),this.startIdleDetection(t);break}case"permission.updated":{const o=s.properties;if(o.sessionID!==i)break;const n=o.id;e.pendingPermissions.set(n,o),e.config.autoAccept&&e.client&&i?e.client.postSessionIdPermissionsPermissionId({path:{id:i,permissionID:n},body:{response:"once"},query:{directory:e.workingDirectory}}).then(()=>{e.pendingPermissions.delete(n)}).catch(a=>{console.warn("[OpencodeSdkAdapter] Auto-accept permission failed:",a)}):this.emitEvent({type:"permission_request",sessionId:t,timestamp:r,data:{permissionPrompt:o.title,toolName:o.type}});break}case"session.error":{const{sessionID:o,error:n}=s.properties;if(o&&o!==i)break;let a="OpenCode session error";if(n){const m=n.data;typeof m?.message=="string"?a=`${n.name}: ${m.message}`:a=n.name}this.emitEvent({type:"error",sessionId:t,timestamp:r,data:{text:a}});break}}}handlePartUpdate(t,e,s,r,i){switch(s.type){case"text":{let o;if(r!==void 0)o=r,e.seenTextPartIds.add(s.id);else if(!e.seenTextPartIds.has(s.id))o=s.text,o&&e.seenTextPartIds.add(s.id);else break;if(!o)break;e.currentAssistantText+=o,this.emitEvent({type:"text_delta",sessionId:t,timestamp:i,data:{text:o}});break}case"reasoning":{const o=r??s.text;if(!o)break;this.emitEvent({type:"thinking",sessionId:t,timestamp:i,data:{text:o}});break}case"tool":{const o=s.callID,n=s.tool,a=s.state,m=a.input,h=s.metadata,l=U(m),c=l&&typeof l=="object"&&!Array.isArray(l)?l:{},f=()=>{if(e.emittedToolStarts.has(o))return;e.emittedToolStarts.add(o);const p={...C(n,m,h),actionId:o};this.emitEvent({type:"tool_use_start",sessionId:t,timestamp:i,data:{toolName:n,toolInput:c,toolUseId:o,...p}}),e.adapterSession.messages.push({id:P(),sessionId:t,role:"tool_use",content:`${n}: ${JSON.stringify(c).slice(0,100)}`,timestamp:i,toolName:n,toolInput:c,toolUseId:o})};if(a.status==="running"){f();const p={...C(n,m,h),actionId:o};this.emit("status-change",t,"tool_using",{...p,usage:e.adapterSession.totalUsage})}else if(a.status==="completed"){(n==="todowrite"||n==="todo_write")&&this.syncTodosFromToolCall(e,m).catch(w=>{console.warn("[OpencodeSdkAdapter] \u540C\u6B65 todo \u5230\u6587\u4EF6\u5931\u8D25:",w)}),f();const p=O(a.output);this.emitEvent({type:"tool_use_end",sessionId:t,timestamp:i,data:{toolName:n,toolResult:p,isError:!1,toolUseId:o}}),e.emittedToolStarts.delete(o)}else if(a.status==="error"){f();const p=O(a.error);this.emitEvent({type:"tool_use_end",sessionId:t,timestamp:i,data:{toolName:n,toolResult:p,isError:!0,toolUseId:o}}),e.emittedToolStarts.delete(o)}break}}}getTodoStoreDir(){return g.join(_(),"todos")}async syncTodosFromToolCall(t,e){const s=t.config.agentId;if(!s)return;const r=e.todos;if(!Array.isArray(r)||r.length===0)return;const i=[];for(const l of r)if(l&&typeof l=="object"){const c=l,f=typeof c.content=="string"?c.content.trim():"",p=typeof c.status=="string"?c.status:"",w=typeof c.priority=="string"?c.priority:"";f&&p&&w&&i.push({content:f,status:p,priority:w})}if(i.length===0)return;const o=String(s).replace(/[^a-zA-Z0-9_-]/g,"_"),n=this.getTodoStoreDir(),a=g.join(n,`${o}.json`),m={agentId:s,updatedAt:new Date().toISOString(),background:"OpenCode runtime todos",todos:i};await S.promises.mkdir(n,{recursive:!0});const h=`${a}.tmp`;await S.promises.writeFile(h,JSON.stringify(m,null,2),"utf-8"),await S.promises.rename(h,a)}emitEvent(t){this.emit("event",t)}startIdleDetection(t){this.stopIdleDetection(t);const e=this.sessions.get(t),s=e?.idleCommands?.idleInputCommand;if(!e||!s)return;if(this.isMessagePollingIdleCommand(s)){e.idlePollLoop||(e.idlePollLoop=new I({getStatus:()=>this.sessions.get(t)?.adapterSession.status,getCommand:()=>this.sessions.get(t)?.idleCommands?.idleInputCommand,isPollingCommand:i=>this.isMessagePollingIdleCommand(i),preDispatchHook:()=>null,dispatchPollingPrompt:(i,o)=>this.sendMessage(t,o?i.trim():this.toIdlePrompt(i),{keepWaitingStatus:!0}),dispatchRegularIdleCommand:i=>this.sendMessage(t,this.toIdlePrompt(i)),pollDelayMs:1500})),e.idlePollLoop.start();return}e.idlePollLoop||(e.idlePollLoop=new I({getStatus:()=>this.sessions.get(t)?.adapterSession.status,getCommand:()=>this.sessions.get(t)?.idleCommands?.idleInputCommand,isPollingCommand:i=>this.isMessagePollingIdleCommand(i),preDispatchHook:()=>null,dispatchPollingPrompt:(i,o)=>this.sendMessage(t,o?i.trim():this.toIdlePrompt(i),{keepWaitingStatus:!0}),dispatchRegularIdleCommand:i=>this.sendMessage(t,this.toIdlePrompt(i)),pollDelayMs:1500}));const r=setInterval(()=>{this.checkIdleState(t)},500);e.idleTimer=r}stopIdleDetection(t){const e=this.sessions.get(t);e?.idlePollLoop?.stop(),e?.idleTimer&&(clearInterval(e.idleTimer),e.idleTimer=void 0)}checkIdleState(t){const e=this.sessions.get(t);!e||e.adapterSession.status!=="waiting_input"||e.idleCommands?.idleInputCommand&&(this.sendMessage(t,this.toIdlePrompt(e.idleCommands.idleInputCommand)),this.stopIdleDetection(t))}toIdlePrompt(t){const e=t.trim();return this.isMessagePollingIdleCommand(e)?R:e}isMessagePollingIdleCommand(t){const e=t.trim();if(!e)return!1;const s=e.toLowerCase();return s.includes("poll_message")||s.includes("get_message")||e.includes("\u53D6\u6D88\u606F")}}export{Y as OpencodeSdkAdapter};
1
+ import{spawn as T}from"node:child_process";import{EventEmitter as E}from"node:events";import*as S from"node:fs";import*as x from"node:net";import*as A from"node:os";import*as g from"node:path";import{v4 as P}from"uuid";import{getAcodeDataHome as _}from"../config.js";import{registerListenerWakeHook as M,unregisterListenerWakeHook as D}from"../services/browser-session-manager.js";import{logger as $}from"../utils/logger.js";import{BRIDGE_PACKAGE_ROOT as L,importBridgeSdkPackage as N}from"../utils/sdk-package-loader.js";import{IdlePollLoop as C}from"./idle-poll-loop.js";import{MESSAGE_POLLING_IDLE_PROMPT as R}from"./prompts.js";import{getToolActionInfo as I,redactTransientClipboardPastePaths as O,redactTransientClipboardPastePathsInValue as U}from"./types.js";function j(d){if(d&&g.isAbsolute(d)&&S.existsSync(d))return d;const t=d?.trim()||"opencode";if(process.platform==="win32"){const e=process.env.USERPROFILE||process.env.HOME||A.homedir(),s=process.env.LOCALAPPDATA||"",o=[g.join(s,"Volta","tools","shared","opencode-ai","node_modules","opencode-windows-x64","bin"),g.join(s,"Volta","tools","shared","opencode-ai","node_modules","opencode-windows-x64-baseline","bin")];for(const i of o){const r=g.join(i,"opencode.exe");if(S.existsSync(r))return r}const n=[g.join(e,"AppData","Roaming","npm"),g.join(e,"AppData","Local","Volta","bin")];for(const i of n)for(const r of["opencode.cmd","opencode.exe","opencode"]){const a=g.join(i,r);if(S.existsSync(a))return a}}return t}async function H(d=14096){for(let t=d;t<d+100;t++)if(await new Promise(s=>{const o=x.createServer();o.once("error",()=>s(!1)),o.once("listening",()=>{o.close(()=>s(!0))}),o.listen(t,"127.0.0.1")}))return t;throw new Error(`No available port found in range ${d}\u2013${d+99}`)}function W(d){return d instanceof Error&&"code"in d&&typeof d.code=="string"}function F(d,t){return W(d)&&d.code==="ERR_MODULE_NOT_FOUND"&&d.message.includes(t)}function v(d){if(!d||!d.trim())return;const t=d.trim(),e=t.indexOf("/");return e>0?{providerID:t.slice(0,e),modelID:t.slice(e+1)}:{modelID:t}}class Y extends E{constructor(){super(...arguments),this.providerId="opencode",this.displayName="OpenCode",this.sessions=new Map,this.listenerWakeHooks=new Map}async startSession(t,e){const s={adapterSession:{sessionId:t,status:"starting",messages:[],createdAt:new Date().toISOString(),totalUsage:{inputTokens:0,outputTokens:0}},config:e,sseActive:!1,pendingPermissions:new Map,emittedToolStarts:new Set,workingDirectory:e.workingDirectory,userMessageIds:new Set,currentAssistantText:"",seenTextPartIds:new Set};if(this.sessions.set(t,s),e.agentId){const o=()=>{this.sessions.get(t)?.idlePollLoop?.start()};this.listenerWakeHooks.set(t,o),M(e.agentId,o)}this.emit("status-change",t,"starting");try{const o=await H();s.port=o;const n=j(e.command),i=n.endsWith(".cmd")||n.endsWith(".CMD")||process.platform==="win32"&&!g.isAbsolute(n),r={...process.env,...e.envOverrides},a={},m=v(e.model),h=e.model;m?.modelID&&h!==null&&h!==void 0&&(a.model=h.trim()),e.systemPrompt&&typeof e.systemPrompt=="string"&&(a.systemPrompt=e.systemPrompt),Object.keys(a).length>0&&(r.OPENCODE_CONFIG_CONTENT=JSON.stringify(a),$.info(`[OpencodeSdkAdapter] OPENCODE_CONFIG_CONTENT keys=${Object.keys(a).join(",")}`));const l=T(n,["serve","--port",String(o)],{cwd:e.workingDirectory,stdio:["ignore","pipe","pipe"],env:r,shell:i});s.serverProcess=l,s.startupOutput=[],l.stdout?.on("data",u=>{const k=u.toString();this.recordStartupOutput(s,k)}),l.stderr?.on("data",u=>{const k=u.toString();this.recordStartupOutput(s,k)}),l.on("error",u=>{console.error("[OpencodeSdkAdapter] Server process error:",u),s.adapterSession.status!=="terminated"&&(s.adapterSession.status="error",this.emit("status-change",t,"error"),this.emitEvent({type:"error",sessionId:t,timestamp:new Date().toISOString(),data:{text:`OpenCode server error: ${u.message}`}}))}),l.on("exit",u=>{s.sseActive=!1});const p=new Promise(u=>{l.once("exit",(k,b)=>u({code:k,signal:b}))}),c=(await this.loadSdk()).createOpencodeClient({baseUrl:`http://127.0.0.1:${o}`});s.client=c,await Promise.race([this.waitForServer(c,e.workingDirectory,1e4,o),p.then(u=>{throw new Error(this.formatStartupExitMessage(u,s.startupOutput))})]);const y=(await c.session.create({body:{title:`aws-bridge-${t.slice(0,8)}`},query:{directory:e.workingDirectory}})).data;if(!y?.id)throw new Error("OpenCode session.create() did not return an ID");s.opencodeSessionId=y.id,s.adapterSession.providerSessionId=y.id,this.startSseLoop(t,s),s.adapterSession.status="waiting_input",this.emit("status-change",t,"waiting_input",{usage:s.adapterSession.totalUsage}),e.initialPrompt&&this.dispatchInitialPrompt(t,e.initialPrompt)}catch(o){e.agentId&&D(e.agentId,this.listenerWakeHooks.get(t)),this.listenerWakeHooks.delete(t);const n=o instanceof Error?o.message:String(o);throw console.error("[OpencodeSdkAdapter] startSession failed:",o),s.adapterSession.status="error",this.emit("status-change",t,"error"),this.emitEvent({type:"error",sessionId:t,timestamp:new Date().toISOString(),data:{text:`OpenCode start failed: ${n}`}}),o}}async sendMessage(t,e,s){const o=this.sessions.get(t);if(!o)throw new Error(`Session ${t} not found`);if(!o.client||!o.opencodeSessionId)throw new Error(`Session ${t} not ready`);const n={id:P(),sessionId:t,role:"user",content:e,timestamp:new Date().toISOString()};o.adapterSession.messages.push(n),this.emit("conversation-message",t,n),s?.keepWaitingStatus||(o.adapterSession.status="thinking",this.emit("status-change",t,"thinking"),this.stopIdleDetection(t));try{const i=v(o.config.model),r={parts:[{type:"text",text:e}]};i?.providerID&&i?.modelID&&(r.model={providerID:i.providerID,modelID:i.modelID}),await o.client.session.prompt({path:{id:o.opencodeSessionId},body:r,query:{directory:o.workingDirectory}})}catch(i){const r=i instanceof Error?i.message:String(i);this.emitEvent({type:"error",sessionId:t,timestamp:new Date().toISOString(),data:{text:r}})}}async sendConfirmation(t,e){const s=this.sessions.get(t);if(!s?.client||!s.opencodeSessionId)return;const o=e?"once":"reject",n=s.opencodeSessionId;for(const[i]of s.pendingPermissions)try{await s.client.postSessionIdPermissionsPermissionId({path:{id:n,permissionID:i},body:{response:o},query:{directory:s.workingDirectory}})}catch(r){console.warn("[OpencodeSdkAdapter] Permission response failed:",r)}s.pendingPermissions.clear()}async sendQuestionAnswer(t,e){}setIdleCommands(t,e){const s=this.sessions.get(t);s&&(s.idleCommands=e,s.adapterSession.status==="waiting_input"&&(e.idleInputCommand||e.nonInputCommand)&&this.startIdleDetection(t))}async abortCurrentTurn(t){const e=this.sessions.get(t);if(!(!e?.client||!e.opencodeSessionId))try{await e.client.session.abort({path:{id:e.opencodeSessionId},query:{directory:e.workingDirectory}})}catch(s){console.warn("[OpencodeSdkAdapter] Abort failed:",s)}}async terminateSession(t){const e=this.sessions.get(t);if(e){if(this.stopIdleDetection(t),e.sseActive=!1,e.sseAbortController?.abort(),e.serverProcess)try{e.serverProcess.kill()}catch{}e.adapterSession.status="terminated",this.emit("status-change",t,"terminated"),this.emitEvent({type:"session_complete",sessionId:t,timestamp:new Date().toISOString(),data:{exitCode:0}}),e.config.agentId&&D(e.config.agentId,this.listenerWakeHooks.get(t)),this.listenerWakeHooks.delete(t),this.sessions.delete(t)}}getConversation(t){return this.sessions.get(t)?.adapterSession.messages??[]}hasSession(t){return this.sessions.has(t)}getProviderSessionId(t){return this.sessions.get(t)?.opencodeSessionId}getSessionStatus(t){return this.sessions.get(t)?.adapterSession.status}getSessionPid(t){const e=this.sessions.get(t);if(e)return e.serverProcess?.pid}cleanup(){for(const[t]of this.sessions)try{this.terminateSession(t)}catch{}this.sessions.clear()}async loadSdk(){if(!this.sdkModule)try{this.sdkModule=await N("@opencode-ai/sdk")}catch(t){throw F(t,"@opencode-ai/sdk")?new Error(["OpenCode SDK provider is not installed.","","aws-runtime-bridge keeps Codex/OpenCode provider SDKs optional to reduce default install size.",'To use SDK mode with command "opencode", install the SDK into the aws-runtime-bridge package root:',"",` npm install --prefix "${L}" @opencode-ai/sdk@latest opencode-ai@latest`,"","If aws-runtime-bridge is installed locally, run the same command with that local package path.","",`Original error: ${t instanceof Error?t.message:String(t)}`].join(`
2
+ `)):t}return this.sdkModule}async waitForServer(t,e,s,o){const n=Date.now()+s;for(;Date.now()<n;){try{if((await t.session.list({query:{directory:e}})).data!==void 0)return}catch{}await new Promise(i=>setTimeout(i,300))}throw new Error(`OpenCode server (port ${o}) did not start within ${s}ms`)}recordStartupOutput(t,e){const s=e.trim();s&&(t.startupOutput=[...t.startupOutput??[],s].slice(-8))}formatStartupExitMessage(t,e){const s=t.signal?`signal ${t.signal}`:`code ${t.code??"unknown"}`,o=(e??[]).join(`
3
+ `).trim();return o?`OpenCode server exited during startup (${s}): ${o}`:`OpenCode server exited during startup (${s}). Please check whether opencode serve can run in this workspace.`}dispatchInitialPrompt(t,e){this.sendMessage(t,e).catch(s=>{const o=s instanceof Error?s.message:String(s);this.emitEvent({type:"error",sessionId:t,timestamp:new Date().toISOString(),data:{text:`OpenCode initial prompt failed: ${o}`}})})}startSseLoop(t,e){e.sseActive=!0;const s=new AbortController;e.sseAbortController=s,this.runSseLoop(t,e,s).catch(o=>{s.signal.aborted||console.error("[OpencodeSdkAdapter] SSE loop error:",o)})}async runSseLoop(t,e,s){if(e.client)try{const o=await e.client.event.subscribe({query:{directory:e.workingDirectory},signal:s.signal});for await(const n of o.stream){if(!e.sseActive||s.signal.aborted)break;this.handleOpenCodeEvent(t,e,n)}}catch(o){if(s.signal.aborted)return;console.error("[OpencodeSdkAdapter] SSE stream ended:",o)}}handleOpenCodeEvent(t,e,s){const o=new Date().toISOString(),n=e.opencodeSessionId;switch(s.type){case"message.updated":{const i=s.properties.info;if(i.sessionID!==n)break;if(i.role==="user")e.userMessageIds.add(i.id);else if(i.role==="assistant"){const r=i.tokens;r&&(e.adapterSession.totalUsage.inputTokens=Math.max(e.adapterSession.totalUsage.inputTokens,r.input),e.adapterSession.totalUsage.outputTokens=Math.max(e.adapterSession.totalUsage.outputTokens,r.output))}break}case"message.part.updated":{const{part:i,delta:r}=s.properties;if(i.sessionID!==n||e.userMessageIds.has(i.messageID))break;this.handlePartUpdate(t,e,i,r,o);break}case"session.idle":{if(s.properties.sessionID!==n)break;if(e.currentAssistantText){const a={id:P(),sessionId:t,role:"assistant",content:e.currentAssistantText,timestamp:o};e.adapterSession.messages.push(a),e.currentAssistantText=""}e.seenTextPartIds.clear(),this.emitEvent({type:"turn_complete",sessionId:t,timestamp:o,data:{usage:e.adapterSession.totalUsage}}),e.adapterSession.status="waiting_input";const i=e.idleCommands?.idleInputCommand;!!(i&&this.isMessagePollingIdleCommand(i))?this.emit("status-change",t,"waiting_input",{actionType:"idle",actionLabel:"\u76D1\u542C\u6D88\u606F",actionDetail:"aws-mcp/poll_message",usage:e.adapterSession.totalUsage}):this.emit("status-change",t,"waiting_input",{usage:e.adapterSession.totalUsage}),this.startIdleDetection(t);break}case"permission.updated":{const i=s.properties;if(i.sessionID!==n)break;const r=i.id;e.pendingPermissions.set(r,i),e.config.autoAccept&&e.client&&n?e.client.postSessionIdPermissionsPermissionId({path:{id:n,permissionID:r},body:{response:"once"},query:{directory:e.workingDirectory}}).then(()=>{e.pendingPermissions.delete(r)}).catch(a=>{console.warn("[OpencodeSdkAdapter] Auto-accept permission failed:",a)}):this.emitEvent({type:"permission_request",sessionId:t,timestamp:o,data:{permissionPrompt:i.title,toolName:i.type}});break}case"session.error":{const{sessionID:i,error:r}=s.properties;if(i&&i!==n)break;let a="OpenCode session error";if(r){const m=r.data;typeof m?.message=="string"?a=`${r.name}: ${m.message}`:a=r.name}this.emitEvent({type:"error",sessionId:t,timestamp:o,data:{text:a}});break}}}handlePartUpdate(t,e,s,o,n){switch(s.type){case"text":{let i;if(o!==void 0)i=o,e.seenTextPartIds.add(s.id);else if(!e.seenTextPartIds.has(s.id))i=s.text,i&&e.seenTextPartIds.add(s.id);else break;if(!i)break;e.currentAssistantText+=i,this.emitEvent({type:"text_delta",sessionId:t,timestamp:n,data:{text:i}});break}case"reasoning":{const i=o??s.text;if(!i)break;this.emitEvent({type:"thinking",sessionId:t,timestamp:n,data:{text:i}});break}case"tool":{const i=s.callID,r=s.tool,a=s.state,m=a.input,h=s.metadata,l=U(m),p=l&&typeof l=="object"&&!Array.isArray(l)?l:{},f=()=>{if(e.emittedToolStarts.has(i))return;e.emittedToolStarts.add(i);const c={...I(r,m,h),actionId:i};this.emitEvent({type:"tool_use_start",sessionId:t,timestamp:n,data:{toolName:r,toolInput:p,toolUseId:i,...c}}),e.adapterSession.messages.push({id:P(),sessionId:t,role:"tool_use",content:`${r}: ${JSON.stringify(p).slice(0,100)}`,timestamp:n,toolName:r,toolInput:p,toolUseId:i})};if(a.status==="running"){f();const c={...I(r,m,h),actionId:i};this.emit("status-change",t,"tool_using",{...c,usage:e.adapterSession.totalUsage})}else if(a.status==="completed"){(r==="todowrite"||r==="todo_write")&&this.syncTodosFromToolCall(e,m).catch(w=>{console.warn("[OpencodeSdkAdapter] \u540C\u6B65 todo \u5230\u6587\u4EF6\u5931\u8D25:",w)}),f();const c=O(a.output);this.emitEvent({type:"tool_use_end",sessionId:t,timestamp:n,data:{toolName:r,toolResult:c,isError:!1,toolUseId:i}}),e.emittedToolStarts.delete(i)}else if(a.status==="error"){f();const c=O(a.error);this.emitEvent({type:"tool_use_end",sessionId:t,timestamp:n,data:{toolName:r,toolResult:c,isError:!0,toolUseId:i}}),e.emittedToolStarts.delete(i)}break}}}getTodoStoreDir(){return g.join(_(),"todos")}async syncTodosFromToolCall(t,e){const s=t.config.agentId;if(!s)return;const o=e.todos;if(!Array.isArray(o)||o.length===0)return;const n=[];for(const l of o)if(l&&typeof l=="object"){const p=l,f=typeof p.content=="string"?p.content.trim():"",c=typeof p.status=="string"?p.status:"",w=typeof p.priority=="string"?p.priority:"";f&&c&&w&&n.push({content:f,status:c,priority:w})}if(n.length===0)return;const i=String(s).replace(/[^a-zA-Z0-9_-]/g,"_"),r=this.getTodoStoreDir(),a=g.join(r,`${i}.json`),m={agentId:s,updatedAt:new Date().toISOString(),background:"OpenCode runtime todos",todos:n};await S.promises.mkdir(r,{recursive:!0});const h=`${a}.tmp`;await S.promises.writeFile(h,JSON.stringify(m,null,2),"utf-8"),await S.promises.rename(h,a)}emitEvent(t){this.emit("event",t)}startIdleDetection(t){this.stopIdleDetection(t);const e=this.sessions.get(t),s=e?.idleCommands?.idleInputCommand;if(!(!e||!s)){if(this.isMessagePollingIdleCommand(s)){e.idlePollLoop||(e.idlePollLoop=new C({getStatus:()=>this.sessions.get(t)?.adapterSession.status,getCommand:()=>this.sessions.get(t)?.idleCommands?.idleInputCommand,isPollingCommand:o=>this.isMessagePollingIdleCommand(o),preDispatchHook:()=>null,dispatchPollingPrompt:(o,n)=>this.sendMessage(t,n?o.trim():this.toIdlePrompt(o),{keepWaitingStatus:!0}),dispatchRegularIdleCommand:o=>this.sendMessage(t,this.toIdlePrompt(o)),pollDelayMs:1500})),e.idlePollLoop.start();return}e.idlePollLoop||(e.idlePollLoop=new C({getStatus:()=>this.sessions.get(t)?.adapterSession.status,getCommand:()=>this.sessions.get(t)?.idleCommands?.idleInputCommand,isPollingCommand:o=>this.isMessagePollingIdleCommand(o),preDispatchHook:()=>null,dispatchPollingPrompt:(o,n)=>this.sendMessage(t,n?o.trim():this.toIdlePrompt(o),{keepWaitingStatus:!0}),dispatchRegularIdleCommand:o=>this.sendMessage(t,this.toIdlePrompt(o)),pollDelayMs:1500})),this.armIdleCheck(t)}}armIdleCheck(t){const e=this.sessions.get(t);if(!e)return;e.idleTimer&&clearTimeout(e.idleTimer);const s=setTimeout(()=>{e.idleTimer===s&&(e.idleTimer=void 0,this.armIdleCheck(t),this.checkIdleState(t))},500);e.idleTimer=s}stopIdleDetection(t){const e=this.sessions.get(t);e?.idlePollLoop?.stop(),e?.idleTimer&&(clearTimeout(e.idleTimer),e.idleTimer=void 0)}checkIdleState(t){const e=this.sessions.get(t);!e||e.adapterSession.status!=="waiting_input"||e.idleCommands?.idleInputCommand&&(this.sendMessage(t,this.toIdlePrompt(e.idleCommands.idleInputCommand)),this.stopIdleDetection(t))}toIdlePrompt(t){const e=t.trim();return this.isMessagePollingIdleCommand(e)?R:e}isMessagePollingIdleCommand(t){const e=t.trim();if(!e)return!1;const s=e.toLowerCase();return s.includes("poll_message")||s.includes("get_message")||e.includes("\u53D6\u6D88\u606F")}}export{Y as OpencodeSdkAdapter};
4
4
 
@@ -1,2 +1,2 @@
1
1
 
2
- export declare const MESSAGE_POLLING_IDLE_PROMPT = "\u3010\u7A7A\u95F2\u76D1\u542C\u6307\u4EE4\u3011\u6B64\u6307\u4EE4\u4EC5\u5728\u5F53\u524D\u6CA1\u6709\u672A\u5B8C\u6210\u4EFB\u52A1\u65F6\u751F\u6548\u3002\u82E5\u4F60\u4ECD\u5728\u5904\u7406\u4EFB\u52A1\uFF08\u5305\u62EC\u591A\u8F6E\u5DE5\u5177\u8C03\u7528\u3001\u7B49\u5F85\u5DE5\u5177\u7ED3\u679C\u3001\u9636\u6BB5\u6027\u601D\u8003\u8F93\u51FA\u7B49\uFF09\uFF0C\u8BF7\u5FFD\u7565\u672C\u6307\u4EE4\u5E76\u7EE7\u7EED\u6267\u884C\u4EFB\u52A1\u3002\u4EC5\u5F53\u786E\u8BA4\u5F53\u524D\u6CA1\u6709\u4EFB\u4F55\u8FDB\u884C\u4E2D\u6216\u672A\u5B8C\u6210\u7684\u4EFB\u52A1\u65F6\uFF0C\u624D\u8C03\u7528 poll_message \u5DE5\u5177\u963B\u585E\u7B49\u5F85\u65B0\u6D88\u606F\u548C\u6D41\u7A0B\u7EBF\u4EFB\u52A1\u63D0\u9192\uFF1B\u6536\u5230\u6D41\u7A0B\u4EFB\u52A1\u63D0\u9192\u540E\u8C03\u7528 my_task \u67E5\u770B\u5DF2\u7531\u540E\u53F0\u9759\u9ED8\u62A2\u5360\u7684\u4EFB\u52A1\u8BE6\u60C5\u5E76\u76F4\u63A5\u5904\u7406\uFF1B\u5B8C\u6210\u4EFB\u52A1\u540E\u8C03\u7528 submit_task_result \u63D0\u4EA4\u7ED3\u679C\uFF0C\u7136\u540E\u7EE7\u7EED poll_message\u3002 \u8C03\u7528 submit_task_result \u65F6\u8BF7\u4E00\u5E76\u4F20\u5165 changeLog\uFF08\u672C\u6B21\u5904\u7406\u7684\u6587\u4EF6/\u5185\u5BB9\u53D8\u66F4\u65E5\u5FD7\uFF0C\u5305\u542B operation \u4E0E path\uFF09\uFF0C\u7528\u4E8E AI \u56DE\u9000\u3002";
2
+ export declare const MESSAGE_POLLING_IDLE_PROMPT = "\u7EE7\u7EED\u5B8C\u6210\u5DE5\u4F5C\uFF0C\u5426\u5219\u8C03\u7528poll_message\u76D1\u542C\u6D88\u606F";
@@ -1,2 +1,2 @@
1
- const s="\u3010\u7A7A\u95F2\u76D1\u542C\u6307\u4EE4\u3011\u6B64\u6307\u4EE4\u4EC5\u5728\u5F53\u524D\u6CA1\u6709\u672A\u5B8C\u6210\u4EFB\u52A1\u65F6\u751F\u6548\u3002\u82E5\u4F60\u4ECD\u5728\u5904\u7406\u4EFB\u52A1\uFF08\u5305\u62EC\u591A\u8F6E\u5DE5\u5177\u8C03\u7528\u3001\u7B49\u5F85\u5DE5\u5177\u7ED3\u679C\u3001\u9636\u6BB5\u6027\u601D\u8003\u8F93\u51FA\u7B49\uFF09\uFF0C\u8BF7\u5FFD\u7565\u672C\u6307\u4EE4\u5E76\u7EE7\u7EED\u6267\u884C\u4EFB\u52A1\u3002\u4EC5\u5F53\u786E\u8BA4\u5F53\u524D\u6CA1\u6709\u4EFB\u4F55\u8FDB\u884C\u4E2D\u6216\u672A\u5B8C\u6210\u7684\u4EFB\u52A1\u65F6\uFF0C\u624D\u8C03\u7528 poll_message \u5DE5\u5177\u963B\u585E\u7B49\u5F85\u65B0\u6D88\u606F\u548C\u6D41\u7A0B\u7EBF\u4EFB\u52A1\u63D0\u9192\uFF1B\u6536\u5230\u6D41\u7A0B\u4EFB\u52A1\u63D0\u9192\u540E\u8C03\u7528 my_task \u67E5\u770B\u5DF2\u7531\u540E\u53F0\u9759\u9ED8\u62A2\u5360\u7684\u4EFB\u52A1\u8BE6\u60C5\u5E76\u76F4\u63A5\u5904\u7406\uFF1B\u5B8C\u6210\u4EFB\u52A1\u540E\u8C03\u7528 submit_task_result \u63D0\u4EA4\u7ED3\u679C\uFF0C\u7136\u540E\u7EE7\u7EED poll_message\u3002 \u8C03\u7528 submit_task_result \u65F6\u8BF7\u4E00\u5E76\u4F20\u5165 changeLog\uFF08\u672C\u6B21\u5904\u7406\u7684\u6587\u4EF6/\u5185\u5BB9\u53D8\u66F4\u65E5\u5FD7\uFF0C\u5305\u542B operation \u4E0E path\uFF09\uFF0C\u7528\u4E8E AI \u56DE\u9000\u3002";export{s as MESSAGE_POLLING_IDLE_PROMPT};
1
+ const _="\u7EE7\u7EED\u5B8C\u6210\u5DE5\u4F5C\uFF0C\u5426\u5219\u8C03\u7528poll_message\u76D1\u542C\u6D88\u606F";export{_ as MESSAGE_POLLING_IDLE_PROMPT};
2
2
 
@@ -1,9 +1,9 @@
1
1
 
2
2
  import { EventEmitter } from "node:events";
3
3
  export type SessionStatus = "starting" | "thinking" | "tool_using" | "waiting_input" | "completed" | "terminated" | "error" | "compacting";
4
- export type ProviderEventType = "ai_request" | "text_delta" | "thinking" | "command_output" | "tool_use_start" | "tool_use_end" | "permission_request" | "ask_user_question" | "exit_plan_mode" | "turn_complete" | "session_complete" | "error" | "context_compaction" | "runtime_capabilities" | "background_command_completed";
4
+ export type ProviderEventType = "ai_request" | "text_delta" | "thinking" | "command_output" | "tool_use_start" | "tool_use_end" | "permission_request" | "ask_user_question" | "exit_plan_mode" | "turn_complete" | "session_complete" | "error" | "context_compaction" | "runtime_capabilities" | "tool_batch_start" | "tool_batch_metrics" | "background_command_completed";
5
5
 
6
- export type ToolActionType = "skill" | "mcp" | "idle" | "edit_file" | "write_file" | "read_file" | "bash" | "search" | "web" | "ai_request" | "lsp" | "notebook" | "other" | "context_compaction" | "runtime_capabilities" | "background_command";
6
+ export type ToolActionType = "skill" | "mcp" | "idle" | "edit_file" | "write_file" | "read_file" | "bash" | "search" | "web" | "ai_request" | "lsp" | "notebook" | "other" | "context_compaction" | "runtime_capabilities" | "tool_batch" | "background_command";
7
7
 
8
8
  export interface ToolActionInfo {
9
9
 
@@ -55,7 +55,13 @@ export interface RuntimeStatusActionInfo {
55
55
  actionResult?: string;
56
56
  actionId?: string;
57
57
 
58
+ actionError?: string;
59
+
58
60
  parentId?: string;
61
+
62
+ batchId?: string;
63
+
64
+ batchMetrics?: RuntimeToolBatchMetrics;
59
65
  usage?: RuntimeTokenUsage;
60
66
  }
61
67
  export interface ProviderEvent {
@@ -84,8 +90,6 @@ export interface ProviderEvent {
84
90
 
85
91
  lastUserMessagePreview?: string;
86
92
 
87
- requestBody?: string;
88
-
89
93
  toolName?: string;
90
94
 
91
95
  rawToolName?: string;
@@ -130,6 +134,8 @@ export interface ProviderEvent {
130
134
 
131
135
  actionResult?: string;
132
136
 
137
+ actionError?: string;
138
+
133
139
  sequence?: number;
134
140
 
135
141
  cwd?: string;
@@ -139,6 +145,14 @@ export interface ProviderEvent {
139
145
  commandLineCount?: number;
140
146
 
141
147
  capabilities?: RuntimeCapabilities;
148
+
149
+ batchId?: string;
150
+
151
+ batchToolCount?: number;
152
+
153
+ batchToolNames?: string[];
154
+
155
+ batchMetrics?: RuntimeToolBatchMetrics;
142
156
  };
143
157
  }
144
158
 
@@ -177,6 +191,25 @@ export interface RuntimeCapabilities {
177
191
  skillGroups?: RuntimeSkillGroup[];
178
192
  }
179
193
 
194
+ export interface RuntimeToolBatchMetrics {
195
+
196
+ toolCount: number;
197
+
198
+ parallelism: number;
199
+
200
+ speedup: number;
201
+
202
+ wallClockMs: number;
203
+
204
+ totalWaitMs?: number;
205
+
206
+ contentionCount: number;
207
+
208
+ failureCount?: number;
209
+
210
+ maxConcurrentObserved?: number;
211
+ }
212
+
180
213
  export interface AdapterInstanceAiConfig {
181
214
  model?: string;
182
215
  baseURL?: string;
@@ -218,6 +251,10 @@ export interface AdapterSessionConfig {
218
251
 
219
252
  memory?: string;
220
253
 
254
+ resumeContext?: string;
255
+
256
+ resumeTranscript?: unknown[];
257
+
221
258
  model?: string;
222
259
 
223
260
  maxTurns?: number;
@@ -1,2 +1,2 @@
1
- import{EventEmitter as S}from"node:events";const m="[temp clipboard paste file]",b=/[A-Z]:(?:\\\\|\\)[^\r\n"'`]*?(?:\\\\|\\)mini-term-clipboard(?:\\\\|\\)paste-\d+\.txt/gi,P=/\/[^\r\n"'`]*?\/mini-term-clipboard\/paste-\d+\.txt/gi,w=/mini-term-clipboard[\\/]paste-\d+\.txt/gi;function d(a){return a.replace(b,m).replace(P,m).replace(w,m)}function $(a){const e=a.trim().replace(/^(["'])(.*)\1$/,"$2");return[b,P,w].some(c=>{c.lastIndex=0;const i=c.exec(e);return!!(i&&i[0]===e)})}function u(a){return typeof a=="string"?d(a):Array.isArray(a)?a.map(e=>u(e)):a&&typeof a=="object"?Object.fromEntries(Object.entries(a).map(([e,c])=>[e,u(c)])):a}const h={get_colleague:"aws-mcp",get_group_rooms:"aws-mcp",get_profile:"aws-mcp",hire_colleague:"aws-mcp",send_group:"aws-mcp",send_private:"aws-mcp",poll_message:"aws-mcp",get_message:"aws-mcp",get_dm_history:"aws-mcp",get_group_history:"aws-mcp",my_task:"aws-mcp",submit_task_result:"aws-mcp",reject_task:"aws-mcp",terminate_task:"aws-mcp"},C=new Set(["aws-mcp","aws-mcp-dev","agents-work-studio"]);function g(a,e){const c=h[e.toLowerCase()];return c&&C.has(a.toLowerCase())?c:a}function L(a){const e=a.trim();if(!e)return e;if(e.includes("__")){const i=e.split("__").filter(Boolean);if(i.length>=3&&i[0].toLowerCase()==="mcp"){const f=i[1],o=i.slice(2).join("__");return`${g(f,o)}/${o}`}if(i.length>=2){const f=i[0],o=i.slice(1).join("__");return`${g(f,o)}/${o}`}}const c=h[e.toLowerCase()];return c?`${c}/${e}`:e}function k(a,e){return a?e?`${g(a,e)}/${e}`:a:e}const E=500;function p(a,e=E){return!a||a.length<=e?a:`${a.slice(0,e)}...\uFF08\u5185\u5BB9\u8FC7\u957F\uFF0C\u5DF2\u622A\u65AD\uFF09`}function j(a,e,c){if(!a)return{actionType:"other",actionLabel:"\u8C03\u7528\u5DE5\u5177"};const i=a.toLowerCase(),f=i.replace(/[_-]/g,""),A=(i.startsWith("mcp__")?i.split("__").slice(2).join("__"):i.startsWith("builtin__")?i.split("__").slice(1).join("__"):i.includes("-mcp__")?i.slice(i.indexOf("-mcp__")+6):i.includes("/")?i.split("/").filter(Boolean).at(-1)||i:i.includes("__")&&i.split("__").pop()||i).replace(/[_-]/g,""),D=t=>Array.isArray(t)?t.map(r=>String(r??"").trim()).filter(r=>r.length>0):[],n=(...t)=>{for(const r of t){if(typeof r=="string"&&r.trim())return d(r);if(Array.isArray(r)&&r.length>0){const l=r[0];if(typeof l=="string"&&l.trim())return d(l)}}},s=(...t)=>{const r=t.map(l=>l.replace(/[_-]/g,""));return r.includes(f)||r.includes(A)},T=D(e?.load_skills);if((i==="task"||i==="task()")&&T.length>0)return{actionType:"skill",actionLabel:"\u52A0\u8F7D\u6280\u80FD",actionDetail:T.join(", ")};if(i==="skill"||i==="load_skill"||i==="disclosecontext"||i.includes("skill")&&!i.startsWith("mcp__")&&!i.includes("mcp_")){let t="";if(Array.isArray(e?.load_skills)&&e.load_skills.length>0)t=e.load_skills.join(", ");else if(typeof e?.skill=="string")t=e.skill;else if(typeof e?.name=="string")t=e.name;else if(e?.args&&typeof e.args=="object"){const r=e.args;typeof r.name=="string"?t=r.name:typeof r.skill=="string"&&(t=r.skill)}return{actionType:"skill",actionLabel:"\u4F7F\u7528\u6280\u80FD",actionDetail:t||void 0}}if(s("edit","editfile","strreplace","editcode","apply_patch","multiedit","replace"))return{actionType:"edit_file",actionLabel:"\u7F16\u8F91\u6587\u4EF6",actionDetail:n(e?.file_path,e?.filePath,e?.path,e?.target_file,e?.targetFile)};if(s("write","writefile","fswrite"))return{actionType:"write_file",actionLabel:"\u5199\u5165\u6587\u4EF6",actionDetail:n(e?.file_path,e?.filePath,e?.path,e?.target_file,e?.targetFile)};if(s("read","readfile","readcode","readmultiplefiles","read_file"))return Array.isArray(e?.paths)?{actionType:"read_file",actionLabel:"\u8BFB\u53D6\u6587\u4EF6",actionDetail:`${e.paths.length}\u4E2A\u6587\u4EF6`}:{actionType:"read_file",actionLabel:"\u8BFB\u53D6\u6587\u4EF6",actionDetail:n(e?.file_path,e?.filePath,e?.path,e?.paths,e?.target_file,e?.targetFile)};if(s("bash","shell","command","executepwsh","controlpwshprocess","execute","run_command","execute_command")){const t=n(e?.command,e?.cmd,e?.argv);return{actionType:"bash",actionLabel:"\u6267\u884C\u547D\u4EE4",actionDetail:p(t)}}if(s("poll_message","get_message"))return{actionType:"idle",actionLabel:"\u76D1\u542C\u6D88\u606F",actionDetail:L(a)};if(s("create_meeting"))return{actionType:"idle",actionLabel:"\u7B49\u5F85\u4F1A\u8BAE\u5F00\u59CB",actionDetail:L(a)};if(s("ask_user_question","askuserquestion"))return{actionType:"other",actionLabel:"\u7B49\u5F85\u56DE\u7B54"};if(c?.mcpServer){const t=c.mcpServer;return{actionType:"mcp",actionLabel:"\u8C03\u7528MCP",actionDetail:k(t,a||"")}}const y=h[a];if(y)return{actionType:"mcp",actionLabel:"\u8C03\u7528MCP",actionDetail:`${y}/${a}`};if(i.startsWith("mcp__")||i.includes("-mcp__")||i.includes("mcp_")&&!i.includes("skill")||i==="kiropowers"){let t="",r="";if(i.startsWith("mcp__")){const _=a.split("__");t=_[1]||"",r=_.slice(2).join("__")||""}else if(i.includes("-mcp__")){const _=i.indexOf("-mcp__");t=i.substring(0,_+4),r=i.substring(_+6)}else i==="kiropowers"?(t="kiro",r=e?.powerName||e?.action||""):(t="mcp",r=a);return{actionType:"mcp",actionLabel:"\u8C03\u7528MCP",actionDetail:k(t,r)||a}}if(s("edit","editfile","strreplace","editcode","apply_patch","multiedit","replace"))return{actionType:"edit_file",actionLabel:"\u7F16\u8F91\u6587\u4EF6",actionDetail:n(e?.file_path,e?.filePath,e?.path,e?.target_file,e?.targetFile)};if(s("write","writefile","fswrite"))return{actionType:"write_file",actionLabel:"\u5199\u5165\u6587\u4EF6",actionDetail:n(e?.file_path,e?.filePath,e?.path,e?.target_file,e?.targetFile)};if(s("read","readfile","readcode","readmultiplefiles","read_file"))return Array.isArray(e?.paths)?{actionType:"read_file",actionLabel:"\u8BFB\u53D6\u6587\u4EF6",actionDetail:`${e.paths.length}\u4E2A\u6587\u4EF6`}:{actionType:"read_file",actionLabel:"\u8BFB\u53D6\u6587\u4EF6",actionDetail:n(e?.file_path,e?.filePath,e?.path,e?.paths,e?.target_file,e?.targetFile)};if(s("bash","shell","command","executepwsh","controlpwshprocess","execute","run_command","execute_command")){const t=n(e?.command,e?.cmd,e?.argv);return{actionType:"bash",actionLabel:"\u6267\u884C\u547D\u4EE4",actionDetail:p(t)}}if(i==="glob"||i==="grep"||i==="find"||i==="search"||i==="grepsearch"||i==="filesearch"){const t=e?.query||e?.pattern;return{actionType:"search",actionLabel:"\u641C\u7D22\u6587\u4EF6",actionDetail:p(t)}}if(i==="webfetch"||i==="websearch"||i==="fetch"||i==="http"||i==="remote_web_search"){const t=e?.url||e?.query;return{actionType:"web",actionLabel:"\u7F51\u7EDC\u8BF7\u6C42",actionDetail:p(t)}}return i.startsWith("lsp")||i.includes("language_server")?{actionType:"lsp",actionLabel:"LSP\u64CD\u4F5C"}:i==="notebookedit"||i.includes("notebook")?{actionType:"notebook",actionLabel:"\u7F16\u8F91Notebook"}:{actionType:"mcp",actionLabel:"\u8C03\u7528MCP",actionDetail:a}}class R extends S{}export{R as BaseProviderAdapter,L as getCanonicalMcpDetail,j as getToolActionInfo,$ as isTransientClipboardPasteFilePath,d as redactTransientClipboardPastePaths,u as redactTransientClipboardPastePathsInValue};
1
+ import{EventEmitter as S}from"node:events";const m="[temp clipboard paste file]",y=/[A-Z]:(?:\\\\|\\)[^\r\n"'`]*?(?:\\\\|\\)mini-term-clipboard(?:\\\\|\\)paste-\d+\.txt/gi,P=/\/[^\r\n"'`]*?\/mini-term-clipboard\/paste-\d+\.txt/gi,w=/mini-term-clipboard[\\/]paste-\d+\.txt/gi;function d(t){return t.replace(y,m).replace(P,m).replace(w,m)}function $(t){const e=t.trim().replace(/^(["'])(.*)\1$/,"$2");return[y,P,w].some(c=>{c.lastIndex=0;const i=c.exec(e);return!!(i&&i[0]===e)})}function u(t){return typeof t=="string"?d(t):Array.isArray(t)?t.map(e=>u(e)):t&&typeof t=="object"?Object.fromEntries(Object.entries(t).map(([e,c])=>[e,u(c)])):t}const h={get_colleague:"aws-mcp",get_group_rooms:"aws-mcp",list_project_members:"aws-mcp",get_profile:"aws-mcp",hire_colleague:"aws-mcp",send_group:"aws-mcp",send_private:"aws-mcp",poll_message:"aws-mcp",get_message:"aws-mcp",get_dm_history:"aws-mcp",get_group_history:"aws-mcp",my_task:"aws-mcp",submit_task_result:"aws-mcp"},C=new Set(["aws-mcp","aws-mcp-dev","agents-work-studio"]);function g(t,e){const c=h[e.toLowerCase()];return c&&C.has(t.toLowerCase())?c:t}function L(t){const e=t.trim();if(!e)return e;if(e.includes("__")){const i=e.split("__").filter(Boolean);if(i.length>=3&&i[0].toLowerCase()==="mcp"){const f=i[1],o=i.slice(2).join("__");return`${g(f,o)}/${o}`}if(i.length>=2){const f=i[0],o=i.slice(1).join("__");return`${g(f,o)}/${o}`}}const c=h[e.toLowerCase()];return c?`${c}/${e}`:e}function k(t,e){return t?e?`${g(t,e)}/${e}`:t:e}const E=500;function p(t,e=E){return!t||t.length<=e?t:`${t.slice(0,e)}...\uFF08\u5185\u5BB9\u8FC7\u957F\uFF0C\u5DF2\u622A\u65AD\uFF09`}function j(t,e,c){if(!t)return{actionType:"other",actionLabel:"\u8C03\u7528\u5DE5\u5177"};const i=t.toLowerCase(),f=i.replace(/[_-]/g,""),A=(i.startsWith("mcp__")?i.split("__").slice(2).join("__"):i.startsWith("builtin__")?i.split("__").slice(1).join("__"):i.includes("-mcp__")?i.slice(i.indexOf("-mcp__")+6):i.includes("/")?i.split("/").filter(Boolean).at(-1)||i:i.includes("__")&&i.split("__").pop()||i).replace(/[_-]/g,""),D=a=>Array.isArray(a)?a.map(r=>String(r??"").trim()).filter(r=>r.length>0):[],n=(...a)=>{for(const r of a){if(typeof r=="string"&&r.trim())return d(r);if(Array.isArray(r)&&r.length>0){const l=r[0];if(typeof l=="string"&&l.trim())return d(l)}}},s=(...a)=>{const r=a.map(l=>l.replace(/[_-]/g,""));return r.includes(f)||r.includes(A)},T=D(e?.load_skills);if((i==="task"||i==="task()")&&T.length>0)return{actionType:"skill",actionLabel:"\u52A0\u8F7D\u6280\u80FD",actionDetail:T.join(", ")};if(i==="skill"||i==="load_skill"||i==="disclosecontext"||i.includes("skill")&&!i.startsWith("mcp__")&&!i.includes("mcp_")){let a="";if(Array.isArray(e?.load_skills)&&e.load_skills.length>0)a=e.load_skills.join(", ");else if(typeof e?.skill=="string")a=e.skill;else if(typeof e?.name=="string")a=e.name;else if(e?.args&&typeof e.args=="object"){const r=e.args;typeof r.name=="string"?a=r.name:typeof r.skill=="string"&&(a=r.skill)}return{actionType:"skill",actionLabel:"\u4F7F\u7528\u6280\u80FD",actionDetail:a||void 0}}if(s("edit","editfile","strreplace","editcode","apply_patch","multiedit","replace"))return{actionType:"edit_file",actionLabel:"\u7F16\u8F91\u6587\u4EF6",actionDetail:n(e?.file_path,e?.filePath,e?.path,e?.target_file,e?.targetFile)};if(s("write","writefile","fswrite"))return{actionType:"write_file",actionLabel:"\u5199\u5165\u6587\u4EF6",actionDetail:n(e?.file_path,e?.filePath,e?.path,e?.target_file,e?.targetFile)};if(s("read","readfile","readcode","readmultiplefiles","read_file"))return Array.isArray(e?.paths)?{actionType:"read_file",actionLabel:"\u8BFB\u53D6\u6587\u4EF6",actionDetail:`${e.paths.length}\u4E2A\u6587\u4EF6`}:{actionType:"read_file",actionLabel:"\u8BFB\u53D6\u6587\u4EF6",actionDetail:n(e?.file_path,e?.filePath,e?.path,e?.paths,e?.target_file,e?.targetFile)};if(s("bash","shell","command","executepwsh","controlpwshprocess","execute","run_command","execute_command")){const a=n(e?.command,e?.cmd,e?.argv);return{actionType:"bash",actionLabel:"\u6267\u884C\u547D\u4EE4",actionDetail:p(a)}}if(s("poll_message","get_message"))return{actionType:"idle",actionLabel:"\u76D1\u542C\u6D88\u606F",actionDetail:L(t)};if(s("create_meeting"))return{actionType:"idle",actionLabel:"\u7B49\u5F85\u4F1A\u8BAE\u5F00\u59CB",actionDetail:L(t)};if(s("ask_user_question","askuserquestion"))return{actionType:"other",actionLabel:"\u7B49\u5F85\u56DE\u7B54"};if(c?.mcpServer){const a=c.mcpServer;return{actionType:"mcp",actionLabel:"\u8C03\u7528MCP",actionDetail:k(a,t||"")}}const b=h[t];if(b)return{actionType:"mcp",actionLabel:"\u8C03\u7528MCP",actionDetail:`${b}/${t}`};if(i.startsWith("mcp__")||i.includes("-mcp__")||i.includes("mcp_")&&!i.includes("skill")||i==="kiropowers"){let a="",r="";if(i.startsWith("mcp__")){const _=t.split("__");a=_[1]||"",r=_.slice(2).join("__")||""}else if(i.includes("-mcp__")){const _=i.indexOf("-mcp__");a=i.substring(0,_+4),r=i.substring(_+6)}else i==="kiropowers"?(a="kiro",r=e?.powerName||e?.action||""):(a="mcp",r=t);return{actionType:"mcp",actionLabel:"\u8C03\u7528MCP",actionDetail:k(a,r)||t}}if(s("edit","editfile","strreplace","editcode","apply_patch","multiedit","replace"))return{actionType:"edit_file",actionLabel:"\u7F16\u8F91\u6587\u4EF6",actionDetail:n(e?.file_path,e?.filePath,e?.path,e?.target_file,e?.targetFile)};if(s("write","writefile","fswrite"))return{actionType:"write_file",actionLabel:"\u5199\u5165\u6587\u4EF6",actionDetail:n(e?.file_path,e?.filePath,e?.path,e?.target_file,e?.targetFile)};if(s("read","readfile","readcode","readmultiplefiles","read_file"))return Array.isArray(e?.paths)?{actionType:"read_file",actionLabel:"\u8BFB\u53D6\u6587\u4EF6",actionDetail:`${e.paths.length}\u4E2A\u6587\u4EF6`}:{actionType:"read_file",actionLabel:"\u8BFB\u53D6\u6587\u4EF6",actionDetail:n(e?.file_path,e?.filePath,e?.path,e?.paths,e?.target_file,e?.targetFile)};if(s("bash","shell","command","executepwsh","controlpwshprocess","execute","run_command","execute_command")){const a=n(e?.command,e?.cmd,e?.argv);return{actionType:"bash",actionLabel:"\u6267\u884C\u547D\u4EE4",actionDetail:p(a)}}if(i==="glob"||i==="grep"||i==="find"||i==="search"||i==="grepsearch"||i==="filesearch"){const a=e?.query||e?.pattern;return{actionType:"search",actionLabel:"\u641C\u7D22\u6587\u4EF6",actionDetail:p(a)}}if(i==="webfetch"||i==="websearch"||i==="fetch"||i==="http"||i==="remote_web_search"){const a=e?.url||e?.query;return{actionType:"web",actionLabel:"\u7F51\u7EDC\u8BF7\u6C42",actionDetail:p(a)}}return i.startsWith("lsp")||i.includes("language_server")?{actionType:"lsp",actionLabel:"LSP\u64CD\u4F5C"}:i==="notebookedit"||i.includes("notebook")?{actionType:"notebook",actionLabel:"\u7F16\u8F91Notebook"}:{actionType:"mcp",actionLabel:"\u8C03\u7528MCP",actionDetail:t}}class R extends S{}export{R as BaseProviderAdapter,L as getCanonicalMcpDetail,j as getToolActionInfo,$ as isTransientClipboardPasteFilePath,d as redactTransientClipboardPastePaths,u as redactTransientClipboardPastePathsInValue};
2
2
 
@@ -0,0 +1,25 @@
1
+
2
+ import type { ImageFormat } from "./types.js";
3
+
4
+ export interface RawImageFactory {
5
+ (input: Buffer, options: {
6
+ raw: {
7
+ width: number;
8
+ height: number;
9
+ channels: 1 | 2 | 3 | 4;
10
+ };
11
+ }): {
12
+ jpeg: (options?: {
13
+ quality?: number;
14
+ }) => {
15
+ toBuffer: () => Promise<Buffer>;
16
+ };
17
+ png: (options?: {
18
+ compressionLevel?: number;
19
+ }) => {
20
+ toBuffer: () => Promise<Buffer>;
21
+ };
22
+ };
23
+ }
24
+
25
+ export declare function encodeRawImage(sharp: RawImageFactory, raw: Buffer, width: number, height: number, format: ImageFormat, quality: number): Promise<Buffer>;
@@ -0,0 +1,2 @@
1
+ const f=6;async function s(n,o,r,t,c,a){const e=n(o,{raw:{width:r,height:t,channels:4}});return c==="png"?e.png({compressionLevel:6}).toBuffer():e.jpeg({quality:a}).toBuffer()}export{s as encodeRawImage};
2
+
@@ -1,5 +1,4 @@
1
-
2
- import { type ScreencastDiffFrame } from "./types.js";
1
+ import { type ImageFormat, type ScreencastDiffFrame } from "./types.js";
3
2
 
4
3
  export declare function getSharpLoadStatus(): string;
5
4
  export declare class ScreencastDiffer {
@@ -25,7 +24,7 @@ export declare class ScreencastDiffer {
25
24
 
26
25
  isSharpReady(): boolean;
27
26
 
28
- processFrame(jpegBuffer: Buffer, width: number, height: number, quality: number): Promise<ScreencastDiffFrame | null>;
27
+ processFrame(jpegBuffer: Buffer, width: number, height: number, quality: number, sourceFormat?: ImageFormat): Promise<ScreencastDiffFrame | null>;
29
28
 
30
29
  private emitFullFrame;
31
30
 
@@ -1,2 +1,2 @@
1
- import{TILE_DIFF_CONFIG as E}from"./types.js";const _=3,I=15;let R=null,S="pending",W=null;async function b(){return R||(W||(W=(async()=>{try{const s=await import("sharp");return R=s.default??s,S="ok",R}catch(s){return S="failed",console.warn("[browser-screencast] sharp \u52A0\u8F7D\u5931\u8D25\uFF0C\u964D\u7EA7\u5168\u5E27\u6A21\u5F0F:",s instanceof Error?s.message:s),null}})()),W)}async function k(){return b()}function P(){return S}function A(s,t,a,e,f,m,o,d){if(!t||t.length!==s.length||a<=0||e<=0)return Number.MAX_SAFE_INTEGER;const h=Math.max(0,f),r=Math.max(0,m),c=Math.min(a,f+o),M=Math.min(e,m+d),H=a*4,{sampleStep:w,diffThreshold:p}=E;let y=0;for(let J=r;J<M;J+=w){const C=J*H;for(let x=h;x<c;x+=w){const F=C+x*4;Math.abs(s[F]-t[F])+Math.abs(s[F+1]-t[F+1])+Math.abs(s[F+2]-t[F+2])>p&&y++}}return y}function N(s,t,a,e,f,m){if(!s||t<=0||f<=0||m<=0)return null;const o=Math.max(0,a),d=Math.max(0,e),h=Math.min(t,a+f),r=Math.min(Math.floor(s.length/4/t),e+m),c=h-o,M=r-d;if(c<=0||M<=0)return null;const H=t*4,w=Buffer.allocUnsafe(c*M*4);for(let p=0;p<M;p++){const y=(d+p)*H+o*4;s.copy(w,p*c*4,y,y+c*4)}return w}async function O(s,t,a){const e=new Array(s.length);let f=0;const m=Math.max(1,Math.min(t,s.length));return await Promise.all(Array.from({length:m},async()=>{for(;;){const o=f++;if(o>=s.length)return;e[o]=await a(s[o])}})),e}class Y{constructor(){this.lastRaw=null,this.lastWidth=0,this.lastHeight=0,this.lastJpeg=null,this.lastJpegWidth=0,this.lastJpegHeight=0,this.consecutiveFullFrames=0,this.highDynamicMode=!1,this.highDynamicFrameCount=0,this.sharpReady=!1,this.sharpCheckDone=!1,k().then(t=>{this.sharpReady=t!==null,this.sharpCheckDone=!0})}isSharpReady(){return this.sharpReady}async processFrame(t,a,e,f){if(!this.sharpCheckDone||!this.sharpReady)return this.emitFullFrame(t,a,e);const m=R;if(!m)return this.emitFullFrame(t,a,e);try{if(this.lastRaw&&this.lastJpeg&&this.lastJpegWidth===a&&this.lastJpegHeight===e&&this.lastJpeg.length===t.length&&this.lastJpeg.equals(t))return null;if(this.highDynamicMode)if(this.highDynamicFrameCount++,this.highDynamicFrameCount<I&&!(this.lastJpegWidth===a&&this.lastJpegHeight===e))this.highDynamicMode=!1;else{if(this.highDynamicFrameCount<I)return this.lastRaw=null,this.lastJpeg=t,this.lastJpegWidth=a,this.lastJpegHeight=e,this.emitFullFrame(t,this.lastWidth||a,this.lastHeight||e);this.highDynamicMode=!1,this.highDynamicFrameCount=0}const o=await m(t).ensureAlpha().raw().toBuffer({resolveWithObject:!0}),d=o.data,h=o.info.width,r=o.info.height;if(!this.lastRaw||this.lastWidth!==h||this.lastHeight!==r)return this.lastRaw=d,this.lastWidth=h,this.lastHeight=r,this.lastJpeg=t,this.lastJpegWidth=a,this.lastJpegHeight=e,this.emitFullFrame(t,h,r);const{tileSize:c,minChangedSamples:M,fullFrameFallbackRatio:H,encodeConcurrency:w}=E,p=Math.max(1,Math.ceil(h/c)),y=Math.max(1,Math.ceil(r/c)),J=p*y,C=[];let x=0;for(let i=0;i<y;i++)for(let u=0;u<p;u++){const l=u*c,n=i*c,g=Math.min(c,h-l),D=Math.min(c,r-n);A(d,this.lastRaw,h,r,l,n,g,D)>=M&&(C.push({x:l,y:n,w:g,h:D}),x++)}if(x===0)return null;if(x>=Math.ceil(J*H))return this.lastRaw=d,this.lastWidth=h,this.lastHeight=r,this.lastJpeg=t,this.lastJpegWidth=a,this.lastJpegHeight=e,this.consecutiveFullFrames++,this.consecutiveFullFrames>=_&&(this.highDynamicMode=!0,this.highDynamicFrameCount=0),this.emitFullFrame(t,h,r);this.consecutiveFullFrames=0,this.highDynamicMode=!1,this.highDynamicFrameCount=0;const F=[];for(let i=0;i<y;i++){let u=0;const l=C.filter(n=>Math.floor(n.y/c)===i);for(l.sort((n,g)=>n.x-g.x);u<l.length;){let n=u;for(;n+1<l.length&&l[n+1].x===l[n].x+l[n].w;)n++;const g=l[u],D=l[n];F.push({x:g.x,y:g.y,w:D.x+D.w-g.x,h:g.h}),u=n+1}}const T=(await O(F,w,async i=>{const u=Math.min(i.w,h-i.x),l=Math.min(i.h,r-i.y),n=N(d,h,i.x,i.y,u,l);if(!n)return null;try{const g=await m(n,{raw:{width:u,height:l,channels:4}}).jpeg({quality:f}).toBuffer();return{x:i.x,y:i.y,w:u,h:l,data:g}}catch{return null}})).filter(i=>i!==null);return T.length===0?null:(this.lastRaw=d,this.lastWidth=h,this.lastHeight=r,this.lastJpeg=t,this.lastJpegWidth=a,this.lastJpegHeight=e,{kind:"tile",width:h,height:r,tiles:T})}catch(o){return console.warn("[browser-screencast] tile diff \u5F02\u5E38\uFF0C\u56DE\u9000\u5168\u5E27:",o),this.emitFullFrame(t,a,e)}}emitFullFrame(t,a,e){return{kind:"full",width:a,height:e,data:t}}reset(){this.lastRaw=null,this.lastWidth=0,this.lastHeight=0,this.lastJpeg=null,this.lastJpegWidth=0,this.lastJpegHeight=0,this.consecutiveFullFrames=0,this.highDynamicMode=!1,this.highDynamicFrameCount=0}dispose(){this.reset()}}export{Y as ScreencastDiffer,P as getSharpLoadStatus};
1
+ import{encodeRawImage as _}from"./frame-encode.js";import{TILE_DIFF_CONFIG as E}from"./types.js";const b=3,L=15;let D=null,W="pending",I=null;async function k(){return D||(I||(I=(async()=>{try{const s=await import("sharp");return D=s.default??s,W="ok",D}catch(s){return W="failed",console.warn("[browser-screencast] sharp \u52A0\u8F7D\u5931\u8D25\uFF0C\u964D\u7EA7\u5168\u5E27\u6A21\u5F0F:",s instanceof Error?s.message:s),null}})()),I)}async function A(){return k()}function z(){return W}function N(s,t,a,e,f,p,c,g){if(!t||t.length!==s.length||a<=0||e<=0)return Number.MAX_SAFE_INTEGER;const y=Math.max(0,f),l=Math.max(0,p),i=Math.min(a,f+c),r=Math.min(e,p+g),J=a*4,{sampleStep:w,diffThreshold:F}=E;let M=0;for(let x=l;x<r;x+=w){const C=x*J;for(let H=y;H<i;H+=w){const d=C+H*4;Math.abs(s[d]-t[d])+Math.abs(s[d+1]-t[d+1])+Math.abs(s[d+2]-t[d+2])>F&&M++}}return M}function O(s,t,a,e,f,p){if(!s||t<=0||f<=0||p<=0)return null;const c=Math.max(0,a),g=Math.max(0,e),y=Math.min(t,a+f),l=Math.min(Math.floor(s.length/4/t),e+p),i=y-c,r=l-g;if(i<=0||r<=0)return null;const J=t*4,w=Buffer.allocUnsafe(i*r*4);for(let F=0;F<r;F++){const M=(g+F)*J+c*4;s.copy(w,F*i*4,M,M+i*4)}return w}async function G(s,t,a){const e=new Array(s.length);let f=0;const p=Math.max(1,Math.min(t,s.length));return await Promise.all(Array.from({length:p},async()=>{for(;;){const c=f++;if(c>=s.length)return;e[c]=await a(s[c])}})),e}class K{constructor(){this.lastRaw=null,this.lastWidth=0,this.lastHeight=0,this.lastJpeg=null,this.lastJpegWidth=0,this.lastJpegHeight=0,this.consecutiveFullFrames=0,this.highDynamicMode=!1,this.highDynamicFrameCount=0,this.sharpReady=!1,this.sharpCheckDone=!1,A().then(t=>{this.sharpReady=t!==null,this.sharpCheckDone=!0})}isSharpReady(){return this.sharpReady}async processFrame(t,a,e,f,p="jpeg"){if(!this.sharpCheckDone||!this.sharpReady)return this.emitFullFrame(t,a,e);const c=D;if(!c)return this.emitFullFrame(t,a,e);try{if(this.lastRaw&&this.lastJpeg&&this.lastJpegWidth===a&&this.lastJpegHeight===e&&this.lastJpeg.length===t.length&&this.lastJpeg.equals(t))return null;if(this.highDynamicMode)if(this.highDynamicFrameCount++,this.highDynamicFrameCount<L&&!(this.lastJpegWidth===a&&this.lastJpegHeight===e))this.highDynamicMode=!1;else{if(this.highDynamicFrameCount<L)return this.lastRaw=null,this.lastJpeg=t,this.lastJpegWidth=a,this.lastJpegHeight=e,this.emitFullFrame(t,this.lastWidth||a,this.lastHeight||e);this.highDynamicMode=!1,this.highDynamicFrameCount=0}const g=await c(t).ensureAlpha().raw().toBuffer({resolveWithObject:!0}),y=g.data,l=g.info.width,i=g.info.height;if(!this.lastRaw||this.lastWidth!==l||this.lastHeight!==i)return this.lastRaw=y,this.lastWidth=l,this.lastHeight=i,this.lastJpeg=t,this.lastJpegWidth=a,this.lastJpegHeight=e,this.emitFullFrame(t,l,i);const{tileSize:r,minChangedSamples:J,fullFrameFallbackRatio:w,encodeConcurrency:F}=E,M=Math.max(1,Math.ceil(l/r)),x=Math.max(1,Math.ceil(i/r)),C=M*x,H=[];let d=0;for(let n=0;n<x;n++)for(let u=0;u<M;u++){const o=u*r,h=n*r,m=Math.min(r,l-o),R=Math.min(r,i-h);N(y,this.lastRaw,l,i,o,h,m,R)>=J&&(H.push({x:o,y:h,w:m,h:R}),d++)}if(d===0)return null;if(d>=Math.ceil(C*w))return this.lastRaw=y,this.lastWidth=l,this.lastHeight=i,this.lastJpeg=t,this.lastJpegWidth=a,this.lastJpegHeight=e,this.consecutiveFullFrames++,this.consecutiveFullFrames>=b&&(this.highDynamicMode=!0,this.highDynamicFrameCount=0),this.emitFullFrame(t,l,i);this.consecutiveFullFrames=0,this.highDynamicMode=!1,this.highDynamicFrameCount=0;const S=[];for(let n=0;n<x;n++){let u=0;const o=H.filter(h=>Math.floor(h.y/r)===n);for(o.sort((h,m)=>h.x-m.x);u<o.length;){let h=u;for(;h+1<o.length&&o[h+1].x===o[h].x+o[h].w;)h++;const m=o[u],R=o[h];S.push({x:m.x,y:m.y,w:R.x+R.w-m.x,h:m.h}),u=h+1}}const T=(await G(S,F,async n=>{const u=Math.min(n.w,l-n.x),o=Math.min(n.h,i-n.y),h=O(y,l,n.x,n.y,u,o);if(!h)return null;try{const m=await _(c,h,u,o,p,f);return{x:n.x,y:n.y,w:u,h:o,data:m}}catch{return null}})).filter(n=>n!==null);return T.length===0?null:(this.lastRaw=y,this.lastWidth=l,this.lastHeight=i,this.lastJpeg=t,this.lastJpegWidth=a,this.lastJpegHeight=e,{kind:"tile",width:l,height:i,tiles:T})}catch(g){return console.warn("[browser-screencast] tile diff \u5F02\u5E38\uFF0C\u56DE\u9000\u5168\u5E27:",g),this.emitFullFrame(t,a,e)}}emitFullFrame(t,a,e){return{kind:"full",width:a,height:e,data:t}}reset(){this.lastRaw=null,this.lastWidth=0,this.lastHeight=0,this.lastJpeg=null,this.lastJpegWidth=0,this.lastJpegHeight=0,this.consecutiveFullFrames=0,this.highDynamicMode=!1,this.highDynamicFrameCount=0}dispose(){this.reset()}}export{K as ScreencastDiffer,z as getSharpLoadStatus};
2
2
 
@@ -1,2 +1,2 @@
1
- import{encodeBrowserFrame as d,isIncrementalBinaryFrame as m}from"./browser-frame-encode.js";import{ScreencastDiffer as g}from"./screencast-differ.js";import{QUALITY_PRESETS as y}from"./types.js";const l=y.original,F=1,p="jpeg",w=30;class x{constructor(t){this.currentPage=null,this.currentSession=null,this.isRunning=!1,this.subscribers=new Set,this.differ=null,this.tileMode=!0,this.frameSeq=0,this.pipeline=Promise.resolve(),this.latestEvent=null,this.draining=!1,this.lastProcessStartedAt=0,this.seedCaptureInFlight=!1,this.lastDeviceWidth=0,this.lastDeviceHeight=0,this.lastGeometryWarnAt=0,this.config={quality:t?.quality??l.quality,maxWidth:t?.maxWidth??l.maxWidth,maxHeight:t?.maxHeight??l.maxHeight,everyNthFrame:t?.everyNthFrame??F,maxFramesPerSecond:t?.maxFramesPerSecond??w,format:t?.format??p,tileMode:t?.tileMode??!0},this.tileMode=this.config.tileMode,this.frameIntervalMs=1e3/Math.max(1,this.config.maxFramesPerSecond),this.tileMode&&(this.differ=new g)}enqueue(t){const e=this.pipeline.then(t);return this.pipeline=e.then(()=>{},()=>{}),e}subscribe(t){if(this.subscribers.add(t),this.subscribers.size===1&&this.currentPage&&!this.isRunning&&this.start(this.currentPage).catch(()=>{}),this.differ&&this.currentPage){let e=!1;if(this.lastFrame?.binaryFrame?m(this.lastFrame.binaryFrame)&&(this.lastFrame=void 0,this.differ.reset(),e=!0):this.tileMode&&(this.differ.reset(),e=!0),e&&!this.seedCaptureInFlight){const s=this.currentPage;this.seedCaptureInFlight=!0,this.forceCaptureAndPush(s).catch(()=>{}).finally(()=>{this.seedCaptureInFlight=!1})}}if(this.lastFrame){const e=this.lastFrame;setImmediate(()=>{if(this.subscribers.has(t))try{t(e)}catch{}})}return()=>{this.subscribers.delete(t)}}async start(t){if(this.currentPage===t&&this.isRunning)return;this.currentPage&&this.currentPage!==t&&await this.stop(this.currentPage),this.currentPage=t;let e;try{e=await t.context().newCDPSession(t)}catch(s){throw this.isRunning=!1,new Error(`Failed to create CDPSession for screencast: ${s instanceof Error?s.message:String(s)}`)}this.currentSession=e,e.on("Page.screencastFrame",s=>{this.handleScreencastFrame(s,t)});try{await e.send("Page.startScreencast",{format:this.config.format,quality:this.config.quality,maxWidth:this.config.maxWidth,maxHeight:this.config.maxHeight,everyNthFrame:this.config.everyNthFrame,...this.config.maxFramesPerSecond?{maxFramesPerSecond:this.config.maxFramesPerSecond}:{}}),this.isRunning=!0}catch(s){try{await e.detach()}catch{}throw this.currentSession=null,this.isRunning=!1,new Error(`Failed to start screencast: ${s instanceof Error?s.message:String(s)}`)}}handleScreencastFrame(t,e){if(this.ackFrame(t),e===this.currentPage){if(this.subscribers.size===0){this.lastFrame=void 0;return}this.latestEvent={event:t,page:e},this.draining||(this.draining=!0,this.drainPendingFrames())}}async drainPendingFrames(){try{for(;this.latestEvent;){const{event:t,page:e}=this.latestEvent;this.latestEvent=null;const s=this.frameIntervalMs-(Date.now()-this.lastProcessStartedAt);s>0&&await new Promise(i=>setTimeout(i,s)),this.lastProcessStartedAt=Date.now(),await this.enqueue(()=>this.processScreencastFrame(t,e))}}catch{}finally{this.draining=!1}}ackFrame(t){this.currentSession&&t.sessionId&&this.currentSession.send("Page.screencastFrameAck",{sessionId:t.sessionId}).catch(()=>{})}async processScreencastFrame(t,e){if(e!==this.currentPage)return;const s=t.data??"",i=t.metadata?.deviceWidth??0,r=t.metadata?.deviceHeight??0;let n="";try{n=e.url()}catch{}if(i>0&&r>0&&this.lastDeviceWidth>0&&this.lastDeviceHeight>0&&(i!==this.lastDeviceWidth||r!==this.lastDeviceHeight)){this.differ?.reset();const a=Date.now();a-this.lastGeometryWarnAt>=1e3&&(this.lastGeometryWarnAt=a,console.warn(`[browser-screencast] \u9875\u9762\u51E0\u4F55\u53D8\u5316 ${this.lastDeviceWidth}x${this.lastDeviceHeight} -> ${i}x${r}\uFF0C\u91CD\u7F6E\u5DEE\u5206\u57FA\u51C6`))}if(i>0&&r>0&&(this.lastDeviceWidth=i,this.lastDeviceHeight=r),this.tileMode&&this.differ&&s){const a=Buffer.from(s,"base64"),c=await this.differ.processFrame(a,i,r,this.config.quality);if(!c)return;const f=d(c,this.frameSeq++,{url:n}),o={dataUrl:"",base64:"",width:i,height:r,timestamp:Date.now(),url:n,binaryFrame:f};this.lastFrame=o;for(const u of this.subscribers)try{u(o)}catch{}return}const h={dataUrl:`data:image/${this.config.format==="png"?"png":"jpeg"};base64,${s}`,base64:s,width:i,height:r,timestamp:Date.now(),url:n};this.lastFrame=h;for(const a of this.subscribers)try{a(h)}catch{}}async stop(t){if(this.currentPage!==t)return;const e=this.currentSession;if(e){try{await e.send("Page.stopScreencast")}catch{}try{await e.detach()}catch{}}this.currentSession=null,this.isRunning=!1,this.currentPage=null,this.latestEvent=null,this.differ?.reset()}async stopAll(){this.currentPage&&await this.stop(this.currentPage)}async capture(t){if(this.lastFrame&&this.currentPage===t)return this.lastFrame;try{const s=(await t.screenshot({type:this.config.format==="png"?"png":"jpeg",quality:this.config.format==="png"?void 0:this.config.quality})).toString("base64"),i=`data:image/${this.config.format==="png"?"png":"jpeg"};base64,${s}`,r=t.viewportSize();return{dataUrl:i,base64:s,width:r?.width??0,height:r?.height??0,timestamp:Date.now(),url:t.url()}}catch{return}}getLastFrame(){return this.lastFrame}getCurrentCdpSession(){return this.currentSession??void 0}async restartAfterNavigation(t){if(this.currentPage===t)try{await this.stop(t)}catch{}let e=!1;for(let s=0;s<2;s++)try{await this.start(t),e=!0;break}catch{s===0&&await new Promise(i=>setTimeout(i,300))}e||(this.isRunning=!1,this.currentSession=null,this.currentPage=null),await this.forceCaptureAndPush(t).catch(()=>{})}async updateQuality(t){this.config={...this.config,quality:t.quality,maxWidth:t.maxWidth,maxHeight:t.maxHeight};const e=this.currentPage;if(!e||!this.isRunning)return!1;try{await this.stop(e)}catch{}try{await this.start(e)}catch{return!1}return this.forceCaptureAndPush(e).catch(()=>{}),!0}async forceCaptureAndPush(t){!t||t.isClosed()||await this.enqueue(()=>this.doForceCaptureAndPush(t))}async doForceCaptureAndPush(t){let e;const s=t.viewportSize(),i=s?.width??0,r=s?.height??0;if(this.currentSession)try{e=(await this.currentSession.send("Page.captureScreenshot",{format:this.config.format==="png"?"png":"jpeg",quality:this.config.format==="png"?void 0:this.config.quality})).data}catch{}if(!e)try{e=(await t.screenshot({type:this.config.format==="png"?"png":"jpeg",quality:this.config.format==="png"?void 0:this.config.quality})).toString("base64")}catch{return}let n="";try{n=t.url()}catch{}if(this.tileMode&&this.differ&&e){this.differ.reset();const a=Buffer.from(e,"base64"),c=await this.differ.processFrame(a,i,r,this.config.quality);if(c){const f=d(c,this.frameSeq++,{url:n}),o={dataUrl:"",base64:"",width:i,height:r,timestamp:Date.now(),url:n,binaryFrame:f};this.lastFrame=o;for(const u of this.subscribers)try{u(o)}catch{}return}}const h={dataUrl:`data:image/${this.config.format==="png"?"png":"jpeg"};base64,${e}`,base64:e,width:i,height:r,timestamp:Date.now(),url:n};this.lastFrame=h;for(const a of this.subscribers)try{a(h)}catch{}}async dispose(){await this.stopAll(),this.latestEvent=null,this.differ?.dispose(),this.differ=null,this.subscribers.clear(),this.lastFrame=void 0}}export{x as ScreencastManager};
1
+ import{encodeBrowserFrame as d,isIncrementalBinaryFrame as m}from"./browser-frame-encode.js";import{ScreencastDiffer as g}from"./screencast-differ.js";import{QUALITY_PRESETS as y}from"./types.js";const f=y.original,F=1,p=f.format,w=30;class x{constructor(t){this.currentPage=null,this.currentSession=null,this.isRunning=!1,this.subscribers=new Set,this.differ=null,this.tileMode=!0,this.frameSeq=0,this.pipeline=Promise.resolve(),this.latestEvent=null,this.draining=!1,this.lastProcessStartedAt=0,this.seedCaptureInFlight=!1,this.lastDeviceWidth=0,this.lastDeviceHeight=0,this.lastGeometryWarnAt=0,this.config={quality:t?.quality??f.quality,maxWidth:t?.maxWidth??f.maxWidth,maxHeight:t?.maxHeight??f.maxHeight,everyNthFrame:t?.everyNthFrame??F,maxFramesPerSecond:t?.maxFramesPerSecond??w,format:t?.format??p,tileMode:t?.tileMode??!0},this.tileMode=this.config.tileMode,this.frameIntervalMs=1e3/Math.max(1,this.config.maxFramesPerSecond),this.tileMode&&(this.differ=new g)}enqueue(t){const e=this.pipeline.then(t);return this.pipeline=e.then(()=>{},()=>{}),e}subscribe(t){if(this.subscribers.add(t),this.subscribers.size===1&&this.currentPage&&!this.isRunning&&this.start(this.currentPage).catch(()=>{}),this.differ&&this.currentPage){let e=!1;if(this.lastFrame?.binaryFrame?m(this.lastFrame.binaryFrame)&&(this.lastFrame=void 0,this.differ.reset(),e=!0):this.tileMode&&(this.differ.reset(),e=!0),e&&!this.seedCaptureInFlight){const s=this.currentPage;this.seedCaptureInFlight=!0,this.forceCaptureAndPush(s).catch(()=>{}).finally(()=>{this.seedCaptureInFlight=!1})}}if(this.lastFrame){const e=this.lastFrame;setImmediate(()=>{if(this.subscribers.has(t))try{t(e)}catch{}})}return()=>{this.subscribers.delete(t)}}async start(t){if(this.currentPage===t&&this.isRunning)return;this.currentPage&&this.currentPage!==t&&await this.stop(this.currentPage),this.currentPage=t;let e;try{e=await t.context().newCDPSession(t)}catch(s){throw this.isRunning=!1,new Error(`Failed to create CDPSession for screencast: ${s instanceof Error?s.message:String(s)}`)}this.currentSession=e,e.on("Page.screencastFrame",s=>{this.handleScreencastFrame(s,t)});try{await e.send("Page.startScreencast",{format:this.config.format,...this.config.format==="jpeg"?{quality:this.config.quality}:{},maxWidth:this.config.maxWidth,maxHeight:this.config.maxHeight,everyNthFrame:this.config.everyNthFrame,...this.config.maxFramesPerSecond?{maxFramesPerSecond:this.config.maxFramesPerSecond}:{}}),this.isRunning=!0}catch(s){try{await e.detach()}catch{}throw this.currentSession=null,this.isRunning=!1,new Error(`Failed to start screencast: ${s instanceof Error?s.message:String(s)}`)}}handleScreencastFrame(t,e){if(this.ackFrame(t),e===this.currentPage){if(this.subscribers.size===0){this.lastFrame=void 0;return}this.latestEvent={event:t,page:e},this.draining||(this.draining=!0,this.drainPendingFrames())}}async drainPendingFrames(){try{for(;this.latestEvent;){const{event:t,page:e}=this.latestEvent;this.latestEvent=null;const s=this.frameIntervalMs-(Date.now()-this.lastProcessStartedAt);s>0&&await new Promise(i=>setTimeout(i,s)),this.lastProcessStartedAt=Date.now(),await this.enqueue(()=>this.processScreencastFrame(t,e))}}catch{}finally{this.draining=!1}}ackFrame(t){this.currentSession&&t.sessionId&&this.currentSession.send("Page.screencastFrameAck",{sessionId:t.sessionId}).catch(()=>{})}async processScreencastFrame(t,e){if(e!==this.currentPage)return;const s=t.data??"",i=t.metadata?.deviceWidth??0,r=t.metadata?.deviceHeight??0;let n="";try{n=e.url()}catch{}if(i>0&&r>0&&this.lastDeviceWidth>0&&this.lastDeviceHeight>0&&(i!==this.lastDeviceWidth||r!==this.lastDeviceHeight)){this.differ?.reset();const a=Date.now();a-this.lastGeometryWarnAt>=1e3&&(this.lastGeometryWarnAt=a,console.warn(`[browser-screencast] \u9875\u9762\u51E0\u4F55\u53D8\u5316 ${this.lastDeviceWidth}x${this.lastDeviceHeight} -> ${i}x${r}\uFF0C\u91CD\u7F6E\u5DEE\u5206\u57FA\u51C6`))}if(i>0&&r>0&&(this.lastDeviceWidth=i,this.lastDeviceHeight=r),this.tileMode&&this.differ&&s){const a=Buffer.from(s,"base64"),c=await this.differ.processFrame(a,i,r,this.config.quality,this.config.format);if(!c)return;const u=d(c,this.frameSeq++,{url:n}),o={dataUrl:"",base64:"",width:i,height:r,timestamp:Date.now(),url:n,binaryFrame:u};this.lastFrame=o;for(const l of this.subscribers)try{l(o)}catch{}return}const h={dataUrl:`data:image/${this.config.format==="png"?"png":"jpeg"};base64,${s}`,base64:s,width:i,height:r,timestamp:Date.now(),url:n};this.lastFrame=h;for(const a of this.subscribers)try{a(h)}catch{}}async stop(t){if(this.currentPage!==t)return;const e=this.currentSession;if(e){try{await e.send("Page.stopScreencast")}catch{}try{await e.detach()}catch{}}this.currentSession=null,this.isRunning=!1,this.currentPage=null,this.latestEvent=null,this.differ?.reset()}async stopAll(){this.currentPage&&await this.stop(this.currentPage)}async capture(t){if(this.lastFrame&&this.currentPage===t)return this.lastFrame;try{const s=(await t.screenshot({type:this.config.format==="png"?"png":"jpeg",quality:this.config.format==="png"?void 0:this.config.quality})).toString("base64"),i=`data:image/${this.config.format==="png"?"png":"jpeg"};base64,${s}`,r=t.viewportSize();return{dataUrl:i,base64:s,width:r?.width??0,height:r?.height??0,timestamp:Date.now(),url:t.url()}}catch{return}}getLastFrame(){return this.lastFrame}getCurrentCdpSession(){return this.currentSession??void 0}async restartAfterNavigation(t){if(this.currentPage===t)try{await this.stop(t)}catch{}let e=!1;for(let s=0;s<2;s++)try{await this.start(t),e=!0;break}catch{s===0&&await new Promise(i=>setTimeout(i,300))}e||(this.isRunning=!1,this.currentSession=null,this.currentPage=null),await this.forceCaptureAndPush(t).catch(()=>{})}async updateQuality(t){this.config={...this.config,format:t.format,quality:t.quality,maxWidth:t.maxWidth,maxHeight:t.maxHeight},this.differ?.reset();const e=this.currentPage;if(!e||!this.isRunning)return!1;try{await this.stop(e)}catch{}try{await this.start(e)}catch{return!1}return this.forceCaptureAndPush(e).catch(()=>{}),!0}async forceCaptureAndPush(t){!t||t.isClosed()||await this.enqueue(()=>this.doForceCaptureAndPush(t))}async doForceCaptureAndPush(t){let e;const s=t.viewportSize(),i=s?.width??0,r=s?.height??0;if(this.currentSession)try{e=(await this.currentSession.send("Page.captureScreenshot",{format:this.config.format==="png"?"png":"jpeg",quality:this.config.format==="png"?void 0:this.config.quality})).data}catch{}if(!e)try{e=(await t.screenshot({type:this.config.format==="png"?"png":"jpeg",quality:this.config.format==="png"?void 0:this.config.quality})).toString("base64")}catch{return}let n="";try{n=t.url()}catch{}if(this.tileMode&&this.differ&&e){this.differ.reset();const a=Buffer.from(e,"base64"),c=await this.differ.processFrame(a,i,r,this.config.quality,this.config.format);if(c){const u=d(c,this.frameSeq++,{url:n}),o={dataUrl:"",base64:"",width:i,height:r,timestamp:Date.now(),url:n,binaryFrame:u};this.lastFrame=o;for(const l of this.subscribers)try{l(o)}catch{}return}}const h={dataUrl:`data:image/${this.config.format==="png"?"png":"jpeg"};base64,${e}`,base64:e,width:i,height:r,timestamp:Date.now(),url:n};this.lastFrame=h;for(const a of this.subscribers)try{a(h)}catch{}}async dispose(){await this.stopAll(),this.latestEvent=null,this.differ?.dispose(),this.differ=null,this.subscribers.clear(),this.lastFrame=void 0}}export{x as ScreencastManager};
2
2
 
@@ -77,6 +77,8 @@ export declare function parseBrowserKey(key: string): {
77
77
  browserId: string;
78
78
  } | null;
79
79
 
80
+ export type ImageFormat = "jpeg" | "png";
81
+
80
82
  export interface ScreencastConfig {
81
83
 
82
84
  quality?: number;
@@ -89,7 +91,7 @@ export interface ScreencastConfig {
89
91
 
90
92
  maxFramesPerSecond?: number;
91
93
 
92
- format?: "jpeg" | "png";
94
+ format?: ImageFormat;
93
95
 
94
96
  tileMode?: boolean;
95
97
  }
@@ -184,6 +186,8 @@ export type QualityPreset = "original" | "hd" | "smooth";
184
186
 
185
187
  export interface QualityPresetConfig {
186
188
 
189
+ format: ImageFormat;
190
+
187
191
  quality: number;
188
192
 
189
193
  maxWidth: number;
@@ -1,2 +1,2 @@
1
- const e="default";function r(t,o){return`${t}::${o}`}function n(t){const o=t.indexOf("::");return o<0?null:{agentId:t.slice(0,o),browserId:t.slice(o+2)}}const S=8,_=4,i=5,s=0,E=0,x=7891,c="127.0.0.1",a=2*1024*1024,p=10*1e3,T=30*1e3,I=60*1e3,l={original:{quality:80,maxWidth:1280,maxHeight:800},hd:{quality:60,maxWidth:1024,maxHeight:640},smooth:{quality:45,maxWidth:800,maxHeight:500}};function d(t){return t==="original"||t==="hd"||t==="smooth"}const A={tileSize:160,sampleStep:8,diffThreshold:24,minChangedSamples:1,fullFrameFallbackRatio:.5,encodeConcurrency:8};export{e as DEFAULT_BROWSER_ID,I as IDLE_CHECK_INTERVAL_MS,E as IDLE_TIMEOUT_MS,i as MAX_PAGES_PER_SESSION,S as MAX_SESSIONS,_ as MAX_SESSIONS_PER_AGENT,l as QUALITY_PRESETS,s as SESSION_TIMEOUT_MS,A as TILE_DIFF_CONFIG,p as WS_DEFAULT_HEARTBEAT_MS,T as WS_DEFAULT_IDLE_TIMEOUT_MS,a as WS_DEFAULT_MAX_SEND_BYTES,c as WS_HOST,x as WS_PORT,d as isQualityPreset,r as makeBrowserKey,n as parseBrowserKey};
1
+ const e="default";function r(t,o){return`${t}::${o}`}function n(t){const o=t.indexOf("::");return o<0?null:{agentId:t.slice(0,o),browserId:t.slice(o+2)}}const S=8,_=4,i=5,s=0,E=0,x=7891,a="127.0.0.1",c=6*1024*1024,p=10*1e3,T=30*1e3,I=60*1e3,l={original:{format:"png",quality:0,maxWidth:1280,maxHeight:800},hd:{format:"jpeg",quality:80,maxWidth:1024,maxHeight:640},smooth:{format:"jpeg",quality:60,maxWidth:800,maxHeight:500}};function m(t){return t==="original"||t==="hd"||t==="smooth"}const d={tileSize:160,sampleStep:8,diffThreshold:24,minChangedSamples:1,fullFrameFallbackRatio:.5,encodeConcurrency:8};export{e as DEFAULT_BROWSER_ID,I as IDLE_CHECK_INTERVAL_MS,E as IDLE_TIMEOUT_MS,i as MAX_PAGES_PER_SESSION,S as MAX_SESSIONS,_ as MAX_SESSIONS_PER_AGENT,l as QUALITY_PRESETS,s as SESSION_TIMEOUT_MS,d as TILE_DIFF_CONFIG,p as WS_DEFAULT_HEARTBEAT_MS,T as WS_DEFAULT_IDLE_TIMEOUT_MS,c as WS_DEFAULT_MAX_SEND_BYTES,a as WS_HOST,x as WS_PORT,m as isQualityPreset,r as makeBrowserKey,n as parseBrowserKey};
2
2
 
@@ -1,3 +1,3 @@
1
- import{Client as T}from"@modelcontextprotocol/sdk/client/index.js";import{StdioClientTransport as g}from"@modelcontextprotocol/sdk/client/stdio.js";const w=100,y=15e3;class _{constructor(n){this.client=null,this.transport=null,this.stderrLines=[],this.closed=!1,this.closing=!1,this.options=n}isConnected(){return!this.closed&&this.client!==null}getRecentStderr(n=20){return this.stderrLines.slice(-n)}async start(){const{command:n,args:s,cwd:t}=this.options,e=new g({command:n,args:s??[],...t?{cwd:t}:{},env:S({...process.env,...this.options.env??{}}),stderr:"pipe"}),c=this.options.maxStderrLines??w;try{const r=e.stderr;if(r){let l="";r.setEncoding?.("utf8"),r.on("data",a=>{const m=typeof a=="string"?a:Buffer.from(a).toString("utf8");l+=m;const h=l.split(/\r?\n/);l=h.pop()??"";for(const d of h)d.trim()&&(this.stderrLines.push(d),this.stderrLines.length>c&&this.stderrLines.splice(0,this.stderrLines.length-c))})}}catch{}e.onclose=()=>{this.closed||this.closing||(this.closed=!0,this.client=null,this.transport=null,this.options.onUnexpectedClose?.(null))},e.onerror=()=>{};const o=new T({name:"aws-runtime-bridge",version:"1.0.0"}),p=this.options.initTimeoutMs??y;await u(o.connect(e),p,"nuphus-mcp initialize timeout");const{tools:f}=await u(o.listTools(),p,"nuphus-mcp listTools timeout");return this.client=o,this.transport=e,this.closed=!1,f.map(r=>({name:r.name,...r.description?{description:r.description}:{},inputSchema:r.inputSchema??{type:"object",properties:{}}}))}async callTool(n,s,t){const e=this.client;if(!e||this.closed)throw new Error("nuphus-mcp connection is not active");const c=await u(e.callTool({name:n,arguments:s},void 0,{timeout:t}),t+5e3,`nuphus-mcp tool ${n} timeout after ${t}ms`);return E(c)}async close(){if(this.closing||this.closed)return;this.closing=!0,this.closed=!0;const n=this.client;this.client=null,this.transport=null;try{await n?.close()}catch{}this.closing=!1}}function E(i){const s=(Array.isArray(i?.content)?i.content:[]).filter(t=>t?.type==="text").map(t=>t.text);if(s.length>0){const t=s.join(`
2
- `);return i?.isError?`nuphus-mcp tool error: ${t}`:t}return JSON.stringify(i??{})}function S(i){const n={};for(const[s,t]of Object.entries(i))t!==void 0&&(n[s]=t);return n}function u(i,n,s){return new Promise((t,e)=>{const c=setTimeout(()=>e(new Error(s)),n);i.then(o=>{clearTimeout(c),t(o)},o=>{clearTimeout(c),e(o instanceof Error?o:new Error(String(o)))})})}export{_ as DesktopMcpConnection,E as callToolResultToText};
1
+ import{Client as T}from"@modelcontextprotocol/sdk/client/index.js";import{StdioClientTransport as g}from"@modelcontextprotocol/sdk/client/stdio.js";import{sanitizeEnvForChild as w}from"../utils/env-safety.js";const E=100,y=15e3;class C{constructor(n){this.client=null,this.transport=null,this.stderrLines=[],this.closed=!1,this.closing=!1,this.options=n}isConnected(){return!this.closed&&this.client!==null}getRecentStderr(n=20){return this.stderrLines.slice(-n)}async start(){const{command:n,args:i,cwd:t}=this.options,e=new g({command:n,args:i??[],...t?{cwd:t}:{},env:L({...process.env,...w(this.options.env)}),stderr:"pipe"}),c=this.options.maxStderrLines??E;try{const r=e.stderr;if(r){let l="";r.setEncoding?.("utf8"),r.on("data",a=>{const m=typeof a=="string"?a:Buffer.from(a).toString("utf8");l+=m;const h=l.split(/\r?\n/);l=h.pop()??"";for(const d of h)d.trim()&&(this.stderrLines.push(d),this.stderrLines.length>c&&this.stderrLines.splice(0,this.stderrLines.length-c))})}}catch{}e.onclose=()=>{this.closed||this.closing||(this.closed=!0,this.client=null,this.transport=null,this.options.onUnexpectedClose?.(null))},e.onerror=()=>{};const o=new T({name:"aws-runtime-bridge",version:"1.0.0"}),p=this.options.initTimeoutMs??y;await u(o.connect(e),p,"nuphus-mcp initialize timeout");const{tools:f}=await u(o.listTools(),p,"nuphus-mcp listTools timeout");return this.client=o,this.transport=e,this.closed=!1,f.map(r=>({name:r.name,...r.description?{description:r.description}:{},inputSchema:r.inputSchema??{type:"object",properties:{}}}))}async callTool(n,i,t){const e=this.client;if(!e||this.closed)throw new Error("nuphus-mcp connection is not active");const c=await u(e.callTool({name:n,arguments:i},void 0,{timeout:t}),t+5e3,`nuphus-mcp tool ${n} timeout after ${t}ms`);return S(c)}async close(){if(this.closing||this.closed)return;this.closing=!0,this.closed=!0;const n=this.client;this.client=null,this.transport=null;try{await n?.close()}catch{}this.closing=!1}}function S(s){const i=(Array.isArray(s?.content)?s.content:[]).filter(t=>t?.type==="text").map(t=>t.text);if(i.length>0){const t=i.join(`
2
+ `);return s?.isError?`nuphus-mcp tool error: ${t}`:t}return JSON.stringify(s??{})}function L(s){const n={};for(const[i,t]of Object.entries(s))t!==void 0&&(n[i]=t);return n}function u(s,n,i){return new Promise((t,e)=>{const c=setTimeout(()=>e(new Error(i)),n);s.then(o=>{clearTimeout(c),t(o)},o=>{clearTimeout(c),e(o instanceof Error?o:new Error(String(o)))})})}export{C as DesktopMcpConnection,S as callToolResultToText};
3
3
 
@@ -1,8 +1,8 @@
1
- import{promises as S}from"node:fs";import y from"node:path";import{pathToFileURL as C}from"node:url";import{Router as j}from"express";import{getAcodeDataHome as T}from"../config.js";import{validateToken as k}from"../middleware/auth.js";import{getAcodeBgManager as h}from"../services/acode-bg-manager.js";import{getReleasedAcodeEntryPath as B}from"../services/acode-package.js";import{createLogger as E}from"../utils/logger.js";import{listPtySessions as _}from"./pty.js";let m=null;function I(){return m||(m=(async()=>{try{const e=B(),t=y.join(y.dirname(e),"background-command-store.js"),d=await import(C(t).href);return d.BackgroundCommandStore?new d.BackgroundCommandStore:(l.warn("[acode-bg-tasks] BackgroundCommandStore \u4E0D\u53EF\u7528,\u78C1\u76D8\u515C\u5E95\u7981\u7528"),null)}catch(e){return l.warn("[acode-bg-tasks] \u52A0\u8F7D BackgroundCommandStore \u5931\u8D25: %s",e?.message),null}})().then(e=>(e||(m=null),e)),m)}const l=E("acode-bg-tasks"),p=j();function L(e){return String(e).replace(/[^a-zA-Z0-9_-]/g,"_")}function v(e){return y.join(T(),"bg-tasks",L(e),"state.json")}p.get("/acode-bg-tasks/:agentId",k,async(e,t)=>{const d=e.params.agentId,o=Array.isArray(d)?d[0]:d;if(!o||!String(o).trim()){t.status(400).json({ok:!1,error:"agentId is required"});return}try{const s=await h();if(s&&typeof s.listTasksWithReconcile=="function"){const r=e.query.status&&String(e.query.status)!=="all"?String(e.query.status):void 0,n=await s.listTasksWithReconcile(String(o),r);t.json({ok:!0,agentId:String(o),updatedAt:Date.now(),tasks:n});return}}catch(s){l.warn("[acode-bg-tasks] \u5185\u5B58\u5BF9\u8D26\u5217\u8868\u5931\u8D25\uFF0C\u964D\u7EA7\u78C1\u76D8\u8BFB\u53D6: %s",s?.message)}const i=v(String(o));try{const s=await S.readFile(i,"utf-8"),r=JSON.parse(s),u=(Array.isArray(r.tasks)?r.tasks:[]).map(c=>{const a=c;return{taskId:a.taskId,status:a.status,command:a.commandPreview??a.command,commandPreview:a.commandPreview,description:typeof a.description=="string"?a.description:void 0,cwd:a.cwd,startedAt:a.startedAt,finishedAt:a.finishedAt,exitCode:a.exitCode,signal:a.signal,outputLineCount:a.outputLineCount,outputBytes:a.outputBytes}});t.json({ok:!0,agentId:String(o),updatedAt:typeof r.updatedAt=="number"?r.updatedAt:null,tasks:u})}catch(s){if((typeof s=="object"&&s!==null?Reflect.get(s,"code"):void 0)==="ENOENT"){t.json({ok:!0,agentId:String(o),updatedAt:null,tasks:[]});return}if(s instanceof SyntaxError){l.warn("[acode-bg-tasks] \u6587\u4EF6\u635F\u574F\uFF08JSON \u89E3\u6790\u5931\u8D25\uFF09: %s",i),t.json({ok:!0,agentId:String(o),updatedAt:null,tasks:[]});return}const n=s;l.error("[acode-bg-tasks] \u8BFB\u53D6\u5931\u8D25: %s",n.message),t.status(500).json({ok:!1,error:n.message})}}),p.get("/acode-agent-pty-sessions/:agentId",k,(e,t)=>{const d=e.params.agentId,o=Array.isArray(d)?d[0]:d;if(!o||!String(o).trim()){t.status(400).json({ok:!1,error:"agentId is required"});return}const i=String(o),r=_().filter(n=>n.ownerUserId===i);t.json({ok:!0,agentId:i,sessions:r})});const P=15e3;function w(e){return{taskId:e.taskId,status:e.status,exitCode:e.exitCode,signal:e.signal,startedAt:e.startedAt,finishedAt:e.finishedAt,command:e.command,lines:e.lines,nextSeq:e.nextSeq,totalLines:e.totalLines,totalBytes:e.totalBytes,truncated:e.truncated}}async function x(e,t){let o=null;try{o=await S.open(e,"r")}catch(i){if(i?.code==="ENOENT")return{text:[],fileExists:!1,truncated:!1};throw i}try{const s=(await o.stat()).size;if(s===0)return{text:[],fileExists:!0,truncated:!1};const r=Math.min(s,2097152),n=s-r,u=Buffer.alloc(r);await o.read(u,0,r,n);const a=u.toString("utf-8").split(`
2
- `);return n>0&&a.shift(),{text:a.slice(-t),fileExists:!0,truncated:r<s}}finally{await o.close()}}p.get("/acode-bg-tasks/:agentId/:taskId/output",k,(e,t)=>{(async()=>{const d=String(e.params.agentId),o=String(e.params.taskId),i=Math.min(2e3,Math.max(100,Number(e.query.tailLines)||500));try{const s=await h();if(s){const r=s.getTaskOutputSnapshot(d,o);if(r){t.json({ok:!0,source:"memory",...w(r)});return}}}catch(s){l.warn("[acode-bg-tasks] \u5185\u5B58\u5FEB\u7167\u8BFB\u53D6\u5931\u8D25,\u964D\u7EA7\u8D70\u78C1\u76D8: %s",s?.message)}try{const s=await I();if(!s){t.status(503).json({ok:!1,error:"store unavailable"});return}const r=await s.readSession(d);if(!r){t.status(404).json({ok:!1,error:"task_not_found"});return}const n=r.tasks.find(f=>f.taskId===o);if(!n){t.status(404).json({ok:!1,error:"task_not_found"});return}const{text:u,fileExists:c,truncated:a}=await x(n.outputPath,i);t.json({ok:!0,source:"file",taskId:n.taskId,status:n.status,exitCode:n.exitCode,signal:n.signal,startedAt:n.startedAt,finishedAt:n.finishedAt,command:n.command,lines:u,nextSeq:0,totalLines:n.outputLineCount,totalBytes:n.outputBytes,truncated:a||!c})}catch(s){l.error("[acode-bg-tasks] \u78C1\u76D8\u515C\u5E95\u8BFB\u53D6\u5931\u8D25: %s",s?.message),t.status(500).json({ok:!1,error:"internal_error"})}})().catch(d=>{l.error("[acode-bg-tasks] output \u8BFB\u53D6\u5931\u8D25: %s",d?.message),t.status(500).json({ok:!1,error:"internal_error"})})}),p.get("/acode-bg-tasks/:agentId/:taskId/stream",k,(e,t)=>{(async()=>{const d=String(e.params.agentId),o=String(e.params.taskId);t.status(200),t.set({"Content-Type":"text/event-stream","Cache-Control":"no-cache, no-transform",Connection:"keep-alive","X-Accel-Buffering":"no"}),t.flushHeaders?.();const i=(u,c)=>{t.writableEnded||t.destroyed||(c!==void 0&&t.write(`id: ${c}
1
+ import{promises as S}from"node:fs";import y from"node:path";import{pathToFileURL as C}from"node:url";import{Router as j}from"express";import{getAcodeDataHome as T}from"../config.js";import{validateToken as k}from"../middleware/auth.js";import{noteDashboardActivity as B}from"./dashboard.js";import{getAcodeBgManager as h}from"../services/acode-bg-manager.js";import{getReleasedAcodeEntryPath as E}from"../services/acode-package.js";import{createLogger as _}from"../utils/logger.js";import{listPtySessions as L}from"./pty.js";let m=null;function I(){return m||(m=(async()=>{try{const e=E(),t=y.join(y.dirname(e),"background-command-store.js"),d=await import(C(t).href);return d.BackgroundCommandStore?new d.BackgroundCommandStore:(l.warn("[acode-bg-tasks] BackgroundCommandStore \u4E0D\u53EF\u7528,\u78C1\u76D8\u515C\u5E95\u7981\u7528"),null)}catch(e){return l.warn("[acode-bg-tasks] \u52A0\u8F7D BackgroundCommandStore \u5931\u8D25: %s",e?.message),null}})().then(e=>(e||(m=null),e)),m)}const l=_("acode-bg-tasks"),p=j();function v(e){return String(e).replace(/[^a-zA-Z0-9_-]/g,"_")}function P(e){return y.join(T(),"bg-tasks",v(e),"state.json")}p.get("/acode-bg-tasks/:agentId",k,async(e,t)=>{const d=e.params.agentId,o=Array.isArray(d)?d[0]:d;if(!o||!String(o).trim()){t.status(400).json({ok:!1,error:"agentId is required"});return}try{const s=await h();if(s&&typeof s.listTasksWithReconcile=="function"){const r=e.query.status&&String(e.query.status)!=="all"?String(e.query.status):void 0,n=await s.listTasksWithReconcile(String(o),r);t.json({ok:!0,agentId:String(o),updatedAt:Date.now(),tasks:n});return}}catch(s){l.warn("[acode-bg-tasks] \u5185\u5B58\u5BF9\u8D26\u5217\u8868\u5931\u8D25\uFF0C\u964D\u7EA7\u78C1\u76D8\u8BFB\u53D6: %s",s?.message)}const i=P(String(o));try{const s=await S.readFile(i,"utf-8"),r=JSON.parse(s),u=(Array.isArray(r.tasks)?r.tasks:[]).map(c=>{const a=c;return{taskId:a.taskId,status:a.status,command:a.commandPreview??a.command,commandPreview:a.commandPreview,description:typeof a.description=="string"?a.description:void 0,cwd:a.cwd,startedAt:a.startedAt,finishedAt:a.finishedAt,exitCode:a.exitCode,signal:a.signal,outputLineCount:a.outputLineCount,outputBytes:a.outputBytes}});t.json({ok:!0,agentId:String(o),updatedAt:typeof r.updatedAt=="number"?r.updatedAt:null,tasks:u})}catch(s){if((typeof s=="object"&&s!==null?Reflect.get(s,"code"):void 0)==="ENOENT"){t.json({ok:!0,agentId:String(o),updatedAt:null,tasks:[]});return}if(s instanceof SyntaxError){l.warn("[acode-bg-tasks] \u6587\u4EF6\u635F\u574F\uFF08JSON \u89E3\u6790\u5931\u8D25\uFF09: %s",i),t.json({ok:!0,agentId:String(o),updatedAt:null,tasks:[]});return}const n=s;l.error("[acode-bg-tasks] \u8BFB\u53D6\u5931\u8D25: %s",n.message),t.status(500).json({ok:!1,error:n.message})}}),p.get("/acode-agent-pty-sessions/:agentId",k,(e,t)=>{const d=e.params.agentId,o=Array.isArray(d)?d[0]:d;if(!o||!String(o).trim()){t.status(400).json({ok:!1,error:"agentId is required"});return}const i=String(o),r=L().filter(n=>n.ownerUserId===i);t.json({ok:!0,agentId:i,sessions:r})});const N=15e3;function w(e){return{taskId:e.taskId,status:e.status,exitCode:e.exitCode,signal:e.signal,startedAt:e.startedAt,finishedAt:e.finishedAt,command:e.command,lines:e.lines,nextSeq:e.nextSeq,totalLines:e.totalLines,totalBytes:e.totalBytes,truncated:e.truncated}}async function x(e,t){let o=null;try{o=await S.open(e,"r")}catch(i){if(i?.code==="ENOENT")return{text:[],fileExists:!1,truncated:!1};throw i}try{const s=(await o.stat()).size;if(s===0)return{text:[],fileExists:!0,truncated:!1};const r=Math.min(s,2097152),n=s-r,u=Buffer.alloc(r);await o.read(u,0,r,n);const a=u.toString("utf-8").split(`
2
+ `);return n>0&&a.shift(),{text:a.slice(-t),fileExists:!0,truncated:r<s}}finally{await o.close()}}p.get("/acode-bg-tasks/:agentId/:taskId/output",k,(e,t)=>{(async()=>{const d=String(e.params.agentId),o=String(e.params.taskId),i=Math.min(2e3,Math.max(100,Number(e.query.tailLines)||500));try{const s=await h();if(s){const r=s.getTaskOutputSnapshot(d,o);if(r){t.json({ok:!0,source:"memory",...w(r)});return}}}catch(s){l.warn("[acode-bg-tasks] \u5185\u5B58\u5FEB\u7167\u8BFB\u53D6\u5931\u8D25,\u964D\u7EA7\u8D70\u78C1\u76D8: %s",s?.message)}try{const s=await I();if(!s){t.status(503).json({ok:!1,error:"store unavailable"});return}const r=await s.readSession(d);if(!r){t.status(404).json({ok:!1,error:"task_not_found"});return}const n=r.tasks.find(f=>f.taskId===o);if(!n){t.status(404).json({ok:!1,error:"task_not_found"});return}const{text:u,fileExists:c,truncated:a}=await x(n.outputPath,i);t.json({ok:!0,source:"file",taskId:n.taskId,status:n.status,exitCode:n.exitCode,signal:n.signal,startedAt:n.startedAt,finishedAt:n.finishedAt,command:n.command,lines:u,nextSeq:0,totalLines:n.outputLineCount,totalBytes:n.outputBytes,truncated:a||!c})}catch(s){l.error("[acode-bg-tasks] \u78C1\u76D8\u515C\u5E95\u8BFB\u53D6\u5931\u8D25: %s",s?.message),t.status(500).json({ok:!1,error:"internal_error"})}})().catch(d=>{l.error("[acode-bg-tasks] output \u8BFB\u53D6\u5931\u8D25: %s",d?.message),t.status(500).json({ok:!1,error:"internal_error"})})}),p.get("/acode-bg-tasks/:agentId/:taskId/stream",k,(e,t)=>{B(),(async()=>{const d=String(e.params.agentId),o=String(e.params.taskId);t.status(200),t.set({"Content-Type":"text/event-stream","Cache-Control":"no-cache, no-transform",Connection:"keep-alive","X-Accel-Buffering":"no"}),t.flushHeaders?.();const i=(u,c)=>{t.writableEnded||t.destroyed||(c!==void 0&&t.write(`id: ${c}
3
3
  `),t.write(`data: ${JSON.stringify(u)}
4
4
 
5
5
  `))};let s,r=null,n=null;try{s=await h(),s&&(r=s,n=s.getTaskOutputSnapshot(d,o))}catch(u){l.warn("[acode-bg-tasks] \u5185\u5B58\u8BFB\u53D6\u5931\u8D25,\u964D\u7EA7\u8D70\u78C1\u76D8: %s",u?.message)}if(n){if(!r){i({type:"done",status:"killed",exitCode:null,signal:null}),t.end();return}if(i({type:"snapshot",source:"memory",...w(n)}),n.status!=="running"){i({type:"done",status:n.status,exitCode:n.exitCode,signal:n.signal}),t.end();return}let u=null,c=!1;const a=()=>{c||(c=!0,u?.(),clearInterval(f))},f=setInterval(()=>{if(t.writableEnded||t.destroyed){a();return}try{t.write(`: ping
6
6
 
7
- `)}catch{a()}},P);if(f.unref?.(),u=r.subscribeTaskOutput(d,o,{onLine:g=>i({type:"output",stream:g.stream,text:g.text,seq:g.seq},g.seq),onDone:g=>{i({type:"done",status:g.status,exitCode:g.exitCode,signal:g.signal}),a(),t.end()}}),!u){i({type:"done",status:n.status,exitCode:n.exitCode,signal:n.signal}),a(),t.end();return}e.on("close",()=>{a(),t.writableEnded||t.end()}),e.on("aborted",()=>a());return}try{const u=await I();if(!u){i({type:"done",status:"killed",exitCode:null,signal:null}),t.end();return}const c=await u.readSession(d);if(!c){i({type:"done",status:"killed",exitCode:null,signal:null}),t.end();return}const a=c.tasks.find(b=>b.taskId===o);if(!a){i({type:"done",status:"killed",exitCode:null,signal:null}),t.end();return}const{text:f,fileExists:g,truncated:A}=await x(a.outputPath,500);i({type:"snapshot",source:"file",taskId:a.taskId,status:a.status,exitCode:a.exitCode,signal:a.signal,startedAt:a.startedAt,finishedAt:a.finishedAt,command:a.command,lines:f,nextSeq:0,totalLines:a.outputLineCount,totalBytes:a.outputBytes,truncated:A||!g}),i({type:"done",status:a.status,exitCode:a.exitCode,signal:a.signal}),t.end()}catch(u){l.error("[acode-bg-tasks] \u78C1\u76D8\u515C\u5E95 stream \u5931\u8D25: %s",u?.message),t.headersSent?t.end():t.status(500).json({ok:!1,error:"internal_error"})}})().catch(d=>{l.error("[acode-bg-tasks] stream \u5EFA\u7ACB\u5931\u8D25: %s",d?.message),t.headersSent?t.end():t.status(500).json({ok:!1,error:"internal_error"})})});export{p as backgroundTasksRouter};
7
+ `)}catch{a()}},N);if(f.unref?.(),u=r.subscribeTaskOutput(d,o,{onLine:g=>i({type:"output",stream:g.stream,text:g.text,seq:g.seq},g.seq),onDone:g=>{i({type:"done",status:g.status,exitCode:g.exitCode,signal:g.signal}),a(),t.end()}}),!u){i({type:"done",status:n.status,exitCode:n.exitCode,signal:n.signal}),a(),t.end();return}e.on("close",()=>{a(),t.writableEnded||t.end()}),e.on("aborted",()=>a());return}try{const u=await I();if(!u){i({type:"done",status:"killed",exitCode:null,signal:null}),t.end();return}const c=await u.readSession(d);if(!c){i({type:"done",status:"killed",exitCode:null,signal:null}),t.end();return}const a=c.tasks.find(b=>b.taskId===o);if(!a){i({type:"done",status:"killed",exitCode:null,signal:null}),t.end();return}const{text:f,fileExists:g,truncated:A}=await x(a.outputPath,500);i({type:"snapshot",source:"file",taskId:a.taskId,status:a.status,exitCode:a.exitCode,signal:a.signal,startedAt:a.startedAt,finishedAt:a.finishedAt,command:a.command,lines:f,nextSeq:0,totalLines:a.outputLineCount,totalBytes:a.outputBytes,truncated:A||!g}),i({type:"done",status:a.status,exitCode:a.exitCode,signal:a.signal}),t.end()}catch(u){l.error("[acode-bg-tasks] \u78C1\u76D8\u515C\u5E95 stream \u5931\u8D25: %s",u?.message),t.headersSent?t.end():t.status(500).json({ok:!1,error:"internal_error"})}})().catch(d=>{l.error("[acode-bg-tasks] stream \u5EFA\u7ACB\u5931\u8D25: %s",d?.message),t.headersSent?t.end():t.status(500).json({ok:!1,error:"internal_error"})})});export{p as backgroundTasksRouter};
8
8
 
@@ -1,2 +1,2 @@
1
- import{Router as p}from"express";import{validateToken as c}from"../middleware/auth.js";import{getEffective as d,getDefaults as m,getOverrides as u}from"../services/capability-config.js";import{mcpDeployManager as f}from"../services/mcp-deploy.js";import{pluginManager as g}from"../services/plugin-manager.js";import{skillManager as y}from"../services/skill-manager.js";import{createLogger as b}from"../utils/logger.js";const k=b("capabilities"),D=p();function l(i,t,o){const s=u(i,t),r=m(t),a={};for(const e of o){const n=s[e]!==void 0?"agent":r[e]!==void 0?"bridge":"default";a[e]={enabled:d(i,t,e),source:n}}return a}D.post("/capabilities/state",c,async(i,t)=>{const o=String((i.body??{})?.agentId??"").trim();if(!o){t.status(400).json({ok:!1,error:"agentId is required"});return}try{const s=y.listDeployed().map(e=>e.skillName),r=f.listDeployed().map(e=>e.name),a=(await g.listDeployed()).map(e=>e.pluginName);t.json({ok:!0,agentId:o,skills:l(o,"skills",s),mcp:l(o,"mcp",r),plugins:l(o,"plugins",a),deployedSkills:s,deployedMcp:r,deployedPlugins:a})}catch(s){k.warn("[capabilities/state] \u8BFB\u53D6\u80FD\u529B\u72B6\u6001\u5931\u8D25: %s",s.message),t.status(500).json({ok:!1,error:s.message||"read capability state failed"})}});export{D as capabilitiesRouter};
1
+ import{Router as n}from"express";import{validateToken as p}from"../middleware/auth.js";import{getEffective as m,getEffectiveSource as c}from"../services/capability-config.js";import{mcpDeployManager as d}from"../services/mcp-deploy.js";import{pluginManager as f}from"../services/plugin-manager.js";import{skillManager as g}from"../services/skill-manager.js";import{createLogger as u}from"../utils/logger.js";const y=u("capabilities"),k=n();function r(s,o,t){const e={};for(const a of t)e[a]={enabled:m(s,o,a),source:c(s,o,a)};return e}k.post("/capabilities/state",p,async(s,o)=>{const t=String((s.body??{})?.agentId??"").trim();if(!t){o.status(400).json({ok:!1,error:"agentId is required"});return}try{const e=g.listDeployed().map(i=>i.skillName),a=d.listDeployed().map(i=>i.name),l=(await f.listDeployed()).map(i=>i.pluginName);o.json({ok:!0,agentId:t,skills:r(t,"skills",e),mcp:r(t,"mcp",a),plugins:r(t,"plugins",l),deployedSkills:e,deployedMcp:a,deployedPlugins:l})}catch(e){y.warn("[capabilities/state] \u8BFB\u53D6\u80FD\u529B\u72B6\u6001\u5931\u8D25: %s",e.message),o.status(500).json({ok:!1,error:e.message||"read capability state failed"})}});export{k as capabilitiesRouter};
2
2
 
@@ -1,2 +1,4 @@
1
1
 
2
+
3
+ export declare function noteDashboardActivity(): void;
2
4
  export declare const dashboardRouter: import("express-serve-static-core").Router;