aws-runtime-bridge 1.9.124 → 1.9.126
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -2
- package/dist/adapter/AcodeSdkAdapter.js +4 -4
- package/dist/adapter/OpencodeSdkAdapter.js +2 -2
- package/dist/adapter/types.js +1 -1
- package/dist/config.d.ts +30 -4
- package/dist/config.js +3 -1
- package/dist/index.js +1 -1
- package/dist/routes/acode-todos.js +1 -1
- package/dist/routes/background-tasks.js +1 -1
- package/dist/routes/dashboard.js +58 -3
- package/dist/routes/git.d.ts +28 -0
- package/dist/routes/git.js +32 -31
- package/dist/routes/terminal.js +24 -24
- package/dist/services/auto-register.d.ts +2 -2
- package/dist/services/auto-register.js +1 -1
- package/dist/services/aws-client-agent-mcp.d.ts +2 -1
- package/dist/services/aws-client-agent-mcp.js +2 -2
- package/dist/services/cc-switch-sdk.js +1 -1
- package/dist/services/cli-commands.js +5 -5
- package/dist/services/fileSnapshotStore.js +1 -1
- package/dist/services/instance-ai-config-service.js +1 -1
- package/dist/services/instance-features.d.ts +2 -0
- package/dist/services/instance-features.js +1 -1
- package/dist/services/panel-auth.d.ts +2 -0
- package/dist/services/panel-auth.js +1 -1
- package/dist/services/startup-config-wizard.js +6 -6
- package/dist/services/tunnel-client.js +1 -1
- package/dist/services/update-notifier.js +2 -2
- package/package/acode/dist/ask-user-question-tool.js +2 -2
- package/package/acode/dist/background-command-store.js +1 -1
- package/package/acode/dist/builtins/commandArtifacts.js +3 -3
- package/package/acode/dist/mcpToolNames.d.ts +2 -0
- package/package/acode/dist/mcpToolNames.js +1 -1
- package/package/acode/dist/meeting-debug-log.d.ts +1 -0
- package/package/acode/dist/meeting-debug-log.js +3 -0
- package/package/acode/dist/paths.d.ts +2 -0
- package/package/acode/dist/paths.js +2 -0
- package/package/acode/dist/runtime.d.ts +4 -0
- package/package/acode/dist/runtime.js +20 -20
- package/package/acode/dist/sub-agent-manager.d.ts +1 -0
- package/package/acode/dist/sub-agent-manager.js +1 -1
- package/package/acode/dist/sub-agent-store.js +3 -3
- package/package/acode/dist/sub-agent-tools.js +27 -31
- package/package/acode/dist/sub-agent-types.d.ts +1 -1
- package/package/acode/dist/todo-store.js +1 -1
- package/package/acode/dist/tool-allocation.d.ts +18 -4
- package/package/acode/dist/tool-allocation.js +1 -1
- package/package/acode/dist/types.d.ts +0 -3
- package/package/aws-client-agent-mcp/dist/agent-client.d.ts +17 -0
- package/package/aws-client-agent-mcp/dist/agent-client.js +1 -1
- package/package/aws-client-agent-mcp/dist/agent-client.test.js +251 -1
- package/package/aws-client-agent-mcp/dist/config.d.ts +2 -0
- package/package/aws-client-agent-mcp/dist/config.js +1 -1
- package/package/aws-client-agent-mcp/dist/config.test.js +93 -1
- package/package/aws-client-agent-mcp/dist/http-client.d.ts +2 -0
- package/package/aws-client-agent-mcp/dist/http-client.js +1 -1
- package/package/aws-client-agent-mcp/dist/launch-config-tools.test.js +6 -2
- package/package/aws-client-agent-mcp/dist/mcp-server.d.ts +21 -0
- package/package/aws-client-agent-mcp/dist/mcp-server.js +28 -28
- package/package/aws-client-agent-mcp/dist/mcp-server.test.js +628 -7
- package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts +10 -0
- package/package/aws-client-agent-mcp/dist/mcp-tools.js +12 -10
- package/package/aws-client-agent-mcp/dist/mcp-tools.test.js +38 -0
- package/package/aws-client-agent-mcp/dist/meeting-debug-log.d.ts +13 -0
- package/package/aws-client-agent-mcp/dist/meeting-debug-log.js +3 -0
- package/package/aws-client-agent-mcp/dist/message-buffer.d.ts +2 -0
- package/package/aws-client-agent-mcp/dist/message-buffer.js +1 -1
- package/package/aws-client-agent-mcp/dist/message-buffer.test.js +60 -0
- package/package/aws-client-agent-mcp/dist/runtime-launch-binding.d.ts +14 -0
- package/package/aws-client-agent-mcp/dist/runtime-launch-binding.js +1 -1
- package/package/aws-client-agent-mcp/dist/runtime-launch-binding.test.js +39 -1
- package/package/aws-client-agent-mcp/dist/types.d.ts +11 -1
- package/package/aws-client-agent-mcp/dist/websocket-client.js +1 -1
- package/package/aws-client-agent-mcp/package.json +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -86,6 +86,26 @@ AWS_CLIENT_AGENT_MCP_ARGS='[]' \
|
|
|
86
86
|
aws-bridge
|
|
87
87
|
```
|
|
88
88
|
|
|
89
|
+
## 开发环境与生产环境
|
|
90
|
+
|
|
91
|
+
Bridge 区分两类运行形态,二者可在同一台机器上同时运行、互不干扰(适用于"用本项目开发本项目"的场景):
|
|
92
|
+
|
|
93
|
+
| | 生产环境 | 开发环境 |
|
|
94
|
+
| --- | --- | --- |
|
|
95
|
+
| 启动方式 | npm 全局安装后 `awsb` / `node dist/index.js` / 系统服务 | 仓库内 `npm run dev` |
|
|
96
|
+
| 判定依据 | 无环境标记(默认即生产) | `scripts/dev-runner.mjs` 注入 `AWS_RUNTIME_ENV=development` |
|
|
97
|
+
| 运行主目录 | `~/.aws-bridge/` | `<仓库根>/.dev-home/.aws-bridge/` |
|
|
98
|
+
| 首选端口 | `18081` | `28081` |
|
|
99
|
+
| MCP 服务名 | `aws-mcp` | `aws-mcp-dev` |
|
|
100
|
+
|
|
101
|
+
行为要点:
|
|
102
|
+
|
|
103
|
+
- **数据隔离**:开发态的全部持久化数据(config.json、自动注册目标、面板凭据、IP 访问控制、日志、实例状态、mcp/acode 部署目录等)都落在仓库根 `.dev-home/` 下(已加入 `.gitignore`),不碰已安装实例的 `~/.aws-bridge/`;删除 `.dev-home/` 即可完全重置开发环境。
|
|
104
|
+
- **Agent CLI 配置保持共享**:`~/.claude`、`~/.codex`、`~/.opencode` 等 Agent CLI 配置在两种环境下都使用真实用户主目录——开发态 Bridge 拉起的也是真实 Agent 进程。MCP 服务名按环境区分(`aws-mcp` / `aws-mcp-dev`),两个实例写入 Agent 配置的条目并存,互不顶掉线。
|
|
105
|
+
- **端口错开**:两环境首选端口不同(冲突时仍会自动顺延),保证同时监听、地址可预期。
|
|
106
|
+
- **显式覆盖优先**:设置 `AWS_TEST_HOME` 或 `AWS_RUNTIME_HOME_DIR` 时,无论何种环境都使用该目录,测试与系统服务部署行为不受影响。
|
|
107
|
+
- **注意**:在仓库内直接执行 `npm start` / `node dist/index.js` 视为生产环境(与已安装实例共用 `~/.aws-bridge/`),需要隔离时请使用 `npm run dev`。
|
|
108
|
+
|
|
89
109
|
## systemd 服务管理
|
|
90
110
|
|
|
91
111
|
Linux systemd 环境中可使用 CLI 安装或卸载 `awsb.service`。安装命令会写入 systemd unit、执行 `systemctl daemon-reload`、启用开机自启,并在服务尚未运行时立即启动:
|
|
@@ -166,11 +186,12 @@ awsb service uninstall
|
|
|
166
186
|
|
|
167
187
|
| 变量名 | 说明 | 默认值 |
|
|
168
188
|
| --- | --- | --- |
|
|
169
|
-
| `AWS_RUNTIME_BRIDGE_PORT` | Bridge HTTP 端口 | `18081` |
|
|
189
|
+
| `AWS_RUNTIME_BRIDGE_PORT` | Bridge HTTP 端口 | `18081`(开发态 `28081`) |
|
|
190
|
+
| `AWS_RUNTIME_ENV` | 运行环境标记;仅 `npm run dev` 由 `scripts/dev-runner.mjs` 自动注入 `development`,一般无需手动设置。决定运行主目录、默认端口与 MCP 服务名,详见上文「开发环境与生产环境」 | 未设置(生产) |
|
|
170
191
|
| `AWS_RUNTIME_SCHEDULER_BASE_URL` | aws-mcp-server 地址;显式配置优先级最高,未配置且只有一个 `autoRegisterTargets[].serverUrl` 时自动使用该地址 | 单目标自动注册地址;否则 `http://localhost:8080` |
|
|
171
192
|
| `AWS_REGISTER_ADDR` | Bridge 对外注册地址,覆盖配置文件中的 `registerAddr`;支持 `host:port` / 纯 `host` / 完整 URL(`http(s)://...`) | 未设置时读取配置文件 |
|
|
172
193
|
| `AWS_REGISTER_IP` | 已废弃,仅做向后兼容;等同 `registerAddr` 但只接受纯 IP,端口由 `AWS_RUNTIME_BRIDGE_PORT` 决定 | 未设置时读取配置文件 |
|
|
173
|
-
| `AWS_RUNTIME_HOME_DIR` | Bridge
|
|
194
|
+
| `AWS_RUNTIME_HOME_DIR` | Bridge 管理配置与状态的主目录;显式设置时优先于开发/生产环境的默认主目录 | 当前用户 Home(开发态为 `<仓库根>/.dev-home`) |
|
|
174
195
|
| `AWS_RUNTIME_CORS_ORIGINS` | 允许访问 bridge 的来源,逗号分隔 | 本地开发地址 |
|
|
175
196
|
|
|
176
197
|
生产环境中,bridge 最终解析出的调度中心地址必须是机器实例可访问的 `aws-mcp-server` 地址,不能使用不可达的容器内 `localhost`。如果配置了多个 `autoRegisterTargets`,bridge 不会静默选择第一个目标,需通过 `AWS_RUNTIME_SCHEDULER_BASE_URL` 或后续多调度中心身份路由明确目标。
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import{EventEmitter as Y}from"node:events";import I from"node:path";import X from"node:fs/promises";import{pathToFileURL as V}from"node:url";import{v4 as U}from"uuid";import{getAcodeConfigFile as $,getAcodeSkillsDir as Z,getRuntimeHomeDir as R}from"../config.js";import{getReleasedAcodeEntryPath as tt}from"../services/acode-package.js";import{getInstanceAiConfigDebugLogger as x}from"../utils/instance-ai-config-debug-logger.js";import{redactForLog as v}from"../services/instance-ai-config-service.js";import{subAgentManager as et}from"../services/sub-agent-manager-instance.js";import{agentPtyManager as ot}from"../services/agent-pty-manager.js";import{resolveAcodeProviderConfig as st}from"./instance-ai-config-resolver.js";import{recordAgentFileChange as it}from"../services/workspaceTaskChangeWatcher.js";import{getBrowserTools as F,closeBrowserSession as at,registerListenerWakeHook as nt,unregisterListenerWakeHook as B}from"../services/browser-session-manager.js";import{getDesktopTools as O,getDesktopToolsIfReady as rt}from"../services/desktop-mcp-manager.js";import{BROWSER_FEATURE_KEY as W,DESKTOP_FEATURE_KEY as D,isFeatureEnabled as P}from"../services/instance-features.js";import{isMessagePollingIdleCommand as L,isPollMessageToolDescriptor as ut}from"./acode-tool-names.js";import{IdlePollLoop as lt}from"./idle-poll-loop.js";import{getCanonicalMcpDetail as q,getToolActionInfo as dt}from"./types.js";const ct=process.env.ACODE_COMPACTION_DEBUG==="1";function l(...u){ct&&console.log(...u)}const mt=process.env.ACODE_TOKEN_DEBUG==="1";function w(...u){mt&&console.log("[TokenDebug][Adapter]",...u)}const N=["Continue the AgentsWork message loop now.","You MUST call the exact MCP tool named aws-mcp__poll_message as your next action and wait for the next assigned message or task.","Do not answer in plain text before calling aws-mcp__poll_message.","After handling any received work, reply through the appropriate aws-mcp messaging tool, then continue listening again."].join(" "),pt=5e3;function E(u,t){const e=process.env[u];if(e===void 0||e.trim()==="")return t;const o=Number(e.trim());return Number.isFinite(o)&&o>=0?Math.floor(o):t}const H=E("ACODE_DATA_FLOW_WATCHDOG_MS",12e4),gt=5*6e4,ft=E("ACODE_STUCK_AUTOPOLL_TIMEOUT_MS",5*6e4),ht=250,Tt=2e3,K=E("ACODE_SUBMIT_TIMEOUT_MS",12e4),j=3e3,_t="\u7CFB\u7EDF\u63D0\u9192\uFF1A\u5982\u679C\u4EFB\u52A1\u5DF2\u5B8C\u6210\u6216\u6CA1\u6709\u5176\u5B83\u8981\u505A\u7684\uFF0C\u5148\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";function At(){return I.resolve(tt())}function St(u){return V(I.resolve(u)).href}const Q=128e3,y={"claude-4":{contextLimit:2e5,maxOutput:8192},"claude-sonnet-4":{contextLimit:2e5,maxOutput:8192},"claude-3-5-sonnet":{contextLimit:2e5,maxOutput:8192},"claude-3-opus":{contextLimit:2e5,maxOutput:8192},"claude-3-haiku":{contextLimit:2e5,maxOutput:8192},"claude-2":{contextLimit:1e5,maxOutput:4096},"gpt-4o":{contextLimit:128e3,maxOutput:16384},"gpt-4-turbo":{contextLimit:128e3,maxOutput:4096},"gpt-4":{contextLimit:8192,maxOutput:4096},"gpt-3.5-turbo":{contextLimit:16384,maxOutput:4096},o1:{contextLimit:2e5,maxOutput:1e5},"o3-mini":{contextLimit:2e5,maxOutput:1e5},"gemini-2.0-flash":{contextLimit:1048576,maxOutput:8192},"gemini-2.5-pro":{contextLimit:1048576,maxOutput:8192},"gemini-1.5-pro":{contextLimit:2097152,maxOutput:8192},"gemini-1.5-flash":{contextLimit:1048576,maxOutput:8192},deepseek:{contextLimit:64e3,maxOutput:8192},"deepseek-chat":{contextLimit:64e3,maxOutput:8192},"deepseek-reasoner":{contextLimit:64e3,maxOutput:8192},"qwen-max":{contextLimit:32e3,maxOutput:8192},"qwen-plus":{contextLimit:128e3,maxOutput:8192},"qwen-turbo":{contextLimit:1e6,maxOutput:8192},"glm-4":{contextLimit:128e3,maxOutput:4096},"yi-":{contextLimit:2e5,maxOutput:4096},"llama-3":{contextLimit:8192,maxOutput:4096},"llama-2":{contextLimit:4096,maxOutput:4096},mistral:{contextLimit:32e3,maxOutput:4096},mixtral:{contextLimit:32e3,maxOutput:4096},codestral:{contextLimit:256e3,maxOutput:8192},grok:{contextLimit:131072,maxOutput:4096},"nova-":{contextLimit:2e5,maxOutput:8192}};function kt(u){if(!u)return Q;const t=u.toLowerCase().trim();if(y[t])return y[t].contextLimit;const e=Object.keys(y).filter(o=>t.startsWith(o)).sort((o,s)=>s.length-o.length);return e.length>0?y[e[0]].contextLimit:Q}const G=4096;function bt(u){if(!u)return G;const t=u.toLowerCase().trim();if(y[t])return y[t].maxOutput;const e=Object.keys(y).filter(o=>t.startsWith(o)).sort((o,s)=>s.length-o.length);return e.length>0?y[e[0]].maxOutput:G}function Ct(u){if(!u||typeof u!="object")return;const t=u,e=h(t.inputTokens,t.input_tokens,t.promptTokens,t.prompt_tokens),o=h(t.outputTokens,t.output_tokens,t.completionTokens,t.completion_tokens);if(e===0&&o===0)return;let s=h(t.cacheHitTokens,t.promptCacheHitTokens,t.prompt_cache_hit_tokens),a=h(t.cacheMissTokens,t.promptCacheMissTokens,t.prompt_cache_miss_tokens),i=t.cacheHitTokens!==void 0||t.cacheMissTokens!==void 0||t.promptCacheHitTokens!==void 0||t.promptCacheMissTokens!==void 0||t.prompt_cache_hit_tokens!==void 0||t.prompt_cache_miss_tokens!==void 0;if(s===0&&a===0){const n=h(t.cache_read_input_tokens),r=h(t.cache_creation_input_tokens);n>0||r>0?(s=n,a=r+h(t.input_tokens),i=!0):(s=h(t.cache_hit_tokens),a=h(t.cache_miss_tokens),i=i||t.cache_hit_tokens!==void 0||t.cache_miss_tokens!==void 0)}if(s===0&&a===0){const n=h(t.prompt_tokens_details?.cached_tokens);n>0&&(s=n,a=e>n?e-n:0,i=!0)}return{inputTokens:e,outputTokens:o,...s>0||a>0?{cacheHitTokens:s,cacheMissTokens:a}:{},...i?{hasCache:!0}:{}}}function h(...u){for(const t of u){const e=Number(t);if(Number.isFinite(e)&&e>0)return e}return 0}function J(u){return h(u.estimatedContextTokens,u.contextTokens,u.context_tokens,u.contextUsedTokens,u.context_used_tokens)}function yt(u){return u==="stderr"||u==="mixed"?u:"stdout"}function wt(u){if(!u||typeof u!="object"||Array.isArray(u))return;const t={};for(const[e,o]of Object.entries(u))typeof o=="string"&&(t[e]=o);return Object.keys(t).length>0?t:void 0}function Pt(u){return u.failed===!0}function z(u,t,e){if(!u)return e?`${t}/${e}`:t;const o=`${t}__`;return u.startsWith(o)?q(`${t}__${u.slice(o.length)}`):q(u.replace("/","__"))}function Lt(u){return u==="read_file"||u==="edit_file"||u==="write_file"||u==="bash"}function $t(u){const t=xt(u);return t?[t.directMessages,t.groupMessages,t.messages].some(e=>Array.isArray(e)&&e.length>0):typeof u=="string"&&u.trim().length>0}function xt(u){if(u&&typeof u=="object"&&!Array.isArray(u))return u;if(!(typeof u!="string"||!u.trim()))try{const t=JSON.parse(u);return t&&typeof t=="object"&&!Array.isArray(t)?t:void 0}catch{return}}class zt extends Y{constructor(){super(...arguments),this.providerId="acode",this.displayName="ACode",this.sessions=new Map,this.listenerWakeHooks=new Map}async startSession(t,e){const o=R(),s=e.mcpConfigPath||$(o),{resolved:a,configContextLimit:i,supportsImage:n}=await this.resolveAcodeProvider(e,s),r=a.model,c=i??kt(r),p=bt(r),m={sessionId:t,status:"starting",messages:[],createdAt:new Date().toISOString(),totalUsage:{inputTokens:0,outputTokens:0,contextLimit:c,maxOutput:p,cacheHitTokens:0,cacheMissTokens:0}};this.sessions.set(t,{adapterSession:m,config:e,runtime:await this.createRuntime(t,r,e,o,a,n),autoPollActive:!1}),this.emit("status-change",t,"starting");const g=this.sessions.get(t);if(!g)throw new Error("ACode session was not initialized");const d=()=>{const f=this.sessions.get(t);f&&this.getIdlePollLoop(f).start()};this.listenerWakeHooks.set(t,d),nt(e.agentId,d);try{await g.runtime.start(),m.status="waiting_input",this.emit("status-change",t,"waiting_input",{usage:g.adapterSession.totalUsage}),e.initialPrompt?.trim()?this.startInitialPromptTurn(t,e.initialPrompt):this.armIdleLoopOrAutoPoll(t)}catch(f){m.status="error",this.emitRuntimeErrorEvent(t,f),this.emit("status-change",t,"error");const _=this.sessions.get(t);throw _?.capabilitiesFallbackTimer&&clearTimeout(_.capabilitiesFallbackTimer),this.sessions.delete(t),B(e.agentId,this.listenerWakeHooks.get(t)),this.listenerWakeHooks.delete(t),f}}async sendMessage(t,e){const o=Date.now();l("[ACode] \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"),l("[ACode] \u25B6\uFE0F sendMessage STARTED"),l(`[ACode] Session: ${t}`),l(`[ACode] Message: ${e.slice(0,100)}${e.length>100?"...":""}`),l("[ACode] \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");const s=this.requireSession(t),a=s.adapterSession.status;l(`[ACode] Previous status: ${a}`),this.cancelScheduledAutoPoll(s),s.failedTurnRecoveryScheduled=!1,s.idlePollLoop?.stop();const i={id:U(),sessionId:t,role:"user",content:e,timestamp:new Date().toISOString()};s.adapterSession.messages.push(i),this.emit("conversation-message",t,i),l(`[ACode] Changing status: ${a} \u2192 thinking`),s.adapterSession.status="thinking",this.emit("status-change",t,"thinking"),this.startSubmitTimeoutDetection(t,s,"sendMessage");try{l("[ACode] \u25B6\uFE0F Calling runtime.submit()...");const n=Date.now();await s.runtime.submit(e);const r=Date.now()-n;this.cancelSubmitTimeoutDetection(s),l(`[ACode] \u2705 runtime.submit() completed in ${r}ms`),l(`[ACode] Current status after submit: ${s.adapterSession.status}`),l("[ACode] \u25B6\uFE0F Calling recoverResolvedTurnWithoutTerminalEvent()..."),this.recoverResolvedTurnWithoutTerminalEvent(t),l(`[ACode] Status after recovery: ${s.adapterSession.status}`);const c=Date.now()-o;l("[ACode] \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"),l(`[ACode] \u2705 sendMessage COMPLETED in ${c}ms`),l("[ACode] \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550")}catch(n){const r=Date.now()-o;console.error(`[ACode] \u274C sendMessage FAILED after ${r}ms:`,n instanceof Error?n.message:String(n)),this.cancelSubmitTimeoutDetection(s),l("[ACode] \u25B6\uFE0F Calling emitRuntimeError with recover=true..."),this.emitRuntimeError(t,n,{recover:!0}),l(`[ACode] Status after error recovery: ${s.adapterSession.status}`)}}async sendConfirmation(t,e){}async sendQuestionAnswer(t,e){const o=this.sessions.get(t);if(!o)return;const s=o.pendingQuestionToolCallId;if(!s){l(`[AcodeSdkAdapter] sendQuestionAnswer: no pending question for session ${t}`);return}o.pendingQuestionToolCallId=void 0,o.pendingQuestions=void 0,o.runtime.submitQuestionAnswer&&o.runtime.submitQuestionAnswer(s,e),this.startSubmitTimeoutDetection(t,o,"sendQuestionAnswer")}async abortCurrentTurn(t){await this.requireSession(t).runtime.abort()}async resetContext(t){const e=this.requireSession(t);if(this.cancelScheduledAutoPoll(e),e.failedTurnRecoveryScheduled=!1,e.autoPollActive=!1,e.autoPollObservedPollingTool=!1,e.autoPollObservedAssistantText=!1,e.autoPollObservedAnyTool=!1,e.stopAutoPollAfterCurrentTurn=!1,e.idlePollLoop?.stop(),!e.runtime.resetContext)throw new Error("ACode runtime does not support context reset");await e.runtime.resetContext(),e.adapterSession.messages=[];const o=e.adapterSession.totalUsage;if(e.adapterSession.totalUsage={inputTokens:0,outputTokens:0,contextLimit:o.contextLimit,maxOutput:o.maxOutput,inputLimit:o.inputLimit,compactionThreshold:o.compactionThreshold,cacheHitTokens:o.cacheHitTokens,cacheMissTokens:o.cacheMissTokens},e.adapterSession.status="waiting_input",this.emit("status-change",t,"waiting_input",{usage:e.adapterSession.totalUsage}),e.config.initialPrompt?.trim()){this.startInitialPromptTurn(t,e.config.initialPrompt);return}this.armIdleLoopOrAutoPoll(t)}async terminateSession(t){const e=this.sessions.get(t);if(!e)return;this.cancelScheduledAutoPoll(e),e.failedTurnRecoveryScheduled=!1,e.idlePollLoop?.stop(),e.capabilitiesFallbackTimer&&(clearTimeout(e.capabilitiesFallbackTimer),e.capabilitiesFallbackTimer=void 0),await e.runtime.stop();const o=e.config.agentId;o&&(B(o,this.listenerWakeHooks.get(t)),at(o)),this.listenerWakeHooks.delete(t),e.adapterSession.status="terminated",this.sessions.delete(t),this.emit("status-change",t,"terminated")}getConversation(t){return this.sessions.get(t)?.adapterSession.messages??[]}hasSession(t){return this.sessions.has(t)}getProviderSessionId(t){return this.sessions.has(t)?t:void 0}getSessionStatus(t){return this.sessions.get(t)?.adapterSession.status}notifyForceMessage(t){const e=this.sessions.get(t);return e?.runtime?.notifyForceMessage?(e.runtime.notifyForceMessage(),!0):!1}getCapabilities(t){return this.sessions.get(t)?.lastCombinedCapabilities}async resolveAgentAiInfo(t){try{const e=[...this.sessions.values()].find(n=>n.config.agentId===t);if(!e)return;const o=R(),s=e.config.mcpConfigPath||$(o),{resolved:a,supportsImage:i}=await this.resolveAcodeProvider(e.config,s);return a?.model?{model:a.model,supportsImage:i===!0,...a.baseURL?{baseURL:a.baseURL}:{},...a.apiKey?{apiKey:a.apiKey}:{}}:void 0}catch{return}}async applyAgentFeatures(t){if(!t)return;const e=P(t,D),o=P(t,W);for(const[s,a]of this.sessions){if(a.config.agentId!==t)continue;const i=a.runtime;try{if(e){const n=await O(t,await this.resolveAgentAiInfo(t)),r=i.addBuiltInTools?.(n)??0;r>0&&l(`[acode-adapter] session ${s}: ${r} desktop tools hot-added for agent ${t}`)}else{const n=i.removeBuiltInToolsByPrefix?.("desktop_")??0;n>0&&l(`[acode-adapter] session ${s}: ${n} desktop tools hot-removed for agent ${t}`)}}catch(n){l(`[acode-adapter] session ${s}: desktop feature hot-sync failed for agent ${t}:`,n.message)}if(o)try{const n=await F(t,a.config.scopeKey,typeof a.config.browserAllowPrivate=="boolean"?{allowPrivate:a.config.browserAllowPrivate}:void 0),r=i.addBuiltInTools?.(n)??0;r>0&&l(`[acode-adapter] session ${s}: ${r} browser tools hot-added for agent ${t}`)}catch(n){l(`[acode-adapter] session ${s}: browser feature hot-sync failed for agent ${t}:`,n.message)}}this.syncMcpToolsForAgent(t)}syncMcpToolsForAgent(t){if(t){for(const[e,o]of this.sessions)if(o.config.agentId===t)try{o.runtime.requestMcpToolsRefresh?.()}catch(s){l(`[acode-adapter] session ${e}: mcp tools refresh failed for agent ${t}:`,s.message)}}}getPendingQuestion(t){const e=this.sessions.get(t);if(e?.pendingQuestionToolCallId)return{toolCallId:e.pendingQuestionToolCallId,questions:e.pendingQuestions??[]}}cleanup(){for(const t of this.sessions.keys())this.terminateSession(t)}setIdleCommands(t,e){const o=this.sessions.get(t);if(o){if(o.idleCommands=e,this.cancelScheduledAutoPoll(o),e.idleInputCommand&&L(e.idleInputCommand)){this.getIdlePollLoop(o).start();return}o.adapterSession.status==="waiting_input"&&(e.idleInputCommand||e.nonInputCommand)&&this.getIdlePollLoop(o).start()}}setRuntimeConstructorForTest(t){this.runtimeConstructor=t}async loadAcodeProviderSection(t){try{const e=await X.readFile(t,"utf-8"),o=JSON.parse(e),a=o.provider?.default,i=a?.options,n=h(o.contextLimit),r={},c={},p=a?.models;if(p&&typeof p=="object"){for(const[m,g]of Object.entries(p))if(g&&typeof g=="object"){const d=h(g.contextLimit);d>0&&(r[m.trim()]=d);const f=g.modalities?.input,_=Array.isArray(f)&&f.includes("image")||g.supportsImageInput===!0;c[m.trim()]=_===!0}}return{...a?.model?{model:a.model}:{},...i?.baseURL||i?.baseUrl?{baseURL:i?.baseURL||i?.baseUrl}:{},...i?.apiKey?{apiKey:i.apiKey}:{},...n>0?{contextLimit:n}:{},...Object.keys(r).length>0?{modelContextLimits:r}:{},...Object.keys(c).length>0?{modelImageSupport:c}:{}}}catch(e){const o=e instanceof Error?e.message:String(e);return x().log({level:"warn",category:"load",message:`loadAcodeProviderSection failed: ${t}: ${o}`,source:"bridge"}),{}}}async resolveAcodeProvider(t,e){const o=typeof t.model=="string"&&t.model.trim()?t.model.trim():void 0,s=x();s.log({level:"info",category:"resolve",message:"resolveAcodeProvider \u8F93\u5165",source:"bridge",details:{configModel:t.model??null,configInstanceAiConfig:t.instanceAiConfig?v(t.instanceAiConfig):null,configPath:e}});const a={...t.instanceAiConfig?.model?{model:t.instanceAiConfig.model}:{},...t.instanceAiConfig?.baseURL?{baseURL:t.instanceAiConfig.baseURL}:{},...t.instanceAiConfig?.apiKey?{apiKey:t.instanceAiConfig.apiKey}:{},...t.instanceAiConfig?.effort?{effort:t.instanceAiConfig.effort}:{},...o?{model:o}:{}},i=await this.loadAcodeProviderSection(e);let n=i.contextLimit;if(!n&&i.modelContextLimits){const c=o||t.instanceAiConfig?.model||i.model;c&&i.modelContextLimits[c]&&(n=i.modelContextLimits[c])}const r=st(a,i,"acode-default");return s.log({level:"info",category:"resolve",message:"resolveAcodeProvider \u89E3\u6790\u7ED3\u679C",source:"bridge",details:{instanceConfig:v(a),globalConfigModel:i?.model??null,resolvedModel:r.model,resolvedBaseURL:r.baseURL??null,resolvedApiKey:r.apiKey?"[set]":null,configContextLimit:n,resolvedSource:r.source}}),{resolved:r,configPath:e,perSessionModel:o,configContextLimit:n,supportsImage:i.modelImageSupport?.[r.model]===!0}}async createRuntime(t,e,o,s,a,i){const n=await this.loadRuntimeConstructor(),r=o.mcpConfigPath||$(s);let c=[];try{c=await F(o.agentId,o.scopeKey,typeof o.browserAllowPrivate=="boolean"?{allowPrivate:o.browserAllowPrivate}:void 0)}catch(d){l(`[acode-adapter] browser tools injection skipped for agent ${o.agentId}:`,d.message)}let p=[];if(P(o.agentId??"",W)&&(p=c),o.agentId&&P(o.agentId,D))try{const d=a?.model?{model:a.model,supportsImage:i===!0,...a.baseURL?{baseURL:a.baseURL}:{},...a.apiKey?{apiKey:a.apiKey}:{}}:void 0,f=await O(o.agentId,d);f.length>0&&(p=[...p,...f])}catch(d){l(`[acode-adapter] desktop tools injection skipped for agent ${o.agentId}:`,d.message)}const m=new n({sessionId:t,agentId:o.agentId,workingDirectory:o.workingDirectory,configPath:r,skillsDir:Z(s),model:e,systemPrompt:typeof o.systemPrompt=="string"?o.systemPrompt:void 0,globalPrompt:typeof o.globalPrompt=="string"?o.globalPrompt:void 0,rolePrompt:typeof o.rolePrompt=="string"?o.rolePrompt:void 0,memory:typeof o.memory=="string"?o.memory:void 0,env:o.envOverrides,subAgentManager:et,terminalManager:ot,...o.subAgentModel?{subAgentModel:o.subAgentModel}:{},...o.subAgentEffort?{subAgentEffort:o.subAgentEffort}:{},...o.instanceAiConfig?.effort?{effort:o.instanceAiConfig.effort}:{},onFileChange:d=>it({...d,agentId:o.agentId,workspacePath:o.workingDirectory}),extraBuiltInTools:p,subAgentSuiteTools:c,subAgentSuiteToolProvider:this.buildSubAgentSuiteToolProvider(o.agentId)});return x().log({level:"info",category:"resolve",message:"ACode provider resolved",source:"bridge",sessionId:t,details:{resolvedModel:e,perInstanceModel:o.instanceAiConfig?.model||null,perInstanceBaseURL:o.instanceAiConfig?.baseURL?"[set]":null,perInstanceApiKey:o.instanceAiConfig?.apiKey?"[set]":null,configPath:r}}),m.on("event",d=>this.forwardAcodeEvent(d)),m}buildSubAgentSuiteToolProvider(t){return async e=>{if(!t)return[];if(!P(t,D))return[];if(e.length===0)return rt();if(!e.some(a=>{const i=a.trim().replace(/[.*]+$/,"");return i==="desktop"||i.startsWith("desktop.")}))return[];const s=await this.resolveAgentAiInfo(t);return O(t,s)}}async loadRuntimeConstructor(){if(this.runtimeConstructor)return this.runtimeConstructor;const t=At(),e=await import(St(t));if(!e.ACodeRuntime)throw new Error(`ACode runtime export not found: ${t}`);return this.runtimeConstructor=e.ACodeRuntime,this.runtimeConstructor}requireSession(t){const e=this.sessions.get(t);if(!e)throw new Error("ACode session not found");return e}startInitialPromptTurn(t,e){const o=this.sessions.get(t);o&&(o.adapterSession.status="thinking",this.emit("status-change",t,"thinking"),this.startSubmitTimeoutDetection(t,o,"startInitialPromptTurn"),o.runtime.submit(e).then(()=>{this.cancelSubmitTimeoutDetection(o),this.recoverResolvedTurnWithoutTerminalEvent(t)}).catch(s=>{const a=this.sessions.get(t);a&&(this.cancelSubmitTimeoutDetection(a),this.emitRuntimeError(t,s,{recover:!0}))}))}forwardAcodeEvent(t){const e=this.sessions.get(t.sessionId);if(e){if(e.autoPollActive&&(e.autoPollLastActivityAt=Date.now()),t.type==="assistant_delta"){const o=typeof t.data.text=="string"?t.data.text:"";e.autoPollActive&&(e.autoPollObservedAssistantText=!0),e.adapterSession.messages.push({id:U(),sessionId:t.sessionId,role:"assistant",content:o,timestamp:t.timestamp}),this.resetDataFlowWatchdog(t.sessionId,e),this.emitProviderEvent(t,"text_delta",{text:o});return}if(t.type==="thinking_delta"){const o=typeof t.data.text=="string"?t.data.text:"";this.resetDataFlowWatchdog(t.sessionId,e),this.emitProviderEvent(t,"thinking",{text:o});return}if(t.type==="command_output"){this.emitProviderEvent(t,"command_output",{text:typeof t.data.text=="string"?t.data.text:"",stream:yt(t.data.stream),sequence:typeof t.data.sequence=="number"?t.data.sequence:void 0,cwd:typeof t.data.cwd=="string"?t.data.cwd:void 0,commandLineCount:typeof t.data.commandLineCount=="number"?t.data.commandLineCount:void 0,commandFilePath:typeof t.data.commandFilePath=="string"?t.data.commandFilePath:void 0});return}if(t.type==="background_command_completed"){this.emitProviderEvent(t,"background_command_completed",t.data);return}if(t.type==="ai_request"){const o=J(t.data),s=t.data.lastUsage,a=h(s?.inputTokens),i=h(s?.outputTokens),n=h(s?.cacheHitTokens),r=h(s?.cacheMissTokens),c=!!(s&&(a>0||i>0));let p;if(c&&(a>0&&(e.adapterSession.totalUsage.inputTokens=a),i>0&&(e.adapterSession.totalUsage.outputTokens=i),(s?.cacheHitTokens!==void 0||s?.cacheMissTokens!==void 0)&&(e.adapterSession.totalUsage.cacheHitTokens=n,e.adapterSession.totalUsage.cacheMissTokens=r),p={...e.adapterSession.totalUsage},w(`ai_request lastUsage applied: ${JSON.stringify(s)} -> totalUsage=${JSON.stringify(e.adapterSession.totalUsage)}`)),!c&&o>0){const d=e.adapterSession.totalUsage.inputTokens;d>0?e.adapterSession.totalUsage.inputTokens=Math.min(o,Math.floor(d*1.5)):e.adapterSession.totalUsage.inputTokens=o,p={...e.adapterSession.totalUsage}}e.adapterSession.status==="compacting"&&(e.adapterSession.status="thinking"),e.adapterSession.status==="waiting_input"&&(e.adapterSession.status="thinking");const g={actionType:"ai_request",actionLabel:"AI\u8BF7\u6C42",actionDetail:this.formatAiRequestActionDetail(t.data)};p&&(g.usage=p),w(`ai_request handled: estimatedContextTokens=${t.data.estimatedContextTokens??"n/a"} totalUsage=${JSON.stringify(e.adapterSession.totalUsage)} displayUsage=${JSON.stringify(p??null)}`),this.emit("status-change",t.sessionId,e.adapterSession.status,g),this.startDataFlowWatchdog(t.sessionId,e),e.adapterSession.status==="thinking"&&e.watchdogSubmitStartTime&&(e.watchdogSubmitStartTime=Date.now()),this.emitProviderEvent(t,"ai_request",{model:typeof t.data.model=="string"?t.data.model:void 0,endpoint:typeof t.data.endpoint=="string"?t.data.endpoint:void 0,requestMethod:typeof t.data.requestMethod=="string"?t.data.requestMethod:void 0,requestUrl:typeof t.data.requestUrl=="string"?t.data.requestUrl:void 0,requestHeaders:wt(t.data.requestHeaders),stream:typeof t.data.stream=="boolean"?t.data.stream:void 0,messageCount:typeof t.data.messageCount=="number"?t.data.messageCount:void 0,toolCount:typeof t.data.toolCount=="number"?t.data.toolCount:void 0,lastUserMessagePreview:typeof t.data.lastUserMessagePreview=="string"?t.data.lastUserMessagePreview:void 0,requestBody:typeof t.data.requestBody=="string"?t.data.requestBody:void 0});return}if(t.type==="turn_complete"){const o=Ct(t.data.usage);if(o){const a=e.adapterSession.totalUsage.inputTokens,i=a>0&&o.inputTokens<Math.floor(a*.2)&&!o.hasCache;w(`turn_complete usage: raw=${JSON.stringify(t.data.usage)} parsed=${JSON.stringify(o)} currentInput=${a} threshold20pct=${Math.floor(a*.2)} isFallbackUsage=${i}`),i?o.outputTokens>0&&(e.adapterSession.totalUsage.outputTokens=o.outputTokens):(e.adapterSession.totalUsage.inputTokens=o.inputTokens,e.adapterSession.totalUsage.outputTokens=o.outputTokens),(o.cacheHitTokens||o.cacheMissTokens)&&(e.adapterSession.totalUsage.cacheHitTokens=o.cacheHitTokens,e.adapterSession.totalUsage.cacheMissTokens=o.cacheMissTokens,l(`[ACode] \u{1F4B0} Cache usage (overwrite from runtime cumulative): hit=${e.adapterSession.totalUsage.cacheHitTokens}, miss=${e.adapterSession.totalUsage.cacheMissTokens} (turn delta: hit=${o.cacheHitTokens||0}, miss=${o.cacheMissTokens||0})`)),w(`totalUsage after turn_complete: ${JSON.stringify(e.adapterSession.totalUsage)}`)}else w(`turn_complete has NO parseable usage: raw=${JSON.stringify(t.data.usage)} failed=${t.data.failed===!0} aborted=${t.data.aborted===!0}`);const s=e.adapterSession.status;if(l(`[ACode] turn_complete event received (session: ${t.sessionId}), previous status: ${s}, failed: ${t.data.failed===!0}, aborted: ${t.data.aborted===!0}`),Pt(t.data)){l(`[ACode] Recovering from failed turn_complete (session: ${t.sessionId})`),this.cancelDataFlowWatchdog(e),this.recoverTurnFailure(t.sessionId,e);return}if(t.data.aborted===!0&&e.autoPollActive){l(`[ACode] Recovering from aborted turn_complete (session: ${t.sessionId}), using R2 2s backoff instead of immediate rearm`),this.cancelDataFlowWatchdog(e),this.recoverTurnFailure(t.sessionId,e);return}if(this.cancelDataFlowWatchdog(e),this.emitProviderEvent(t,"turn_complete",{usage:e.adapterSession.totalUsage,responseBody:typeof t.data.responseBody=="string"?t.data.responseBody:void 0,finishReason:typeof t.data.finishReason=="string"?t.data.finishReason:void 0}),e.adapterSession.status="waiting_input",this.emit("status-change",t.sessionId,"waiting_input",{usage:e.adapterSession.totalUsage}),w(`status-change emitted (waiting_input after turn_complete): usage=${JSON.stringify(e.adapterSession.totalUsage)}`),l(`[ACode] Status changed to waiting_input after turn_complete (session: ${t.sessionId})`),e.autoPollActive&&e.autoPollObservedAssistantText&&!e.autoPollObservedPollingTool&&!e.autoPollObservedAnyTool){e.stopAutoPollAfterCurrentTurn=!0,console.warn(`[${this.displayName}] Auto-poll turn produced assistant text without calling any tool; stopping auto-poll rearm for session ${t.sessionId}`);return}this.armIdleLoopOrAutoPoll(t.sessionId);return}if(t.type==="session_complete"){this.cancelDataFlowWatchdog(e),this.cancelScheduledAutoPoll(e),e.failedTurnRecoveryScheduled=!1,e.idlePollLoop?.stop(),e.adapterSession.status="completed",this.emitProviderEvent(t,"session_complete",{exitCode:Number(t.data.exitCode)||0}),this.emit("status-change",t.sessionId,"completed");return}if(t.type==="question_request"){this.cancelDataFlowWatchdog(e),this.cancelSubmitTimeoutDetection(e);const o=typeof t.data.toolCallId=="string"?t.data.toolCallId:"",s=Array.isArray(t.data.questions)?t.data.questions:[];o&&(e.pendingQuestionToolCallId=o,e.pendingQuestions=s),this.emit("ask-user-question",{sessionId:t.sessionId,toolCallId:o||void 0,questions:s});return}if(t.type==="error"){if(t.data.nonFatal){this.resetDataFlowWatchdog(t.sessionId,e),this.emitProviderEvent(t,"error",{text:String(t.data.message||"ACode runtime error")});return}this.cancelDataFlowWatchdog(e),e.adapterSession.status="error",this.emitProviderEvent(t,"error",{text:String(t.data.message||"ACode runtime error")}),this.emit("status-change",t.sessionId,"error"),e.autoPollActive||this.recoverTurnFailure(t.sessionId,e);return}if(t.type==="mcp_status"){if(!t.data.action&&Array.isArray(t.data.tools)){const f=t.data.tools;f.some(T=>ut(T))||console.warn(`[${this.displayName}] ACode runtime is not exposing a poll_message tool. The LLM cannot call poll_message. Please configure an MCP server that provides poll_message (e.g. aws-mcp) in the dashboard panel for this runtime.`);const A=Array.isArray(t.data.servers)?t.data.servers:[],k=f.map(T=>({name:String(T.name??""),source:String(T.source??""),description:String(T.description??"")})).filter(T=>T.name),b={kind:"mcp",mcpServers:A,mcpTools:k};e.cachedMcpCapabilities=b,e.lastMcpCapabilities=b,e.lastCombinedCapabilities={kind:"combined",mcpServers:A,mcpTools:k,skills:e.lastCombinedCapabilities?.skills??[],skillsDir:e.lastCombinedCapabilities?.skillsDir,skillGroups:e.lastCombinedCapabilities?.skillGroups??[]},l(`[cap-diag] MCP capabilities cached: ${A.length} servers, ${k.length} tools`,{sessionId:t.sessionId,servers:A,toolNames:k.map(T=>T.name)}),e.capabilitiesFallbackTimer&&clearTimeout(e.capabilitiesFallbackTimer),e.capabilitiesFallbackTimer=setTimeout(()=>{const T=e.cachedMcpCapabilities;if(!T)return;const C={...T,skills:[],skillGroups:[]};this.emitProviderEvent(t,"runtime_capabilities",{capabilities:C,actionType:"runtime_capabilities",actionLabel:"\u8FD0\u884C\u65F6\u80FD\u529B",actionDetail:JSON.stringify(C)}),l(`[cap-diag] MCP capabilities emitted via fallback (skill_status not received within ${j}ms)`,{sessionId:t.sessionId,mcpServers:T.mcpServers,mcpToolsCount:T.mcpTools?.length??0}),e.cachedMcpCapabilities=void 0,e.capabilitiesFallbackTimer=void 0},j);return}const o=String(t.data.action??"");l(`[ACode] \u{1F4E1} mcp_status event: action=${o}, server=${typeof t.data.server=="string"?t.data.server:"?"}, tool=${typeof t.data.tool=="string"?t.data.tool:"?"}, toolUseId=${typeof t.data.toolUseId=="string"?t.data.toolUseId.slice(0,16)+"\u2026":"none"}, failed=${t.data.failed===!0}, session=${t.sessionId}, status=${e.adapterSession.status}`);const s=typeof t.data.server=="string"?t.data.server:"mcp",a=typeof t.data.tool=="string"?t.data.tool:"",i=s&&a?`${s}__${a}`:a||s,n=t.data.arguments&&typeof t.data.arguments=="object"&&!Array.isArray(t.data.arguments)?t.data.arguments:void 0,r=dt(i,n);e.autoPollActive&&(e.autoPollObservedAnyTool=!0,r.actionType==="idle"&&(e.autoPollObservedPollingTool=!0));const c=Lt(r.actionType)?r.actionDetail||z(void 0,s,a):z(r.actionDetail,s,a),p=typeof t.data.toolUseId=="string"?t.data.toolUseId:void 0,m=n?JSON.stringify(n,null,2):void 0,g={toolName:c,rawToolName:i,actionType:r.actionType,actionLabel:r.actionLabel,actionDetail:c,...m?{actionInput:m}:{},...n?{toolInput:n}:{},...p?{toolUseId:p,actionId:p}:{},metadata:{mcpServer:s}};if(t.data.action==="tool_result"){this.emitProviderEvent(t,"tool_use_end",{...g,toolResult:typeof t.data.result=="string"?t.data.result:JSON.stringify(t.data.result??"")});const f=r.actionType==="idle"&&!$t(t.data.result)?"waiting_input":"thinking";e.adapterSession.status=f,r.actionType==="idle"&&(e.idleToolActiveAt=void 0),this.cancelDataFlowWatchdog(e),e.pendingToolEventData=void 0;const _=r.actionType==="idle";this.emit("status-change",t.sessionId,f,_||f==="thinking"?void 0:g);return}const d=r.actionType==="idle"?"waiting_input":"tool_using";e.adapterSession.status=d,r.actionType==="idle"&&(e.idleToolActiveAt=Date.now()),d==="tool_using"&&(this.resetDataFlowWatchdog(t.sessionId,e),e.pendingToolEventData={...g}),this.emitProviderEvent(t,"tool_use_start",g),this.emit("status-change",t.sessionId,d,g);return}if(t.type==="skill_status"){const s=(Array.isArray(t.data.skills)?t.data.skills:[]).map(m=>({name:String(m.name??""),description:typeof m.description=="string"?m.description:void 0,directory:typeof m.directory=="string"?m.directory:void 0})).filter(m=>m.name),a=typeof t.data.skillsDir=="string"?t.data.skillsDir:void 0,n=(Array.isArray(t.data.skillGroups)?t.data.skillGroups:[]).map(m=>{const g=Array.isArray(m.skills)?m.skills:[];return{dir:typeof m.dir=="string"?m.dir:"",exists:m.exists===!0,skills:g.map(d=>({name:String(d.name??""),description:typeof d.description=="string"?d.description:void 0,directory:typeof d.directory=="string"?d.directory:void 0})).filter(d=>d.name)}}).filter(m=>m.dir),r=e.cachedMcpCapabilities??e.lastMcpCapabilities,c=e.cachedMcpCapabilities!==void 0,p={kind:"combined",mcpServers:r?.mcpServers??[],mcpTools:r?.mcpTools??[],skills:s,skillsDir:a,skillGroups:n};this.emitProviderEvent(t,"runtime_capabilities",{capabilities:p,actionType:"runtime_capabilities",actionLabel:"\u8FD0\u884C\u65F6\u80FD\u529B",actionDetail:JSON.stringify(p)}),e.lastCombinedCapabilities=p,l(`[cap-diag] Combined capabilities emitted ${c?"(startup merge)":"(runtime refresh)"}: ${(r?.mcpTools??[]).length} MCP tools, ${s.length} skills`,{sessionId:t.sessionId,mcpServers:r?.mcpServers??[],skillsDir:a}),e.capabilitiesFallbackTimer&&(clearTimeout(e.capabilitiesFallbackTimer),e.capabilitiesFallbackTimer=void 0),e.cachedMcpCapabilities=void 0;return}if(t.type==="startup_phase"){l(`[ACode] \u{1F680} startup_phase swallowed: ${String(t.data.phase??"unknown")}`,{sessionId:t.sessionId});return}if(t.type==="command_status"){if(t.data.action==="commands_loaded"){l(`[ACode] \u{1F4CB} command_status commands_loaded swallowed: ${typeof t.data.installedCommandCount=="number"?t.data.installedCommandCount:"?"} commands`,{sessionId:t.sessionId});return}this.emitProviderEvent(t,"thinking",{text:JSON.stringify(t.data)});return}if(t.type==="session_started"){const o=J(t.data),s=h(t.data.contextLimit)||void 0,a=h(t.data.maxOutput)||void 0,i=h(t.data.inputLimit)||void 0,n=h(t.data.compactionThreshold)||void 0;let r=!1;o>0&&(e.adapterSession.totalUsage.inputTokens=o,e.adapterSession.totalUsage.outputTokens=0,r=!0),s!==void 0&&(e.adapterSession.totalUsage.contextLimit=s,r=!0),a!==void 0&&(e.adapterSession.totalUsage.maxOutput=a,r=!0),i!==void 0&&(e.adapterSession.totalUsage.inputLimit=i,r=!0),n!==void 0&&(e.adapterSession.totalUsage.compactionThreshold=n,r=!0),r&&this.emit("status-change",t.sessionId,e.adapterSession.status,{usage:e.adapterSession.totalUsage});return}if(t.type==="exit_plan_mode"){e.adapterSession.status="waiting_input";const o=typeof t.data.plan=="string"?t.data.plan:void 0;this.emitProviderEvent(t,"exit_plan_mode",{toolInput:t.data.toolInput&&typeof t.data.toolInput=="object"?t.data.toolInput:void 0,text:o||"\u9000\u51FA\u8BA1\u5212\u6A21\u5F0F"}),this.emit("status-change",t.sessionId,"waiting_input",{actionLabel:"\u5BA1\u6279\u8BA1\u5212",actionDetail:o||"\u7B49\u5F85\u7528\u6237\u5BA1\u6279\u9000\u51FA\u8BA1\u5212\u6A21\u5F0F"});return}if(t.type==="context_compaction"){const o=t.data,s=o.action,a=s==="start",i=s==="end",n=s==="phase",r=o.parentId,c=o.compactionId;let p,m;if(a){const d=String(o.sizeKB??o.sizeBeforeKB??"?"),f=String(o.messageCount??o.messageCountBefore??"?"),_=o.estimatedTokens,A=o.actualInputTokens?`input=${o.actualInputTokens}`:"",k=o.actualOutputTokens?`output=${o.actualOutputTokens}`:"",b=o.trigger?`, \u89E6\u53D1: ${o.trigger}`:"";p="\u4E0A\u4E0B\u6587\u538B\u7F29\u5F00\u59CB",_!==void 0?m=`\u538B\u7F29\u524D: ~${_} tokens, \u6D88\u606F: ${f}\u6761`+(A?`, \u5B9E\u9645 tokens: ${A} ${k}`:"")+b:m=`\u538B\u7F29\u524D: ${d}KB, \u6D88\u606F: ${f}\u6761`+(A?`, \u5B9E\u9645 tokens: ${A} ${k}`:"")+b}else if(n)p=String(o.phaseLabel??"\u538B\u7F29\u9636\u6BB5"),m=String(o.phaseDetail??"");else{const d=o.tokensBefore,f=o.tokensAfter,_=o.freedTokens,A=String(o.sizeBeforeKB??"?"),k=String(o.sizeAfterKB??"?"),b=String(o.freedKB??"?"),T=String(o.strategy??"?"),C=Number(o.prunedToolMessages??0),S=Number(o.summarizedMessages??0);p="\u538B\u7F29\u5B8C\u6210",d!==void 0&&f!==void 0?m=`\u91CA\u653E: ${_??d-f} tokens, ${d} tokens \u2192 ${f} tokens, \u7B56\u7565: ${T}`+(C?`, \u88C1\u526A\u5DE5\u5177: ${C}\u6761`:"")+(S?`, \u6458\u8981\u5316: ${S}\u6761`:""):m=`\u91CA\u653E: ${b}KB, ${A}KB \u2192 ${k}KB, \u7B56\u7565: ${T}`+(C?`, \u88C1\u526A\u5DE5\u5177: ${C}\u6761`:"")+(S?`, \u6458\u8981\u5316: ${S}\u6761`:"")}a&&(e.adapterSession.status="compacting");const g={actionType:"context_compaction",actionLabel:p,actionDetail:m};if(a&&c)g.actionId=c;else if((n||i)&&c)if(g.parentId=c,n){const d=String(o.phase??"unknown");g.actionId=`${c}-phase-${d}`}else g.actionId=`${c}-end`;n&&r&&!g.parentId&&(g.parentId=r),i&&(e.adapterSession.totalUsage.inputTokens=h(o.tokensAfter),e.adapterSession.totalUsage.outputTokens=0,g.usage={...e.adapterSession.totalUsage}),this.emitProviderEvent(t,"context_compaction",g),this.emit("status-change",t.sessionId,"compacting",g);return}this.emitProviderEvent(t,"thinking",{text:JSON.stringify(t.data)})}}emitProviderEvent(t,e,o){this.emit("event",{type:e,sessionId:t.sessionId,timestamp:t.timestamp,data:o})}armIdleLoopOrAutoPoll(t){const e=this.sessions.get(t);if(!(!e||this.isTerminalStatus(e.adapterSession.status))){if(e.idleCommands?.idleInputCommand){this.getIdlePollLoop(e).start();return}this.scheduleAutoPoll(t)}}getIdlePollLoop(t){if(t.idlePollLoop)return t.idlePollLoop;const e=t.adapterSession.sessionId;return t.idlePollLoop=new lt({getStatus:()=>this.sessions.get(e)?.adapterSession.status,getCommand:()=>this.sessions.get(e)?.idleCommands?.idleInputCommand,isPollingCommand:o=>L(o),preDispatchHook:()=>null,dispatchPollingPrompt:(o,s)=>this.submitAutoPollPrompt(e,s?o:_t,{keepWaitingStatus:!0}),dispatchRegularIdleCommand:o=>this.submitAutoPollPrompt(e,o)}),t.idlePollLoop}submitAutoPollPrompt(t,e,o){const s=this.sessions.get(t);if(!s||this.isTerminalStatus(s.adapterSession.status))return;const a=(s.autoPollToken??0)+1;s.autoPollToken=a,s.autoPollActive=!0,s.autoPollObservedPollingTool=!1,s.autoPollObservedAssistantText=!1,s.autoPollObservedAnyTool=!1,s.stopAutoPollAfterCurrentTurn=!1,s.autoPollQueuedAt=Date.now(),s.autoPollLastActivityAt=Date.now(),s.idleToolActiveAt=void 0,o?.keepWaitingStatus||(s.adapterSession.status="thinking",this.emit("status-change",t,"thinking")),this.startSubmitTimeoutDetection(t,s,"submitAutoPollPrompt"),s.runtime.submit(e).catch(i=>{this.emitRuntimeError(t,i)}).finally(()=>{const i=this.sessions.get(t);if(i){if(i.autoPollToken!==a){l(`[ACode] submitAutoPollPrompt.finally: token mismatch (my=${a}, current=${i.autoPollToken}), skipping cleanup \u2014 newer turn has taken over`);return}if(this.cancelSubmitTimeoutDetection(i),i.autoPollActive=!1,i.failedTurnRecoveryScheduled||i.autoPollTimer){i.failedTurnRecoveryScheduled=!1;return}if(i.stopAutoPollAfterCurrentTurn){i.stopAutoPollAfterCurrentTurn=!1,i.autoPollObservedPollingTool=!1,i.autoPollObservedAssistantText=!1,i.autoPollObservedAnyTool=!1;return}if(i.adapterSession.status==="error"){this.recoverTurnFailure(t,i);return}if(i.adapterSession.status==="thinking"||i.adapterSession.status==="tool_using"){this.recoverResolvedTurnWithoutTerminalEvent(t);return}i.adapterSession.status==="waiting_input"&&this.armIdleLoopOrAutoPoll(t)}})}scheduleAutoPoll(t,e=ht){const o=this.sessions.get(t);!o||o.autoPollActive||o.autoPollTimer||this.isTerminalStatus(o.adapterSession.status)||(o.autoPollTimer=setTimeout(()=>{const s=this.sessions.get(t);!s||s.autoPollActive||this.isTerminalStatus(s.adapterSession.status)||(s.autoPollTimer=void 0,this.submitAutoPollPrompt(t,N,{keepWaitingStatus:!0}))},e))}cancelScheduledAutoPoll(t){t.autoPollTimer&&(clearTimeout(t.autoPollTimer),t.autoPollTimer=void 0)}isTerminalStatus(t){return t==="completed"||t==="terminated"}emitRuntimeError(t,e,o){const s=this.sessions.get(t);s&&(s.adapterSession.status="error",this.emitRuntimeErrorEvent(t,e),this.emit("status-change",t,"error"),o?.recover&&this.recoverTurnFailure(t,s))}emitRuntimeErrorEvent(t,e){const o=new Date().toISOString();this.emit("event",{type:"error",sessionId:t,timestamp:o,data:{text:e instanceof Error?e.message:String(e)}})}estimateOutputTokensFromMessages(t){const e=t.filter(o=>o.role==="assistant").map(o=>o.content).join("");return Math.max(0,Math.round(e.length/4))}recoverTurnFailure(t,e){if(this.isTerminalStatus(e.adapterSession.status))return;if(e.idleToolActiveAt=void 0,e.adapterSession.status==="tool_using"&&e.pendingToolEventData){const n=e.pendingToolEventData;l(`[ACode] recoverTurnFailure: \u8865\u53D1 tool_use_end (tool: ${n.toolName??"unknown"}) \u5173\u95ED\u65F6\u95F4\u7EBF\u6761\u76EE\uFF0C\u907F\u514D\u6C38\u4E45\u5361\u5728\u5DE5\u5177\u6267\u884C\u72B6\u6001`),this.emit("event",{type:"tool_use_end",sessionId:t,timestamp:new Date().toISOString(),data:{...n,toolResult:"[aborted] \u5DE5\u5177\u6267\u884C\u88AB\u6570\u636E\u6D41\u770B\u95E8\u72D7\u4E2D\u65AD"}}),e.pendingToolEventData=void 0}const o=this.estimateOutputTokensFromMessages(e.adapterSession.messages);if(o>0){const n=e.adapterSession.totalUsage.outputTokens;e.adapterSession.totalUsage.outputTokens=o,l(`[ACode] recoverTurnFailure: \u4F30\u7B97\u8986\u76D6 output tokens ${n} -> ${o} (totalUsage now: input=${e.adapterSession.totalUsage.inputTokens}, output=${e.adapterSession.totalUsage.outputTokens})`)}const s=e.idleCommands?.idleInputCommand,i=!!(s&&L(s))?{actionType:"idle",actionLabel:"\u76D1\u542C\u6D88\u606F",actionDetail:"aws-mcp/poll_message"}:void 0;if(e.autoPollTimer||e.failedTurnRecoveryScheduled){e.adapterSession.status!=="waiting_input"&&(e.adapterSession.status="waiting_input",this.emit("status-change",t,"waiting_input",{usage:e.adapterSession.totalUsage,...i}));return}this.cancelScheduledAutoPoll(e),e.adapterSession.status="waiting_input",this.emit("status-change",t,"waiting_input",{usage:e.adapterSession.totalUsage,...i}),e.failedTurnRecoveryScheduled=!0,e.autoPollTimer=setTimeout(()=>{const n=this.sessions.get(t);if(!n||n.autoPollActive||this.isTerminalStatus(n.adapterSession.status)){n&&(n.failedTurnRecoveryScheduled=!1);return}n.autoPollTimer=void 0,n.failedTurnRecoveryScheduled=!1,n.idleCommands?.idleInputCommand?this.getIdlePollLoop(n).start():this.submitAutoPollPrompt(t,N,{keepWaitingStatus:!0})},Tt)}recoverResolvedTurnWithoutTerminalEvent(t){l(`[ACode] \u25B6\uFE0F recoverResolvedTurnWithoutTerminalEvent called for session ${t}`);const e=this.sessions.get(t);if(!e||this.isTerminalStatus(e.adapterSession.status)){l(`[ACode] Skipping recovery: entry=${!!e}, isTerminal=${e?this.isTerminalStatus(e.adapterSession.status):"N/A"}`);return}if(l(`[ACode] Current status: ${e.adapterSession.status}`),e.adapterSession.status!=="thinking"&&e.adapterSession.status!=="tool_using"){l(`[ACode] Skipping recovery: status is ${e.adapterSession.status} (not thinking/tool_using)`);return}console.warn(`[ACode] \u26A0\uFE0F Detected stuck state: ${e.adapterSession.status} after submit resolved! Recovering to waiting_input. If runtime.submit() is still pending (e.g., built-in tool execution not interruptible by abort()), the submitQueue is deadlocked and subsequent auto-poll/user submits will never execute.`),l("[ACode] Recovering to waiting_input..."),e.adapterSession.status="waiting_input";const o=e.idleCommands?.idleInputCommand,a=!!(o&&L(o))?{actionType:"idle",actionLabel:"\u76D1\u542C\u6D88\u606F",actionDetail:"aws-mcp/poll_message"}:void 0;this.emit("status-change",t,"waiting_input",a),l(`[ACode] \u2705 Recovery complete, status now: ${e.adapterSession.status}`),l("[ACode] \u25B6\uFE0F Arming idle loop or auto-poll..."),this.armIdleLoopOrAutoPoll(t),l("[ACode] \u2705 Idle loop armed, recovery process complete")}startSubmitTimeoutDetection(t,e,o){this.cancelSubmitTimeoutDetection(e),e.watchdogSubmitStartTime=Date.now(),e.watchdogLastDataFlowTime=Date.now(),e.watchdogTimer=setInterval(()=>{const s=this.sessions.get(t);if(!s){this.cancelSubmitTimeoutDetection(e);return}const a=s.adapterSession.status,i=Date.now();if(a==="waiting_input"){if(s.autoPollActive&&s.autoPollLastActivityAt&&s.idleToolActiveAt===void 0&&i-s.autoPollLastActivityAt>=ft){console.warn(`[ACode] CRITICAL: stuck auto-poll detected after ${Math.round((i-s.autoPollLastActivityAt)/1e3)}s (source: ${o}, session: ${t}): submit queued but no runtime events and no active poll_message tool. Forcing recovery (runtime force-settle will unblock submitQueue).`),this.executeWatchdogRecovery(t,s,o,"stuck_autopoll",i-s.autoPollLastActivityAt);return}s.watchdogSubmitStartTime=i,s.watchdogLastDataFlowTime=i;return}if(a==="tool_using"){const c=i-(s.watchdogLastDataFlowTime||i);if(c>=gt){const p=String(s.pendingToolEventData?.rawToolName??"");if(p.endsWith("await_complete")){console.warn(`[ACode] tool_using elapsed ${Math.round(c/1e3)}s but await_complete is running (session: ${t}, tool: ${p}), skipping recovery (sub-agents have their own watchdogs, bg commands have timeout limits)`),s.watchdogSubmitStartTime=i,s.watchdogLastDataFlowTime=i;return}if(console.warn(`[ACode] CRITICAL: tool_using slow timeout triggered after ${Math.round(c/1e3)}s (source: ${o}, session: ${t}). Tool execution likely hung. Forcing recovery via recoverTurnFailure.`),s.runtime.detachCurrentToolExecution?.()){console.warn(`[ACode] tool_using slow (${Math.round(c/1e3)}s): detached tool ${p} to background (session: ${t}); waiting for the real tool_result to continue the turn`),s.watchdogSubmitStartTime=i,s.watchdogLastDataFlowTime=i;return}this.executeWatchdogRecovery(t,s,o,"tool_using_slow",c);return}s.watchdogSubmitStartTime=i;return}if(a!=="thinking")return;const n=i-(s.watchdogSubmitStartTime||i),r=i-(s.watchdogLastDataFlowTime||i);if(H>0&&r>=H){console.warn(`[ACode] CRITICAL: Data flow watchdog triggered after ${Math.round(r/1e3)}s (source: ${o}, session: ${t}, status: ${a}). No stream data received. Forcing recovery via recoverTurnFailure.`),this.executeWatchdogRecovery(t,s,o,"data_flow",r);return}if(K>0&&n>=K){console.warn(`[ACode] CRITICAL: submit timeout detected after ${Math.round(n/1e3)}s (source: ${o}, session: ${t}, status: ${a}). Forcing recovery to prevent permanent state stuck.`),this.executeWatchdogRecovery(t,s,o,"submit_timeout",n);return}},pt)}executeWatchdogRecovery(t,e,o,s,a){l(`[ACode] Watchdog (${s}): calling runtime.abort() after ${Math.round(a/1e3)}s...`);try{e.runtime.abort(),l(`[ACode] Watchdog (${s}): runtime.abort() called`)}catch(i){console.warn(`[ACode] \u26A0\uFE0F Watchdog (${s}): runtime.abort() threw: ${i instanceof Error?i.message:String(i)}`)}this.cancelSubmitTimeoutDetection(e),this.recoverTurnFailure(t,e),console.warn(`[ACode] \u26A0\uFE0F Watchdog (${s}) recovery complete. If abort() could not cancel the underlying operation, submitQueue may still be deadlocked.`)}cancelSubmitTimeoutDetection(t){t.watchdogTimer&&(clearInterval(t.watchdogTimer),t.watchdogTimer=void 0),t.watchdogSubmitStartTime=void 0,t.watchdogLastDataFlowTime=void 0}resetDataFlowWatchdog(t,e){e.watchdogLastDataFlowTime=Date.now(),e.watchdogSubmitStartTime=Date.now()}startDataFlowWatchdog(t,e){e.watchdogLastDataFlowTime=Date.now()}cancelDataFlowWatchdog(t){t.watchdogLastDataFlowTime=Date.now()}formatAiRequestActionDetail(t){const e=`
|
|
1
|
+
import{EventEmitter as z}from"node:events";import I from"node:path";import Y from"node:fs/promises";import{pathToFileURL as X}from"node:url";import{v4 as U}from"uuid";import{getAcodeConfigFile as $,getAcodeSkillsDir as V}from"../config.js";import{getReleasedAcodeEntryPath as Z}from"../services/acode-package.js";import{getInstanceAiConfigDebugLogger as x}from"../utils/instance-ai-config-debug-logger.js";import{redactForLog as R}from"../services/instance-ai-config-service.js";import{subAgentManager as tt}from"../services/sub-agent-manager-instance.js";import{agentPtyManager as et}from"../services/agent-pty-manager.js";import{resolveAcodeProviderConfig as ot}from"./instance-ai-config-resolver.js";import{recordAgentFileChange as st}from"../services/workspaceTaskChangeWatcher.js";import{getBrowserTools as v,closeBrowserSession as it,registerListenerWakeHook as at,unregisterListenerWakeHook as F}from"../services/browser-session-manager.js";import{getDesktopTools as O,getDesktopToolsIfReady as nt}from"../services/desktop-mcp-manager.js";import{BROWSER_FEATURE_KEY as B,DESKTOP_FEATURE_KEY as E,isFeatureEnabled as P}from"../services/instance-features.js";import{isMessagePollingIdleCommand as L,isPollMessageToolDescriptor as rt}from"./acode-tool-names.js";import{IdlePollLoop as ut}from"./idle-poll-loop.js";import{getCanonicalMcpDetail as W,getToolActionInfo as lt}from"./types.js";const dt=process.env.ACODE_COMPACTION_DEBUG==="1";function l(...u){dt&&console.log(...u)}const ct=process.env.ACODE_TOKEN_DEBUG==="1";function w(...u){ct&&console.log("[TokenDebug][Adapter]",...u)}const q=["Continue the AgentsWork message loop now.","You MUST call the exact MCP tool named aws-mcp__poll_message as your next action and wait for the next assigned message or task.","Do not answer in plain text before calling aws-mcp__poll_message.","After handling any received work, reply through the appropriate aws-mcp messaging tool, then continue listening again."].join(" "),mt=5e3;function D(u,t){const e=process.env[u];if(e===void 0||e.trim()==="")return t;const o=Number(e.trim());return Number.isFinite(o)&&o>=0?Math.floor(o):t}const N=D("ACODE_DATA_FLOW_WATCHDOG_MS",12e4),pt=5*6e4,gt=D("ACODE_STUCK_AUTOPOLL_TIMEOUT_MS",5*6e4),ft=250,ht=2e3,H=D("ACODE_SUBMIT_TIMEOUT_MS",12e4),K=3e3,Tt="\u7CFB\u7EDF\u63D0\u9192\uFF1A\u5982\u679C\u4EFB\u52A1\u5DF2\u5B8C\u6210\u6216\u6CA1\u6709\u5176\u5B83\u8981\u505A\u7684\uFF0C\u5148\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";function _t(){return I.resolve(Z())}function At(u){return X(I.resolve(u)).href}const j=128e3,y={"claude-4":{contextLimit:2e5,maxOutput:8192},"claude-sonnet-4":{contextLimit:2e5,maxOutput:8192},"claude-3-5-sonnet":{contextLimit:2e5,maxOutput:8192},"claude-3-opus":{contextLimit:2e5,maxOutput:8192},"claude-3-haiku":{contextLimit:2e5,maxOutput:8192},"claude-2":{contextLimit:1e5,maxOutput:4096},"gpt-4o":{contextLimit:128e3,maxOutput:16384},"gpt-4-turbo":{contextLimit:128e3,maxOutput:4096},"gpt-4":{contextLimit:8192,maxOutput:4096},"gpt-3.5-turbo":{contextLimit:16384,maxOutput:4096},o1:{contextLimit:2e5,maxOutput:1e5},"o3-mini":{contextLimit:2e5,maxOutput:1e5},"gemini-2.0-flash":{contextLimit:1048576,maxOutput:8192},"gemini-2.5-pro":{contextLimit:1048576,maxOutput:8192},"gemini-1.5-pro":{contextLimit:2097152,maxOutput:8192},"gemini-1.5-flash":{contextLimit:1048576,maxOutput:8192},deepseek:{contextLimit:64e3,maxOutput:8192},"deepseek-chat":{contextLimit:64e3,maxOutput:8192},"deepseek-reasoner":{contextLimit:64e3,maxOutput:8192},"qwen-max":{contextLimit:32e3,maxOutput:8192},"qwen-plus":{contextLimit:128e3,maxOutput:8192},"qwen-turbo":{contextLimit:1e6,maxOutput:8192},"glm-4":{contextLimit:128e3,maxOutput:4096},"yi-":{contextLimit:2e5,maxOutput:4096},"llama-3":{contextLimit:8192,maxOutput:4096},"llama-2":{contextLimit:4096,maxOutput:4096},mistral:{contextLimit:32e3,maxOutput:4096},mixtral:{contextLimit:32e3,maxOutput:4096},codestral:{contextLimit:256e3,maxOutput:8192},grok:{contextLimit:131072,maxOutput:4096},"nova-":{contextLimit:2e5,maxOutput:8192}};function St(u){if(!u)return j;const t=u.toLowerCase().trim();if(y[t])return y[t].contextLimit;const e=Object.keys(y).filter(o=>t.startsWith(o)).sort((o,s)=>s.length-o.length);return e.length>0?y[e[0]].contextLimit:j}const Q=4096;function kt(u){if(!u)return Q;const t=u.toLowerCase().trim();if(y[t])return y[t].maxOutput;const e=Object.keys(y).filter(o=>t.startsWith(o)).sort((o,s)=>s.length-o.length);return e.length>0?y[e[0]].maxOutput:Q}function bt(u){if(!u||typeof u!="object")return;const t=u,e=h(t.inputTokens,t.input_tokens,t.promptTokens,t.prompt_tokens),o=h(t.outputTokens,t.output_tokens,t.completionTokens,t.completion_tokens);if(e===0&&o===0)return;let s=h(t.cacheHitTokens,t.promptCacheHitTokens,t.prompt_cache_hit_tokens),n=h(t.cacheMissTokens,t.promptCacheMissTokens,t.prompt_cache_miss_tokens),i=t.cacheHitTokens!==void 0||t.cacheMissTokens!==void 0||t.promptCacheHitTokens!==void 0||t.promptCacheMissTokens!==void 0||t.prompt_cache_hit_tokens!==void 0||t.prompt_cache_miss_tokens!==void 0;if(s===0&&n===0){const a=h(t.cache_read_input_tokens),r=h(t.cache_creation_input_tokens);a>0||r>0?(s=a,n=r+h(t.input_tokens),i=!0):(s=h(t.cache_hit_tokens),n=h(t.cache_miss_tokens),i=i||t.cache_hit_tokens!==void 0||t.cache_miss_tokens!==void 0)}if(s===0&&n===0){const a=h(t.prompt_tokens_details?.cached_tokens);a>0&&(s=a,n=e>a?e-a:0,i=!0)}return{inputTokens:e,outputTokens:o,...s>0||n>0?{cacheHitTokens:s,cacheMissTokens:n}:{},...i?{hasCache:!0}:{}}}function h(...u){for(const t of u){const e=Number(t);if(Number.isFinite(e)&&e>0)return e}return 0}function G(u){return h(u.estimatedContextTokens,u.contextTokens,u.context_tokens,u.contextUsedTokens,u.context_used_tokens)}function Ct(u){return u==="stderr"||u==="mixed"?u:"stdout"}function yt(u){if(!u||typeof u!="object"||Array.isArray(u))return;const t={};for(const[e,o]of Object.entries(u))typeof o=="string"&&(t[e]=o);return Object.keys(t).length>0?t:void 0}function wt(u){return u.failed===!0}function J(u,t,e){if(!u)return e?`${t}/${e}`:t;const o=`${t}__`;return u.startsWith(o)?W(`${t}__${u.slice(o.length)}`):W(u.replace("/","__"))}function Pt(u){return u==="read_file"||u==="edit_file"||u==="write_file"||u==="bash"}function Lt(u){const t=$t(u);return t?[t.directMessages,t.groupMessages,t.messages].some(e=>Array.isArray(e)&&e.length>0):typeof u=="string"&&u.trim().length>0}function $t(u){if(u&&typeof u=="object"&&!Array.isArray(u))return u;if(!(typeof u!="string"||!u.trim()))try{const t=JSON.parse(u);return t&&typeof t=="object"&&!Array.isArray(t)?t:void 0}catch{return}}class Jt extends z{constructor(){super(...arguments),this.providerId="acode",this.displayName="ACode",this.sessions=new Map,this.listenerWakeHooks=new Map}async startSession(t,e){const o=e.mcpConfigPath||$(),{resolved:s,configContextLimit:n,supportsImage:i}=await this.resolveAcodeProvider(e,o),a=s.model,r=n??St(a),c=kt(a),p={sessionId:t,status:"starting",messages:[],createdAt:new Date().toISOString(),totalUsage:{inputTokens:0,outputTokens:0,contextLimit:r,maxOutput:c,cacheHitTokens:0,cacheMissTokens:0}};this.sessions.set(t,{adapterSession:p,config:e,runtime:await this.createRuntime(t,a,e,s,i),autoPollActive:!1}),this.emit("status-change",t,"starting");const m=this.sessions.get(t);if(!m)throw new Error("ACode session was not initialized");const d=()=>{const g=this.sessions.get(t);g&&this.getIdlePollLoop(g).start()};this.listenerWakeHooks.set(t,d),at(e.agentId,d);try{await m.runtime.start(),p.status="waiting_input",this.emit("status-change",t,"waiting_input",{usage:m.adapterSession.totalUsage}),e.initialPrompt?.trim()?this.startInitialPromptTurn(t,e.initialPrompt):this.armIdleLoopOrAutoPoll(t)}catch(g){p.status="error",this.emitRuntimeErrorEvent(t,g),this.emit("status-change",t,"error");const f=this.sessions.get(t);throw f?.capabilitiesFallbackTimer&&clearTimeout(f.capabilitiesFallbackTimer),this.sessions.delete(t),F(e.agentId,this.listenerWakeHooks.get(t)),this.listenerWakeHooks.delete(t),g}}async sendMessage(t,e){const o=Date.now();l("[ACode] \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"),l("[ACode] \u25B6\uFE0F sendMessage STARTED"),l(`[ACode] Session: ${t}`),l(`[ACode] Message: ${e.slice(0,100)}${e.length>100?"...":""}`),l("[ACode] \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");const s=this.requireSession(t),n=s.adapterSession.status;l(`[ACode] Previous status: ${n}`),this.cancelScheduledAutoPoll(s),s.failedTurnRecoveryScheduled=!1,s.idlePollLoop?.stop();const i={id:U(),sessionId:t,role:"user",content:e,timestamp:new Date().toISOString()};s.adapterSession.messages.push(i),this.emit("conversation-message",t,i),l(`[ACode] Changing status: ${n} \u2192 thinking`),s.adapterSession.status="thinking",this.emit("status-change",t,"thinking"),this.startSubmitTimeoutDetection(t,s,"sendMessage");try{l("[ACode] \u25B6\uFE0F Calling runtime.submit()...");const a=Date.now();await s.runtime.submit(e);const r=Date.now()-a;this.cancelSubmitTimeoutDetection(s),l(`[ACode] \u2705 runtime.submit() completed in ${r}ms`),l(`[ACode] Current status after submit: ${s.adapterSession.status}`),l("[ACode] \u25B6\uFE0F Calling recoverResolvedTurnWithoutTerminalEvent()..."),this.recoverResolvedTurnWithoutTerminalEvent(t),l(`[ACode] Status after recovery: ${s.adapterSession.status}`);const c=Date.now()-o;l("[ACode] \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"),l(`[ACode] \u2705 sendMessage COMPLETED in ${c}ms`),l("[ACode] \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550")}catch(a){const r=Date.now()-o;console.error(`[ACode] \u274C sendMessage FAILED after ${r}ms:`,a instanceof Error?a.message:String(a)),this.cancelSubmitTimeoutDetection(s),l("[ACode] \u25B6\uFE0F Calling emitRuntimeError with recover=true..."),this.emitRuntimeError(t,a,{recover:!0}),l(`[ACode] Status after error recovery: ${s.adapterSession.status}`)}}async sendConfirmation(t,e){}async sendQuestionAnswer(t,e){const o=this.sessions.get(t);if(!o)return;const s=o.pendingQuestionToolCallId;if(!s){l(`[AcodeSdkAdapter] sendQuestionAnswer: no pending question for session ${t}`);return}o.pendingQuestionToolCallId=void 0,o.pendingQuestions=void 0,o.runtime.submitQuestionAnswer&&o.runtime.submitQuestionAnswer(s,e),this.startSubmitTimeoutDetection(t,o,"sendQuestionAnswer")}async abortCurrentTurn(t){await this.requireSession(t).runtime.abort()}async resetContext(t){const e=this.requireSession(t);if(this.cancelScheduledAutoPoll(e),e.failedTurnRecoveryScheduled=!1,e.autoPollActive=!1,e.autoPollObservedPollingTool=!1,e.autoPollObservedAssistantText=!1,e.autoPollObservedAnyTool=!1,e.stopAutoPollAfterCurrentTurn=!1,e.idlePollLoop?.stop(),!e.runtime.resetContext)throw new Error("ACode runtime does not support context reset");await e.runtime.resetContext(),e.adapterSession.messages=[];const o=e.adapterSession.totalUsage;if(e.adapterSession.totalUsage={inputTokens:0,outputTokens:0,contextLimit:o.contextLimit,maxOutput:o.maxOutput,inputLimit:o.inputLimit,compactionThreshold:o.compactionThreshold,cacheHitTokens:o.cacheHitTokens,cacheMissTokens:o.cacheMissTokens},e.adapterSession.status="waiting_input",this.emit("status-change",t,"waiting_input",{usage:e.adapterSession.totalUsage}),e.config.initialPrompt?.trim()){this.startInitialPromptTurn(t,e.config.initialPrompt);return}this.armIdleLoopOrAutoPoll(t)}async terminateSession(t){const e=this.sessions.get(t);if(!e)return;this.cancelScheduledAutoPoll(e),e.failedTurnRecoveryScheduled=!1,e.idlePollLoop?.stop(),e.capabilitiesFallbackTimer&&(clearTimeout(e.capabilitiesFallbackTimer),e.capabilitiesFallbackTimer=void 0),await e.runtime.stop();const o=e.config.agentId;o&&(F(o,this.listenerWakeHooks.get(t)),it(o)),this.listenerWakeHooks.delete(t),e.adapterSession.status="terminated",this.sessions.delete(t),this.emit("status-change",t,"terminated")}getConversation(t){return this.sessions.get(t)?.adapterSession.messages??[]}hasSession(t){return this.sessions.has(t)}getProviderSessionId(t){return this.sessions.has(t)?t:void 0}getSessionStatus(t){return this.sessions.get(t)?.adapterSession.status}notifyForceMessage(t){const e=this.sessions.get(t);return e?.runtime?.notifyForceMessage?(e.runtime.notifyForceMessage(),!0):!1}getCapabilities(t){return this.sessions.get(t)?.lastCombinedCapabilities}async resolveAgentAiInfo(t){try{const e=[...this.sessions.values()].find(i=>i.config.agentId===t);if(!e)return;const o=e.config.mcpConfigPath||$(),{resolved:s,supportsImage:n}=await this.resolveAcodeProvider(e.config,o);return s?.model?{model:s.model,supportsImage:n===!0,...s.baseURL?{baseURL:s.baseURL}:{},...s.apiKey?{apiKey:s.apiKey}:{}}:void 0}catch{return}}async applyAgentFeatures(t){if(!t)return;const e=P(t,E),o=P(t,B);for(const[s,n]of this.sessions){if(n.config.agentId!==t)continue;const i=n.runtime;try{if(e){const a=await O(t,await this.resolveAgentAiInfo(t)),r=i.addBuiltInTools?.(a)??0;r>0&&l(`[acode-adapter] session ${s}: ${r} desktop tools hot-added for agent ${t}`)}else{const a=i.removeBuiltInToolsByPrefix?.("desktop_")??0;a>0&&l(`[acode-adapter] session ${s}: ${a} desktop tools hot-removed for agent ${t}`)}}catch(a){l(`[acode-adapter] session ${s}: desktop feature hot-sync failed for agent ${t}:`,a.message)}if(o)try{const a=await v(t,n.config.scopeKey,typeof n.config.browserAllowPrivate=="boolean"?{allowPrivate:n.config.browserAllowPrivate}:void 0),r=i.addBuiltInTools?.(a)??0;r>0&&l(`[acode-adapter] session ${s}: ${r} browser tools hot-added for agent ${t}`)}catch(a){l(`[acode-adapter] session ${s}: browser feature hot-sync failed for agent ${t}:`,a.message)}}this.syncMcpToolsForAgent(t)}syncMcpToolsForAgent(t){if(t){for(const[e,o]of this.sessions)if(o.config.agentId===t)try{o.runtime.requestMcpToolsRefresh?.()}catch(s){l(`[acode-adapter] session ${e}: mcp tools refresh failed for agent ${t}:`,s.message)}}}getPendingQuestion(t){const e=this.sessions.get(t);if(e?.pendingQuestionToolCallId)return{toolCallId:e.pendingQuestionToolCallId,questions:e.pendingQuestions??[]}}cleanup(){for(const t of this.sessions.keys())this.terminateSession(t)}setIdleCommands(t,e){const o=this.sessions.get(t);if(o){if(o.idleCommands=e,this.cancelScheduledAutoPoll(o),e.idleInputCommand&&L(e.idleInputCommand)){this.getIdlePollLoop(o).start();return}o.adapterSession.status==="waiting_input"&&(e.idleInputCommand||e.nonInputCommand)&&this.getIdlePollLoop(o).start()}}setRuntimeConstructorForTest(t){this.runtimeConstructor=t}async loadAcodeProviderSection(t){try{const e=await Y.readFile(t,"utf-8"),o=JSON.parse(e),n=o.provider?.default,i=n?.options,a=h(o.contextLimit),r={},c={},p=n?.models;if(p&&typeof p=="object"){for(const[m,d]of Object.entries(p))if(d&&typeof d=="object"){const g=h(d.contextLimit);g>0&&(r[m.trim()]=g);const f=d.modalities?.input,A=Array.isArray(f)&&f.includes("image")||d.supportsImageInput===!0;c[m.trim()]=A===!0}}return{...n?.model?{model:n.model}:{},...i?.baseURL||i?.baseUrl?{baseURL:i?.baseURL||i?.baseUrl}:{},...i?.apiKey?{apiKey:i.apiKey}:{},...a>0?{contextLimit:a}:{},...Object.keys(r).length>0?{modelContextLimits:r}:{},...Object.keys(c).length>0?{modelImageSupport:c}:{}}}catch(e){const o=e instanceof Error?e.message:String(e);return x().log({level:"warn",category:"load",message:`loadAcodeProviderSection failed: ${t}: ${o}`,source:"bridge"}),{}}}async resolveAcodeProvider(t,e){const o=typeof t.model=="string"&&t.model.trim()?t.model.trim():void 0,s=x();s.log({level:"info",category:"resolve",message:"resolveAcodeProvider \u8F93\u5165",source:"bridge",details:{configModel:t.model??null,configInstanceAiConfig:t.instanceAiConfig?R(t.instanceAiConfig):null,configPath:e}});const n={...t.instanceAiConfig?.model?{model:t.instanceAiConfig.model}:{},...t.instanceAiConfig?.baseURL?{baseURL:t.instanceAiConfig.baseURL}:{},...t.instanceAiConfig?.apiKey?{apiKey:t.instanceAiConfig.apiKey}:{},...t.instanceAiConfig?.effort?{effort:t.instanceAiConfig.effort}:{},...o?{model:o}:{}},i=await this.loadAcodeProviderSection(e);let a=i.contextLimit;if(!a&&i.modelContextLimits){const c=o||t.instanceAiConfig?.model||i.model;c&&i.modelContextLimits[c]&&(a=i.modelContextLimits[c])}const r=ot(n,i,"acode-default");return s.log({level:"info",category:"resolve",message:"resolveAcodeProvider \u89E3\u6790\u7ED3\u679C",source:"bridge",details:{instanceConfig:R(n),globalConfigModel:i?.model??null,resolvedModel:r.model,resolvedBaseURL:r.baseURL??null,resolvedApiKey:r.apiKey?"[set]":null,configContextLimit:a,resolvedSource:r.source}}),{resolved:r,configPath:e,perSessionModel:o,configContextLimit:a,supportsImage:i.modelImageSupport?.[r.model]===!0}}async createRuntime(t,e,o,s,n){const i=await this.loadRuntimeConstructor(),a=o.mcpConfigPath||$();let r=[];try{r=await v(o.agentId,o.scopeKey,typeof o.browserAllowPrivate=="boolean"?{allowPrivate:o.browserAllowPrivate}:void 0)}catch(d){l(`[acode-adapter] browser tools injection skipped for agent ${o.agentId}:`,d.message)}let c=[];if(P(o.agentId??"",B)&&(c=r),o.agentId&&P(o.agentId,E))try{const d=s?.model?{model:s.model,supportsImage:n===!0,...s.baseURL?{baseURL:s.baseURL}:{},...s.apiKey?{apiKey:s.apiKey}:{}}:void 0,g=await O(o.agentId,d);g.length>0&&(c=[...c,...g])}catch(d){l(`[acode-adapter] desktop tools injection skipped for agent ${o.agentId}:`,d.message)}const p=new i({sessionId:t,agentId:o.agentId,workingDirectory:o.workingDirectory,configPath:a,skillsDir:V(),model:e,systemPrompt:typeof o.systemPrompt=="string"?o.systemPrompt:void 0,globalPrompt:typeof o.globalPrompt=="string"?o.globalPrompt:void 0,rolePrompt:typeof o.rolePrompt=="string"?o.rolePrompt:void 0,memory:typeof o.memory=="string"?o.memory:void 0,env:o.envOverrides,subAgentManager:tt,terminalManager:et,...o.subAgentModel?{subAgentModel:o.subAgentModel}:{},...o.subAgentEffort?{subAgentEffort:o.subAgentEffort}:{},...o.instanceAiConfig?.effort?{effort:o.instanceAiConfig.effort}:{},onFileChange:d=>st({...d,agentId:o.agentId,workspacePath:o.workingDirectory}),extraBuiltInTools:c,subAgentSuiteTools:r,subAgentSuiteToolProvider:this.buildSubAgentSuiteToolProvider(o.agentId)});return x().log({level:"info",category:"resolve",message:"ACode provider resolved",source:"bridge",sessionId:t,details:{resolvedModel:e,perInstanceModel:o.instanceAiConfig?.model||null,perInstanceBaseURL:o.instanceAiConfig?.baseURL?"[set]":null,perInstanceApiKey:o.instanceAiConfig?.apiKey?"[set]":null,configPath:a}}),p.on("event",d=>this.forwardAcodeEvent(d)),p}buildSubAgentSuiteToolProvider(t){return async e=>{if(!t)return[];if(!P(t,E))return[];if(e.length===0)return nt();if(!e.some(n=>{const i=n.trim().replace(/[.*]+$/,"");return i==="desktop"||i.startsWith("desktop.")}))return[];const s=await this.resolveAgentAiInfo(t);return O(t,s)}}async loadRuntimeConstructor(){if(this.runtimeConstructor)return this.runtimeConstructor;const t=_t(),e=await import(At(t));if(!e.ACodeRuntime)throw new Error(`ACode runtime export not found: ${t}`);return this.runtimeConstructor=e.ACodeRuntime,this.runtimeConstructor}requireSession(t){const e=this.sessions.get(t);if(!e)throw new Error("ACode session not found");return e}startInitialPromptTurn(t,e){const o=this.sessions.get(t);o&&(o.adapterSession.status="thinking",this.emit("status-change",t,"thinking"),this.startSubmitTimeoutDetection(t,o,"startInitialPromptTurn"),o.runtime.submit(e).then(()=>{this.cancelSubmitTimeoutDetection(o),this.recoverResolvedTurnWithoutTerminalEvent(t)}).catch(s=>{const n=this.sessions.get(t);n&&(this.cancelSubmitTimeoutDetection(n),this.emitRuntimeError(t,s,{recover:!0}))}))}forwardAcodeEvent(t){const e=this.sessions.get(t.sessionId);if(e){if(e.autoPollActive&&(e.autoPollLastActivityAt=Date.now()),t.type==="assistant_delta"){const o=typeof t.data.text=="string"?t.data.text:"";e.autoPollActive&&(e.autoPollObservedAssistantText=!0),e.adapterSession.messages.push({id:U(),sessionId:t.sessionId,role:"assistant",content:o,timestamp:t.timestamp}),this.resetDataFlowWatchdog(t.sessionId,e),this.emitProviderEvent(t,"text_delta",{text:o});return}if(t.type==="thinking_delta"){const o=typeof t.data.text=="string"?t.data.text:"";this.resetDataFlowWatchdog(t.sessionId,e),this.emitProviderEvent(t,"thinking",{text:o});return}if(t.type==="command_output"){this.emitProviderEvent(t,"command_output",{text:typeof t.data.text=="string"?t.data.text:"",stream:Ct(t.data.stream),sequence:typeof t.data.sequence=="number"?t.data.sequence:void 0,cwd:typeof t.data.cwd=="string"?t.data.cwd:void 0,commandLineCount:typeof t.data.commandLineCount=="number"?t.data.commandLineCount:void 0,commandFilePath:typeof t.data.commandFilePath=="string"?t.data.commandFilePath:void 0});return}if(t.type==="background_command_completed"){this.emitProviderEvent(t,"background_command_completed",t.data);return}if(t.type==="ai_request"){const o=G(t.data),s=t.data.lastUsage,n=h(s?.inputTokens),i=h(s?.outputTokens),a=h(s?.cacheHitTokens),r=h(s?.cacheMissTokens),c=!!(s&&(n>0||i>0));let p;if(c&&(n>0&&(e.adapterSession.totalUsage.inputTokens=n),i>0&&(e.adapterSession.totalUsage.outputTokens=i),(s?.cacheHitTokens!==void 0||s?.cacheMissTokens!==void 0)&&(e.adapterSession.totalUsage.cacheHitTokens=a,e.adapterSession.totalUsage.cacheMissTokens=r),p={...e.adapterSession.totalUsage},w(`ai_request lastUsage applied: ${JSON.stringify(s)} -> totalUsage=${JSON.stringify(e.adapterSession.totalUsage)}`)),!c&&o>0){const g=e.adapterSession.totalUsage.inputTokens;g>0?e.adapterSession.totalUsage.inputTokens=Math.min(o,Math.floor(g*1.5)):e.adapterSession.totalUsage.inputTokens=o,p={...e.adapterSession.totalUsage}}e.adapterSession.status==="compacting"&&(e.adapterSession.status="thinking"),e.adapterSession.status==="waiting_input"&&(e.adapterSession.status="thinking");const d={actionType:"ai_request",actionLabel:"AI\u8BF7\u6C42",actionDetail:this.formatAiRequestActionDetail(t.data)};p&&(d.usage=p),w(`ai_request handled: estimatedContextTokens=${t.data.estimatedContextTokens??"n/a"} totalUsage=${JSON.stringify(e.adapterSession.totalUsage)} displayUsage=${JSON.stringify(p??null)}`),this.emit("status-change",t.sessionId,e.adapterSession.status,d),this.startDataFlowWatchdog(t.sessionId,e),e.adapterSession.status==="thinking"&&e.watchdogSubmitStartTime&&(e.watchdogSubmitStartTime=Date.now()),this.emitProviderEvent(t,"ai_request",{model:typeof t.data.model=="string"?t.data.model:void 0,endpoint:typeof t.data.endpoint=="string"?t.data.endpoint:void 0,requestMethod:typeof t.data.requestMethod=="string"?t.data.requestMethod:void 0,requestUrl:typeof t.data.requestUrl=="string"?t.data.requestUrl:void 0,requestHeaders:yt(t.data.requestHeaders),stream:typeof t.data.stream=="boolean"?t.data.stream:void 0,messageCount:typeof t.data.messageCount=="number"?t.data.messageCount:void 0,toolCount:typeof t.data.toolCount=="number"?t.data.toolCount:void 0,lastUserMessagePreview:typeof t.data.lastUserMessagePreview=="string"?t.data.lastUserMessagePreview:void 0,requestBody:typeof t.data.requestBody=="string"?t.data.requestBody:void 0});return}if(t.type==="turn_complete"){const o=bt(t.data.usage);if(o){const n=e.adapterSession.totalUsage.inputTokens,i=n>0&&o.inputTokens<Math.floor(n*.2)&&!o.hasCache;w(`turn_complete usage: raw=${JSON.stringify(t.data.usage)} parsed=${JSON.stringify(o)} currentInput=${n} threshold20pct=${Math.floor(n*.2)} isFallbackUsage=${i}`),i?o.outputTokens>0&&(e.adapterSession.totalUsage.outputTokens=o.outputTokens):(e.adapterSession.totalUsage.inputTokens=o.inputTokens,e.adapterSession.totalUsage.outputTokens=o.outputTokens),(o.cacheHitTokens||o.cacheMissTokens)&&(e.adapterSession.totalUsage.cacheHitTokens=o.cacheHitTokens,e.adapterSession.totalUsage.cacheMissTokens=o.cacheMissTokens,l(`[ACode] \u{1F4B0} Cache usage (overwrite from runtime cumulative): hit=${e.adapterSession.totalUsage.cacheHitTokens}, miss=${e.adapterSession.totalUsage.cacheMissTokens} (turn delta: hit=${o.cacheHitTokens||0}, miss=${o.cacheMissTokens||0})`)),w(`totalUsage after turn_complete: ${JSON.stringify(e.adapterSession.totalUsage)}`)}else w(`turn_complete has NO parseable usage: raw=${JSON.stringify(t.data.usage)} failed=${t.data.failed===!0} aborted=${t.data.aborted===!0}`);const s=e.adapterSession.status;if(l(`[ACode] turn_complete event received (session: ${t.sessionId}), previous status: ${s}, failed: ${t.data.failed===!0}, aborted: ${t.data.aborted===!0}`),wt(t.data)){l(`[ACode] Recovering from failed turn_complete (session: ${t.sessionId})`),this.cancelDataFlowWatchdog(e),this.recoverTurnFailure(t.sessionId,e);return}if(t.data.aborted===!0&&e.autoPollActive){l(`[ACode] Recovering from aborted turn_complete (session: ${t.sessionId}), using R2 2s backoff instead of immediate rearm`),this.cancelDataFlowWatchdog(e),this.recoverTurnFailure(t.sessionId,e);return}if(this.cancelDataFlowWatchdog(e),this.emitProviderEvent(t,"turn_complete",{usage:e.adapterSession.totalUsage,responseBody:typeof t.data.responseBody=="string"?t.data.responseBody:void 0,finishReason:typeof t.data.finishReason=="string"?t.data.finishReason:void 0}),e.adapterSession.status="waiting_input",this.emit("status-change",t.sessionId,"waiting_input",{usage:e.adapterSession.totalUsage}),w(`status-change emitted (waiting_input after turn_complete): usage=${JSON.stringify(e.adapterSession.totalUsage)}`),l(`[ACode] Status changed to waiting_input after turn_complete (session: ${t.sessionId})`),e.autoPollActive&&e.autoPollObservedAssistantText&&!e.autoPollObservedPollingTool&&!e.autoPollObservedAnyTool){e.stopAutoPollAfterCurrentTurn=!0,console.warn(`[${this.displayName}] Auto-poll turn produced assistant text without calling any tool; stopping auto-poll rearm for session ${t.sessionId}`);return}this.armIdleLoopOrAutoPoll(t.sessionId);return}if(t.type==="session_complete"){this.cancelDataFlowWatchdog(e),this.cancelScheduledAutoPoll(e),e.failedTurnRecoveryScheduled=!1,e.idlePollLoop?.stop(),e.adapterSession.status="completed",this.emitProviderEvent(t,"session_complete",{exitCode:Number(t.data.exitCode)||0}),this.emit("status-change",t.sessionId,"completed");return}if(t.type==="question_request"){this.cancelDataFlowWatchdog(e),this.cancelSubmitTimeoutDetection(e);const o=typeof t.data.toolCallId=="string"?t.data.toolCallId:"",s=Array.isArray(t.data.questions)?t.data.questions:[];o&&(e.pendingQuestionToolCallId=o,e.pendingQuestions=s),this.emit("ask-user-question",{sessionId:t.sessionId,toolCallId:o||void 0,questions:s});return}if(t.type==="error"){if(t.data.nonFatal){this.resetDataFlowWatchdog(t.sessionId,e),this.emitProviderEvent(t,"error",{text:String(t.data.message||"ACode runtime error")});return}this.cancelDataFlowWatchdog(e),e.adapterSession.status="error",this.emitProviderEvent(t,"error",{text:String(t.data.message||"ACode runtime error")}),this.emit("status-change",t.sessionId,"error"),e.autoPollActive||this.recoverTurnFailure(t.sessionId,e);return}if(t.type==="mcp_status"){if(!t.data.action&&Array.isArray(t.data.tools)){const f=t.data.tools;f.some(T=>rt(T))||console.warn(`[${this.displayName}] ACode runtime is not exposing a poll_message tool. The LLM cannot call poll_message. Please configure an MCP server that provides poll_message (e.g. aws-mcp) in the dashboard panel for this runtime.`);const _=Array.isArray(t.data.servers)?t.data.servers:[],k=f.map(T=>({name:String(T.name??""),source:String(T.source??""),description:String(T.description??"")})).filter(T=>T.name),b={kind:"mcp",mcpServers:_,mcpTools:k};e.cachedMcpCapabilities=b,e.lastMcpCapabilities=b,e.lastCombinedCapabilities={kind:"combined",mcpServers:_,mcpTools:k,skills:e.lastCombinedCapabilities?.skills??[],skillsDir:e.lastCombinedCapabilities?.skillsDir,skillGroups:e.lastCombinedCapabilities?.skillGroups??[]},l(`[cap-diag] MCP capabilities cached: ${_.length} servers, ${k.length} tools`,{sessionId:t.sessionId,servers:_,toolNames:k.map(T=>T.name)}),e.capabilitiesFallbackTimer&&clearTimeout(e.capabilitiesFallbackTimer),e.capabilitiesFallbackTimer=setTimeout(()=>{const T=e.cachedMcpCapabilities;if(!T)return;const C={...T,skills:[],skillGroups:[]};this.emitProviderEvent(t,"runtime_capabilities",{capabilities:C,actionType:"runtime_capabilities",actionLabel:"\u8FD0\u884C\u65F6\u80FD\u529B",actionDetail:JSON.stringify(C)}),l(`[cap-diag] MCP capabilities emitted via fallback (skill_status not received within ${K}ms)`,{sessionId:t.sessionId,mcpServers:T.mcpServers,mcpToolsCount:T.mcpTools?.length??0}),e.cachedMcpCapabilities=void 0,e.capabilitiesFallbackTimer=void 0},K);return}const o=String(t.data.action??"");l(`[ACode] \u{1F4E1} mcp_status event: action=${o}, server=${typeof t.data.server=="string"?t.data.server:"?"}, tool=${typeof t.data.tool=="string"?t.data.tool:"?"}, toolUseId=${typeof t.data.toolUseId=="string"?t.data.toolUseId.slice(0,16)+"\u2026":"none"}, failed=${t.data.failed===!0}, session=${t.sessionId}, status=${e.adapterSession.status}`);const s=typeof t.data.server=="string"?t.data.server:"mcp",n=typeof t.data.tool=="string"?t.data.tool:"",i=s&&n?`${s}__${n}`:n||s,a=t.data.arguments&&typeof t.data.arguments=="object"&&!Array.isArray(t.data.arguments)?t.data.arguments:void 0,r=lt(i,a);e.autoPollActive&&(e.autoPollObservedAnyTool=!0,r.actionType==="idle"&&(e.autoPollObservedPollingTool=!0));const c=Pt(r.actionType)?r.actionDetail||J(void 0,s,n):J(r.actionDetail,s,n),p=typeof t.data.toolUseId=="string"?t.data.toolUseId:void 0,m=a?JSON.stringify(a,null,2):void 0,d={toolName:c,rawToolName:i,actionType:r.actionType,actionLabel:r.actionLabel,actionDetail:c,...m?{actionInput:m}:{},...a?{toolInput:a}:{},...p?{toolUseId:p,actionId:p}:{},metadata:{mcpServer:s}};if(t.data.action==="tool_result"){this.emitProviderEvent(t,"tool_use_end",{...d,toolResult:typeof t.data.result=="string"?t.data.result:JSON.stringify(t.data.result??"")});const f=r.actionType==="idle"&&!Lt(t.data.result)?"waiting_input":"thinking";e.adapterSession.status=f,r.actionType==="idle"&&(e.idleToolActiveAt=void 0),this.cancelDataFlowWatchdog(e),e.pendingToolEventData=void 0;const A=r.actionType==="idle";this.emit("status-change",t.sessionId,f,A||f==="thinking"?void 0:d);return}const g=r.actionType==="idle"?"waiting_input":"tool_using";e.adapterSession.status=g,r.actionType==="idle"&&(e.idleToolActiveAt=Date.now()),g==="tool_using"&&(this.resetDataFlowWatchdog(t.sessionId,e),e.pendingToolEventData={...d}),this.emitProviderEvent(t,"tool_use_start",d),this.emit("status-change",t.sessionId,g,d);return}if(t.type==="skill_status"){const s=(Array.isArray(t.data.skills)?t.data.skills:[]).map(m=>({name:String(m.name??""),description:typeof m.description=="string"?m.description:void 0,directory:typeof m.directory=="string"?m.directory:void 0})).filter(m=>m.name),n=typeof t.data.skillsDir=="string"?t.data.skillsDir:void 0,a=(Array.isArray(t.data.skillGroups)?t.data.skillGroups:[]).map(m=>{const d=Array.isArray(m.skills)?m.skills:[];return{dir:typeof m.dir=="string"?m.dir:"",exists:m.exists===!0,skills:d.map(g=>({name:String(g.name??""),description:typeof g.description=="string"?g.description:void 0,directory:typeof g.directory=="string"?g.directory:void 0})).filter(g=>g.name)}}).filter(m=>m.dir),r=e.cachedMcpCapabilities??e.lastMcpCapabilities,c=e.cachedMcpCapabilities!==void 0,p={kind:"combined",mcpServers:r?.mcpServers??[],mcpTools:r?.mcpTools??[],skills:s,skillsDir:n,skillGroups:a};this.emitProviderEvent(t,"runtime_capabilities",{capabilities:p,actionType:"runtime_capabilities",actionLabel:"\u8FD0\u884C\u65F6\u80FD\u529B",actionDetail:JSON.stringify(p)}),e.lastCombinedCapabilities=p,l(`[cap-diag] Combined capabilities emitted ${c?"(startup merge)":"(runtime refresh)"}: ${(r?.mcpTools??[]).length} MCP tools, ${s.length} skills`,{sessionId:t.sessionId,mcpServers:r?.mcpServers??[],skillsDir:n}),e.capabilitiesFallbackTimer&&(clearTimeout(e.capabilitiesFallbackTimer),e.capabilitiesFallbackTimer=void 0),e.cachedMcpCapabilities=void 0;return}if(t.type==="startup_phase"){l(`[ACode] \u{1F680} startup_phase swallowed: ${String(t.data.phase??"unknown")}`,{sessionId:t.sessionId});return}if(t.type==="command_status"){if(t.data.action==="commands_loaded"){l(`[ACode] \u{1F4CB} command_status commands_loaded swallowed: ${typeof t.data.installedCommandCount=="number"?t.data.installedCommandCount:"?"} commands`,{sessionId:t.sessionId});return}this.emitProviderEvent(t,"thinking",{text:JSON.stringify(t.data)});return}if(t.type==="session_started"){const o=G(t.data),s=h(t.data.contextLimit)||void 0,n=h(t.data.maxOutput)||void 0,i=h(t.data.inputLimit)||void 0,a=h(t.data.compactionThreshold)||void 0;let r=!1;o>0&&(e.adapterSession.totalUsage.inputTokens=o,e.adapterSession.totalUsage.outputTokens=0,r=!0),s!==void 0&&(e.adapterSession.totalUsage.contextLimit=s,r=!0),n!==void 0&&(e.adapterSession.totalUsage.maxOutput=n,r=!0),i!==void 0&&(e.adapterSession.totalUsage.inputLimit=i,r=!0),a!==void 0&&(e.adapterSession.totalUsage.compactionThreshold=a,r=!0),r&&this.emit("status-change",t.sessionId,e.adapterSession.status,{usage:e.adapterSession.totalUsage});return}if(t.type==="exit_plan_mode"){e.adapterSession.status="waiting_input";const o=typeof t.data.plan=="string"?t.data.plan:void 0;this.emitProviderEvent(t,"exit_plan_mode",{toolInput:t.data.toolInput&&typeof t.data.toolInput=="object"?t.data.toolInput:void 0,text:o||"\u9000\u51FA\u8BA1\u5212\u6A21\u5F0F"}),this.emit("status-change",t.sessionId,"waiting_input",{actionLabel:"\u5BA1\u6279\u8BA1\u5212",actionDetail:o||"\u7B49\u5F85\u7528\u6237\u5BA1\u6279\u9000\u51FA\u8BA1\u5212\u6A21\u5F0F"});return}if(t.type==="context_compaction"){const o=t.data,s=o.action,n=s==="start",i=s==="end",a=s==="phase",r=o.parentId,c=o.compactionId;let p,m;if(n){const g=String(o.sizeKB??o.sizeBeforeKB??"?"),f=String(o.messageCount??o.messageCountBefore??"?"),A=o.estimatedTokens,_=o.actualInputTokens?`input=${o.actualInputTokens}`:"",k=o.actualOutputTokens?`output=${o.actualOutputTokens}`:"",b=o.trigger?`, \u89E6\u53D1: ${o.trigger}`:"";p="\u4E0A\u4E0B\u6587\u538B\u7F29\u5F00\u59CB",A!==void 0?m=`\u538B\u7F29\u524D: ~${A} tokens, \u6D88\u606F: ${f}\u6761`+(_?`, \u5B9E\u9645 tokens: ${_} ${k}`:"")+b:m=`\u538B\u7F29\u524D: ${g}KB, \u6D88\u606F: ${f}\u6761`+(_?`, \u5B9E\u9645 tokens: ${_} ${k}`:"")+b}else if(a)p=String(o.phaseLabel??"\u538B\u7F29\u9636\u6BB5"),m=String(o.phaseDetail??"");else{const g=o.tokensBefore,f=o.tokensAfter,A=o.freedTokens,_=String(o.sizeBeforeKB??"?"),k=String(o.sizeAfterKB??"?"),b=String(o.freedKB??"?"),T=String(o.strategy??"?"),C=Number(o.prunedToolMessages??0),S=Number(o.summarizedMessages??0);p="\u538B\u7F29\u5B8C\u6210",g!==void 0&&f!==void 0?m=`\u91CA\u653E: ${A??g-f} tokens, ${g} tokens \u2192 ${f} tokens, \u7B56\u7565: ${T}`+(C?`, \u88C1\u526A\u5DE5\u5177: ${C}\u6761`:"")+(S?`, \u6458\u8981\u5316: ${S}\u6761`:""):m=`\u91CA\u653E: ${b}KB, ${_}KB \u2192 ${k}KB, \u7B56\u7565: ${T}`+(C?`, \u88C1\u526A\u5DE5\u5177: ${C}\u6761`:"")+(S?`, \u6458\u8981\u5316: ${S}\u6761`:"")}n&&(e.adapterSession.status="compacting");const d={actionType:"context_compaction",actionLabel:p,actionDetail:m};if(n&&c)d.actionId=c;else if((a||i)&&c)if(d.parentId=c,a){const g=String(o.phase??"unknown");d.actionId=`${c}-phase-${g}`}else d.actionId=`${c}-end`;a&&r&&!d.parentId&&(d.parentId=r),i&&(e.adapterSession.totalUsage.inputTokens=h(o.tokensAfter),e.adapterSession.totalUsage.outputTokens=0,d.usage={...e.adapterSession.totalUsage}),this.emitProviderEvent(t,"context_compaction",d),this.emit("status-change",t.sessionId,"compacting",d);return}this.emitProviderEvent(t,"thinking",{text:JSON.stringify(t.data)})}}emitProviderEvent(t,e,o){this.emit("event",{type:e,sessionId:t.sessionId,timestamp:t.timestamp,data:o})}armIdleLoopOrAutoPoll(t){const e=this.sessions.get(t);if(!(!e||this.isTerminalStatus(e.adapterSession.status))){if(e.idleCommands?.idleInputCommand){this.getIdlePollLoop(e).start();return}this.scheduleAutoPoll(t)}}getIdlePollLoop(t){if(t.idlePollLoop)return t.idlePollLoop;const e=t.adapterSession.sessionId;return t.idlePollLoop=new ut({getStatus:()=>this.sessions.get(e)?.adapterSession.status,getCommand:()=>this.sessions.get(e)?.idleCommands?.idleInputCommand,isPollingCommand:o=>L(o),preDispatchHook:()=>null,dispatchPollingPrompt:(o,s)=>this.submitAutoPollPrompt(e,s?o:Tt,{keepWaitingStatus:!0}),dispatchRegularIdleCommand:o=>this.submitAutoPollPrompt(e,o)}),t.idlePollLoop}submitAutoPollPrompt(t,e,o){const s=this.sessions.get(t);if(!s||this.isTerminalStatus(s.adapterSession.status))return;const n=(s.autoPollToken??0)+1;s.autoPollToken=n,s.autoPollActive=!0,s.autoPollObservedPollingTool=!1,s.autoPollObservedAssistantText=!1,s.autoPollObservedAnyTool=!1,s.stopAutoPollAfterCurrentTurn=!1,s.autoPollQueuedAt=Date.now(),s.autoPollLastActivityAt=Date.now(),s.idleToolActiveAt=void 0,o?.keepWaitingStatus||(s.adapterSession.status="thinking",this.emit("status-change",t,"thinking")),this.startSubmitTimeoutDetection(t,s,"submitAutoPollPrompt"),s.runtime.submit(e).catch(i=>{this.emitRuntimeError(t,i)}).finally(()=>{const i=this.sessions.get(t);if(i){if(i.autoPollToken!==n){l(`[ACode] submitAutoPollPrompt.finally: token mismatch (my=${n}, current=${i.autoPollToken}), skipping cleanup \u2014 newer turn has taken over`);return}if(this.cancelSubmitTimeoutDetection(i),i.autoPollActive=!1,i.failedTurnRecoveryScheduled||i.autoPollTimer){i.failedTurnRecoveryScheduled=!1;return}if(i.stopAutoPollAfterCurrentTurn){i.stopAutoPollAfterCurrentTurn=!1,i.autoPollObservedPollingTool=!1,i.autoPollObservedAssistantText=!1,i.autoPollObservedAnyTool=!1;return}if(i.adapterSession.status==="error"){this.recoverTurnFailure(t,i);return}if(i.adapterSession.status==="thinking"||i.adapterSession.status==="tool_using"){this.recoverResolvedTurnWithoutTerminalEvent(t);return}i.adapterSession.status==="waiting_input"&&this.armIdleLoopOrAutoPoll(t)}})}scheduleAutoPoll(t,e=ft){const o=this.sessions.get(t);!o||o.autoPollActive||o.autoPollTimer||this.isTerminalStatus(o.adapterSession.status)||(o.autoPollTimer=setTimeout(()=>{const s=this.sessions.get(t);!s||s.autoPollActive||this.isTerminalStatus(s.adapterSession.status)||(s.autoPollTimer=void 0,this.submitAutoPollPrompt(t,q,{keepWaitingStatus:!0}))},e))}cancelScheduledAutoPoll(t){t.autoPollTimer&&(clearTimeout(t.autoPollTimer),t.autoPollTimer=void 0)}isTerminalStatus(t){return t==="completed"||t==="terminated"}emitRuntimeError(t,e,o){const s=this.sessions.get(t);s&&(s.adapterSession.status="error",this.emitRuntimeErrorEvent(t,e),this.emit("status-change",t,"error"),o?.recover&&this.recoverTurnFailure(t,s))}emitRuntimeErrorEvent(t,e){const o=new Date().toISOString();this.emit("event",{type:"error",sessionId:t,timestamp:o,data:{text:e instanceof Error?e.message:String(e)}})}estimateOutputTokensFromMessages(t){const e=t.filter(o=>o.role==="assistant").map(o=>o.content).join("");return Math.max(0,Math.round(e.length/4))}recoverTurnFailure(t,e){if(this.isTerminalStatus(e.adapterSession.status))return;if(e.idleToolActiveAt=void 0,e.adapterSession.status==="tool_using"&&e.pendingToolEventData){const a=e.pendingToolEventData;l(`[ACode] recoverTurnFailure: \u8865\u53D1 tool_use_end (tool: ${a.toolName??"unknown"}) \u5173\u95ED\u65F6\u95F4\u7EBF\u6761\u76EE\uFF0C\u907F\u514D\u6C38\u4E45\u5361\u5728\u5DE5\u5177\u6267\u884C\u72B6\u6001`),this.emit("event",{type:"tool_use_end",sessionId:t,timestamp:new Date().toISOString(),data:{...a,toolResult:"[aborted] \u5DE5\u5177\u6267\u884C\u88AB\u6570\u636E\u6D41\u770B\u95E8\u72D7\u4E2D\u65AD"}}),e.pendingToolEventData=void 0}const o=this.estimateOutputTokensFromMessages(e.adapterSession.messages);if(o>0){const a=e.adapterSession.totalUsage.outputTokens;e.adapterSession.totalUsage.outputTokens=o,l(`[ACode] recoverTurnFailure: \u4F30\u7B97\u8986\u76D6 output tokens ${a} -> ${o} (totalUsage now: input=${e.adapterSession.totalUsage.inputTokens}, output=${e.adapterSession.totalUsage.outputTokens})`)}const s=e.idleCommands?.idleInputCommand,i=!!(s&&L(s))?{actionType:"idle",actionLabel:"\u76D1\u542C\u6D88\u606F",actionDetail:"aws-mcp/poll_message"}:void 0;if(e.autoPollTimer||e.failedTurnRecoveryScheduled){e.adapterSession.status!=="waiting_input"&&(e.adapterSession.status="waiting_input",this.emit("status-change",t,"waiting_input",{usage:e.adapterSession.totalUsage,...i}));return}this.cancelScheduledAutoPoll(e),e.adapterSession.status="waiting_input",this.emit("status-change",t,"waiting_input",{usage:e.adapterSession.totalUsage,...i}),e.failedTurnRecoveryScheduled=!0,e.autoPollTimer=setTimeout(()=>{const a=this.sessions.get(t);if(!a||a.autoPollActive||this.isTerminalStatus(a.adapterSession.status)){a&&(a.failedTurnRecoveryScheduled=!1);return}a.autoPollTimer=void 0,a.failedTurnRecoveryScheduled=!1,a.idleCommands?.idleInputCommand?this.getIdlePollLoop(a).start():this.submitAutoPollPrompt(t,q,{keepWaitingStatus:!0})},ht)}recoverResolvedTurnWithoutTerminalEvent(t){l(`[ACode] \u25B6\uFE0F recoverResolvedTurnWithoutTerminalEvent called for session ${t}`);const e=this.sessions.get(t);if(!e||this.isTerminalStatus(e.adapterSession.status)){l(`[ACode] Skipping recovery: entry=${!!e}, isTerminal=${e?this.isTerminalStatus(e.adapterSession.status):"N/A"}`);return}if(l(`[ACode] Current status: ${e.adapterSession.status}`),e.adapterSession.status!=="thinking"&&e.adapterSession.status!=="tool_using"){l(`[ACode] Skipping recovery: status is ${e.adapterSession.status} (not thinking/tool_using)`);return}console.warn(`[ACode] \u26A0\uFE0F Detected stuck state: ${e.adapterSession.status} after submit resolved! Recovering to waiting_input. If runtime.submit() is still pending (e.g., built-in tool execution not interruptible by abort()), the submitQueue is deadlocked and subsequent auto-poll/user submits will never execute.`),l("[ACode] Recovering to waiting_input..."),e.adapterSession.status="waiting_input";const o=e.idleCommands?.idleInputCommand,n=!!(o&&L(o))?{actionType:"idle",actionLabel:"\u76D1\u542C\u6D88\u606F",actionDetail:"aws-mcp/poll_message"}:void 0;this.emit("status-change",t,"waiting_input",n),l(`[ACode] \u2705 Recovery complete, status now: ${e.adapterSession.status}`),l("[ACode] \u25B6\uFE0F Arming idle loop or auto-poll..."),this.armIdleLoopOrAutoPoll(t),l("[ACode] \u2705 Idle loop armed, recovery process complete")}startSubmitTimeoutDetection(t,e,o){this.cancelSubmitTimeoutDetection(e),e.watchdogSubmitStartTime=Date.now(),e.watchdogLastDataFlowTime=Date.now(),e.watchdogTimer=setInterval(()=>{const s=this.sessions.get(t);if(!s){this.cancelSubmitTimeoutDetection(e);return}const n=s.adapterSession.status,i=Date.now();if(n==="waiting_input"){if(s.autoPollActive&&s.autoPollLastActivityAt&&s.idleToolActiveAt===void 0&&i-s.autoPollLastActivityAt>=gt){console.warn(`[ACode] CRITICAL: stuck auto-poll detected after ${Math.round((i-s.autoPollLastActivityAt)/1e3)}s (source: ${o}, session: ${t}): submit queued but no runtime events and no active poll_message tool. Forcing recovery (runtime force-settle will unblock submitQueue).`),this.executeWatchdogRecovery(t,s,o,"stuck_autopoll",i-s.autoPollLastActivityAt);return}s.watchdogSubmitStartTime=i,s.watchdogLastDataFlowTime=i;return}if(n==="tool_using"){const c=i-(s.watchdogLastDataFlowTime||i);if(c>=pt){const p=String(s.pendingToolEventData?.rawToolName??"");if(p.endsWith("await_complete")){console.warn(`[ACode] tool_using elapsed ${Math.round(c/1e3)}s but await_complete is running (session: ${t}, tool: ${p}), skipping recovery (sub-agents have their own watchdogs, bg commands have timeout limits)`),s.watchdogSubmitStartTime=i,s.watchdogLastDataFlowTime=i;return}if(console.warn(`[ACode] CRITICAL: tool_using slow timeout triggered after ${Math.round(c/1e3)}s (source: ${o}, session: ${t}). Tool execution likely hung. Forcing recovery via recoverTurnFailure.`),s.runtime.detachCurrentToolExecution?.()){console.warn(`[ACode] tool_using slow (${Math.round(c/1e3)}s): detached tool ${p} to background (session: ${t}); waiting for the real tool_result to continue the turn`),s.watchdogSubmitStartTime=i,s.watchdogLastDataFlowTime=i;return}this.executeWatchdogRecovery(t,s,o,"tool_using_slow",c);return}s.watchdogSubmitStartTime=i;return}if(n!=="thinking")return;const a=i-(s.watchdogSubmitStartTime||i),r=i-(s.watchdogLastDataFlowTime||i);if(N>0&&r>=N){console.warn(`[ACode] CRITICAL: Data flow watchdog triggered after ${Math.round(r/1e3)}s (source: ${o}, session: ${t}, status: ${n}). No stream data received. Forcing recovery via recoverTurnFailure.`),this.executeWatchdogRecovery(t,s,o,"data_flow",r);return}if(H>0&&a>=H){console.warn(`[ACode] CRITICAL: submit timeout detected after ${Math.round(a/1e3)}s (source: ${o}, session: ${t}, status: ${n}). Forcing recovery to prevent permanent state stuck.`),this.executeWatchdogRecovery(t,s,o,"submit_timeout",a);return}},mt)}executeWatchdogRecovery(t,e,o,s,n){l(`[ACode] Watchdog (${s}): calling runtime.abort() after ${Math.round(n/1e3)}s...`);try{e.runtime.abort(),l(`[ACode] Watchdog (${s}): runtime.abort() called`)}catch(i){console.warn(`[ACode] \u26A0\uFE0F Watchdog (${s}): runtime.abort() threw: ${i instanceof Error?i.message:String(i)}`)}this.cancelSubmitTimeoutDetection(e),this.recoverTurnFailure(t,e),console.warn(`[ACode] \u26A0\uFE0F Watchdog (${s}) recovery complete. If abort() could not cancel the underlying operation, submitQueue may still be deadlocked.`)}cancelSubmitTimeoutDetection(t){t.watchdogTimer&&(clearInterval(t.watchdogTimer),t.watchdogTimer=void 0),t.watchdogSubmitStartTime=void 0,t.watchdogLastDataFlowTime=void 0}resetDataFlowWatchdog(t,e){e.watchdogLastDataFlowTime=Date.now(),e.watchdogSubmitStartTime=Date.now()}startDataFlowWatchdog(t,e){e.watchdogLastDataFlowTime=Date.now()}cancelDataFlowWatchdog(t){t.watchdogLastDataFlowTime=Date.now()}formatAiRequestActionDetail(t){const e=`
|
|
2
2
|
|
|
3
3
|
\u8BF7\u6C42\u5934:
|
|
4
4
|
`,o=`
|
|
5
5
|
|
|
6
6
|
\u8BF7\u6C42\u4F53:
|
|
7
|
-
`,
|
|
8
|
-
`)||"ACode \u6B63\u5728\u53D1\u9001 AI \u8BF7\u6C42",k=
|
|
7
|
+
`,n=typeof t.model=="string"?t.model:"",i=typeof t.endpoint=="string"?t.endpoint:typeof t.requestUrl=="string"?t.requestUrl:"",a=typeof t.requestMethod=="string"?t.requestMethod:"",r=typeof t.stream=="boolean"?t.stream:void 0,c=typeof t.messageCount=="number"?t.messageCount:void 0,p=typeof t.toolCount=="number"?t.toolCount:void 0,m=typeof t.lastUserMessagePreview=="string"?t.lastUserMessagePreview:"",d=[n?`\u6A21\u578B: ${n}`:void 0,i?`\u63A5\u53E3: ${i}`:void 0,a?`\u65B9\u6CD5: ${a}`:void 0,r!==void 0?`\u6D41\u5F0F: ${r?"\u662F":"\u5426"}`:void 0,c!==void 0?`\u4E0A\u4E0B\u6587\u6D88\u606F: ${c}`:void 0,p!==void 0?`\u53EF\u7528\u5DE5\u5177: ${p}`:void 0,m?`\u6700\u540E\u8BF7\u6C42: ${m}`:void 0].filter(S=>!!S),g=/^(authorization|x-api-key|api-key|cookie|set-cookie|x-auth-token|token)$/i,f=t.requestHeaders,A=f?Object.entries(f).filter(([S])=>!g.test(S)).map(([S,M])=>`${S}: ${M}`).filter(S=>S.trim().length>0):[],_=d.join(`
|
|
8
|
+
`)||"ACode \u6B63\u5728\u53D1\u9001 AI \u8BF7\u6C42",k=A.length>0?`${e}${A.join(`
|
|
9
9
|
`)}`:"",b=typeof t.requestBody=="string"?t.requestBody:"",T=b.length>6e4?`${b.slice(0,6e4)}
|
|
10
|
-
...(\u8BF7\u6C42\u4F53\u8FC7\u957F\uFF0C\u5DF2\u622A\u65AD)`:b,C=T?`${o}${T}`:"";return`${
|
|
10
|
+
...(\u8BF7\u6C42\u4F53\u8FC7\u957F\uFF0C\u5DF2\u622A\u65AD)`:b,C=T?`${o}${T}`:"";return`${_}${k}${C}`}}export{Jt as AcodeSdkAdapter,wt as isFailedAcodeTurnComplete,At as toAcodeEsmImportSpecifier};
|
|
11
11
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{spawn as
|
|
1
|
+
import{spawn as A}from"node:child_process";import{EventEmitter as E}from"node:events";import*as w from"node:fs";import*as x from"node:net";import*as T from"node:os";import*as h from"node:path";import{v4 as y}from"uuid";import{BRIDGE_PACKAGE_ROOT as _,importBridgeSdkPackage as $}from"../utils/sdk-package-loader.js";import{getAcodeDataHome as M}from"../config.js";import{logger as L}from"../utils/logger.js";import{IdlePollLoop as O}from"./idle-poll-loop.js";import{getToolActionInfo as D,redactTransientClipboardPastePaths as P,redactTransientClipboardPastePathsInValue as C}from"./types.js";import{registerListenerWakeHook as j,unregisterListenerWakeHook as I}from"../services/browser-session-manager.js";function N(d){if(d&&h.isAbsolute(d)&&w.existsSync(d))return d;const t=d?.trim()||"opencode";if(process.platform==="win32"){const e=process.env.USERPROFILE||process.env.HOME||T.homedir(),o=process.env.LOCALAPPDATA||"",r=[h.join(o,"Volta","tools","shared","opencode-ai","node_modules","opencode-windows-x64","bin"),h.join(o,"Volta","tools","shared","opencode-ai","node_modules","opencode-windows-x64-baseline","bin")];for(const s of r){const n=h.join(s,"opencode.exe");if(w.existsSync(n))return console.log(`[OpencodeSdkAdapter] Found opencode.exe: ${n}`),n}const i=[h.join(e,"AppData","Roaming","npm"),h.join(e,"AppData","Local","Volta","bin")];for(const s of i)for(const n of["opencode.cmd","opencode.exe","opencode"]){const a=h.join(s,n);if(w.existsSync(a))return console.log(`[OpencodeSdkAdapter] Found ${n}: ${a}`),a}}return t}async function R(d=14096){for(let t=d;t<d+100;t++)if(await new Promise(o=>{const r=x.createServer();r.once("error",()=>o(!1)),r.once("listening",()=>{r.close(()=>o(!0))}),r.listen(t,"127.0.0.1")}))return t;throw new Error(`No available port found in range ${d}\u2013${d+99}`)}function U(d){return d instanceof Error&&"code"in d&&typeof d.code=="string"}function H(d,t){return U(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 Q extends E{constructor(){super(...arguments),this.providerId="opencode",this.displayName="OpenCode",this.sessions=new Map,this.listenerWakeHooks=new Map}async startSession(t,e){console.log(`[OpencodeSdkAdapter] \u2605\u2605\u2605 \u542F\u52A8 OpenCode SDK \u4F1A\u8BDD \u2605\u2605\u2605 sessionId="${t}", workingDirectory="${e.workingDirectory}"`);const o={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,o),e.agentId){const r=()=>{this.sessions.get(t)?.idlePollLoop?.start()};this.listenerWakeHooks.set(t,r),j(e.agentId,r)}this.emit("status-change",t,"starting");try{const r=await R();o.port=r,console.log(`[OpencodeSdkAdapter] \u2605\u2605\u2605 \u4F7F\u7528\u7AEF\u53E3 \u2605\u2605\u2605 port=${r}`);const i=N(e.command);console.log(`[OpencodeSdkAdapter] \u2605\u2605\u2605 \u542F\u52A8\u547D\u4EE4 \u2605\u2605\u2605 command="${i}"`);const s=i.endsWith(".cmd")||i.endsWith(".CMD")||process.platform==="win32"&&!h.isAbsolute(i);console.log(`[OpencodeSdkAdapter] shell=${s}`);const n={...process.env,...e.envOverrides},a={};v(e.model)?.modelID&&(a.model=e.model.trim()),e.systemPrompt&&typeof e.systemPrompt=="string"&&(a.systemPrompt=e.systemPrompt),Object.keys(a).length>0&&(n.OPENCODE_CONFIG_CONTENT=JSON.stringify(a),L.info(`[OpencodeSdkAdapter] OPENCODE_CONFIG_CONTENT keys=${Object.keys(a).join(",")}`));const l=A(i,["serve","--port",String(r)],{cwd:e.workingDirectory,stdio:["ignore","pipe","pipe"],env:n,shell:s});o.serverProcess=l,o.startupOutput=[],l.stdout?.on("data",c=>{const f=c.toString();this.recordStartupOutput(o,f),console.debug(`[OpencodeSdkAdapter] serve stdout: ${f.slice(0,200)}`)}),l.stderr?.on("data",c=>{const f=c.toString();this.recordStartupOutput(o,f),console.debug(`[OpencodeSdkAdapter] serve stderr: ${f.slice(0,200)}`)}),l.on("error",c=>{console.error("[OpencodeSdkAdapter] Server process error:",c),o.adapterSession.status!=="terminated"&&(o.adapterSession.status="error",this.emit("status-change",t,"error"),this.emitEvent({type:"error",sessionId:t,timestamp:new Date().toISOString(),data:{text:`OpenCode server error: ${c.message}`}}))}),l.on("exit",c=>{console.log(`[OpencodeSdkAdapter] Server exited with code ${c}`),o.sseActive=!1});const p=new Promise(c=>{l.once("exit",(f,b)=>c({code:f,signal:b}))}),g=(await this.loadSdk()).createOpencodeClient({baseUrl:`http://127.0.0.1:${r}`});o.client=g,await Promise.race([this.waitForServer(g,e.workingDirectory,1e4,r),p.then(c=>{throw new Error(this.formatStartupExitMessage(c,o.startupOutput))})]),console.log(`[OpencodeSdkAdapter] \u2605\u2605\u2605 OpenCode server ready \u2605\u2605\u2605 port=${r}`);const k=(await g.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");o.opencodeSessionId=k.id,o.adapterSession.providerSessionId=k.id,console.log(`[OpencodeSdkAdapter] \u2605\u2605\u2605 OpenCode \u4F1A\u8BDD\u521B\u5EFA\u6210\u529F \u2605\u2605\u2605 sessionId="${k.id}"`),this.startSseLoop(t,o),o.adapterSession.status="waiting_input",this.emit("status-change",t,"waiting_input",{usage:o.adapterSession.totalUsage}),e.initialPrompt&&this.dispatchInitialPrompt(t,e.initialPrompt)}catch(r){e.agentId&&I(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),o.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,o){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:y(),sessionId:t,role:"user",content:e,timestamp:new Date().toISOString()};r.adapterSession.messages.push(i),this.emit("conversation-message",t,i),o?.keepWaitingStatus||(r.adapterSession.status="thinking",this.emit("status-change",t,"thinking"),this.stopIdleDetection(t));try{const s=v(r.config.model),n={parts:[{type:"text",text:e}]};s?.providerID&&s?.modelID&&(n.model={providerID:s.providerID,modelID:s.modelID},console.log(`[OpencodeSdkAdapter] \u2605\u2605\u2605 per-message model \u2605\u2605\u2605 provider=${s.providerID}, model=${s.modelID}`)),await r.client.session.prompt({path:{id:r.opencodeSessionId},body:n,query:{directory:r.workingDirectory}})}catch(s){const n=s instanceof Error?s.message:String(s);this.emitEvent({type:"error",sessionId:t,timestamp:new Date().toISOString(),data:{text:n}})}}async sendConfirmation(t,e){const o=this.sessions.get(t);if(!o?.client||!o.opencodeSessionId)return;const r=e?"once":"reject",i=o.opencodeSessionId;for(const[s]of o.pendingPermissions)try{await o.client.postSessionIdPermissionsPermissionId({path:{id:i,permissionID:s},body:{response:r},query:{directory:o.workingDirectory}})}catch(n){console.warn("[OpencodeSdkAdapter] Permission response failed:",n)}o.pendingPermissions.clear()}async sendQuestionAnswer(t,e){}setIdleCommands(t,e){const o=this.sessions.get(t);o&&(o.idleCommands=e,o.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(o){console.warn("[OpencodeSdkAdapter] Abort failed:",o)}}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&&I(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 $("@opencode-ai/sdk")}catch(t){throw H(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 "${_}" @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
2
|
`)):t}return this.sdkModule}async waitForServer(t,e,o,r){const i=Date.now()+o;for(;Date.now()<i;){try{if((await t.session.list({query:{directory:e}})).data!==void 0)return}catch{}await new Promise(s=>setTimeout(s,300))}throw new Error(`OpenCode server (port ${r}) did not start within ${o}ms`)}recordStartupOutput(t,e){const o=e.trim();o&&(t.startupOutput=[...t.startupOutput??[],o].slice(-8))}formatStartupExitMessage(t,e){const o=t.signal?`signal ${t.signal}`:`code ${t.code??"unknown"}`,r=(e??[]).join(`
|
|
3
|
-
`).trim();return r?`OpenCode server exited during startup (${o}): ${r}`:`OpenCode server exited during startup (${o}). Please check whether opencode serve can run in this workspace.`}dispatchInitialPrompt(t,e){this.sendMessage(t,e).catch(o=>{const r=o instanceof Error?o.message:String(o);this.emitEvent({type:"error",sessionId:t,timestamp:new Date().toISOString(),data:{text:`OpenCode initial prompt failed: ${r}`}})})}startSseLoop(t,e){e.sseActive=!0;const o=new AbortController;e.sseAbortController=o,this.runSseLoop(t,e,o).catch(r=>{o.signal.aborted||console.error("[OpencodeSdkAdapter] SSE loop error:",r)})}async runSseLoop(t,e,o){if(e.client)try{const r=await e.client.event.subscribe({query:{directory:e.workingDirectory},signal:o.signal});for await(const i of r.stream){if(!e.sseActive||o.signal.aborted)break;this.handleOpenCodeEvent(t,e,i)}}catch(r){if(o.signal.aborted)return;console.error("[OpencodeSdkAdapter] SSE stream ended:",r)}}handleOpenCodeEvent(t,e,o){const r=new Date().toISOString(),i=e.opencodeSessionId;switch(o.type){case"message.updated":{const s=o.properties.info;if(s.sessionID!==i)break;if(s.role==="user")e.userMessageIds.add(s.id);else if(s.role==="assistant"){const n=s.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:s,delta:n}=o.properties;if(s.sessionID!==i||e.userMessageIds.has(s.messageID))break;this.handlePartUpdate(t,e,s,n,r);break}case"session.idle":{if(o.properties.sessionID!==i)break;if(e.currentAssistantText){const a={id:y(),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 s=e.idleCommands?.idleInputCommand;!!(s&&this.isMessagePollingIdleCommand(s))?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 s=o.properties;if(s.sessionID!==i)break;const n=s.id;e.pendingPermissions.set(n,s),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:s.title,toolName:s.type}});break}case"session.error":{const{sessionID:s,error:n}=o.properties;if(s&&s!==i)break;let a="OpenCode session error";if(n){const u=n.data;typeof u?.message=="string"?a=`${n.name}: ${u.message}`:a=n.name}this.emitEvent({type:"error",sessionId:t,timestamp:r,data:{text:a}});break}}}handlePartUpdate(t,e,o,r,i){switch(o.type){case"text":{let s;if(r!==void 0)s=r,e.seenTextPartIds.add(o.id);else if(!e.seenTextPartIds.has(o.id))s=o.text,s&&e.seenTextPartIds.add(o.id);else break;if(!s)break;e.currentAssistantText+=s,this.emitEvent({type:"text_delta",sessionId:t,timestamp:i,data:{text:s}});break}case"reasoning":{const s=r??o.text;if(!s)break;this.emitEvent({type:"thinking",sessionId:t,timestamp:i,data:{text:s}});break}case"tool":{const s=o.callID,n=o.tool,a=o.state,u=a.input,l=o.metadata;l&&Object.keys(l).length>0&&console.log(`[OpencodeSdkAdapter] Tool "${n}" metadata:`,JSON.stringify(
|
|
3
|
+
`).trim();return r?`OpenCode server exited during startup (${o}): ${r}`:`OpenCode server exited during startup (${o}). Please check whether opencode serve can run in this workspace.`}dispatchInitialPrompt(t,e){this.sendMessage(t,e).catch(o=>{const r=o instanceof Error?o.message:String(o);this.emitEvent({type:"error",sessionId:t,timestamp:new Date().toISOString(),data:{text:`OpenCode initial prompt failed: ${r}`}})})}startSseLoop(t,e){e.sseActive=!0;const o=new AbortController;e.sseAbortController=o,this.runSseLoop(t,e,o).catch(r=>{o.signal.aborted||console.error("[OpencodeSdkAdapter] SSE loop error:",r)})}async runSseLoop(t,e,o){if(e.client)try{const r=await e.client.event.subscribe({query:{directory:e.workingDirectory},signal:o.signal});for await(const i of r.stream){if(!e.sseActive||o.signal.aborted)break;this.handleOpenCodeEvent(t,e,i)}}catch(r){if(o.signal.aborted)return;console.error("[OpencodeSdkAdapter] SSE stream ended:",r)}}handleOpenCodeEvent(t,e,o){const r=new Date().toISOString(),i=e.opencodeSessionId;switch(o.type){case"message.updated":{const s=o.properties.info;if(s.sessionID!==i)break;if(s.role==="user")e.userMessageIds.add(s.id);else if(s.role==="assistant"){const n=s.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:s,delta:n}=o.properties;if(s.sessionID!==i||e.userMessageIds.has(s.messageID))break;this.handlePartUpdate(t,e,s,n,r);break}case"session.idle":{if(o.properties.sessionID!==i)break;if(e.currentAssistantText){const a={id:y(),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 s=e.idleCommands?.idleInputCommand;!!(s&&this.isMessagePollingIdleCommand(s))?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 s=o.properties;if(s.sessionID!==i)break;const n=s.id;e.pendingPermissions.set(n,s),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:s.title,toolName:s.type}});break}case"session.error":{const{sessionID:s,error:n}=o.properties;if(s&&s!==i)break;let a="OpenCode session error";if(n){const u=n.data;typeof u?.message=="string"?a=`${n.name}: ${u.message}`:a=n.name}this.emitEvent({type:"error",sessionId:t,timestamp:r,data:{text:a}});break}}}handlePartUpdate(t,e,o,r,i){switch(o.type){case"text":{let s;if(r!==void 0)s=r,e.seenTextPartIds.add(o.id);else if(!e.seenTextPartIds.has(o.id))s=o.text,s&&e.seenTextPartIds.add(o.id);else break;if(!s)break;e.currentAssistantText+=s,this.emitEvent({type:"text_delta",sessionId:t,timestamp:i,data:{text:s}});break}case"reasoning":{const s=r??o.text;if(!s)break;this.emitEvent({type:"thinking",sessionId:t,timestamp:i,data:{text:s}});break}case"tool":{const s=o.callID,n=o.tool,a=o.state,u=a.input,l=o.metadata;l&&Object.keys(l).length>0&&console.log(`[OpencodeSdkAdapter] Tool "${n}" metadata:`,JSON.stringify(C(l)));const p=C(u),S=p&&typeof p=="object"&&!Array.isArray(p)?p:{},g=()=>{if(e.emittedToolStarts.has(s))return;e.emittedToolStarts.add(s);const m={...D(n,u,l),actionId:s};this.emitEvent({type:"tool_use_start",sessionId:t,timestamp:i,data:{toolName:n,toolInput:S,toolUseId:s,...m}}),e.adapterSession.messages.push({id:y(),sessionId:t,role:"tool_use",content:`${n}: ${JSON.stringify(S).slice(0,100)}`,timestamp:i,toolName:n,toolInput:S,toolUseId:s})};if(a.status==="running"){g();const m={...D(n,u,l),actionId:s};this.emit("status-change",t,"tool_using",{...m,usage:e.adapterSession.totalUsage})}else if(a.status==="completed"){(n==="todowrite"||n==="todo_write")&&this.syncTodosFromToolCall(e,u).catch(k=>{console.warn("[OpencodeSdkAdapter] \u540C\u6B65 todo \u5230\u6587\u4EF6\u5931\u8D25:",k)}),g();const m=P(a.output);this.emitEvent({type:"tool_use_end",sessionId:t,timestamp:i,data:{toolName:n,toolResult:m,isError:!1,toolUseId:s}}),e.emittedToolStarts.delete(s)}else if(a.status==="error"){g();const m=P(a.error);this.emitEvent({type:"tool_use_end",sessionId:t,timestamp:i,data:{toolName:n,toolResult:m,isError:!0,toolUseId:s}}),e.emittedToolStarts.delete(s)}break}}}getTodoStoreDir(){return h.join(M(),"todos")}async syncTodosFromToolCall(t,e){const o=t.config.agentId;if(!o)return;const r=e.todos;if(!Array.isArray(r)||r.length===0)return;const i=[];for(const p of r)if(p&&typeof p=="object"){const S=typeof p.content=="string"?p.content.trim():"",g=typeof p.status=="string"?p.status:"",m=typeof p.priority=="string"?p.priority:"";S&&g&&m&&i.push({content:S,status:g,priority:m})}if(i.length===0)return;const s=String(o).replace(/[^a-zA-Z0-9_-]/g,"_"),n=this.getTodoStoreDir(),a=h.join(n,`${s}.json`),u={agentId:o,updatedAt:new Date().toISOString(),background:"OpenCode runtime todos",todos:i};await w.promises.mkdir(n,{recursive:!0});const l=`${a}.tmp`;await w.promises.writeFile(l,JSON.stringify(u,null,2),"utf-8"),await w.promises.rename(l,a)}emitEvent(t){this.emit("event",t)}startIdleDetection(t){this.stopIdleDetection(t);const e=this.sessions.get(t),o=e?.idleCommands?.idleInputCommand;if(!e||!o)return;if(this.isMessagePollingIdleCommand(o)){e.idlePollLoop||(e.idlePollLoop=new O({getStatus:()=>this.sessions.get(t)?.adapterSession.status,getCommand:()=>this.sessions.get(t)?.idleCommands?.idleInputCommand,isPollingCommand:i=>this.isMessagePollingIdleCommand(i),preDispatchHook:()=>null,dispatchPollingPrompt:(i,s)=>this.sendMessage(t,s?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 O({getStatus:()=>this.sessions.get(t)?.adapterSession.status,getCommand:()=>this.sessions.get(t)?.idleCommands?.idleInputCommand,isPollingCommand:i=>this.isMessagePollingIdleCommand(i),preDispatchHook:()=>null,dispatchPollingPrompt:(i,s)=>this.sendMessage(t,s?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)?"\u7CFB\u7EDF\u63D0\u9192\uFF1A\u5982\u679C\u4EFB\u52A1\u5DF2\u5B8C\u6210\u6216\u6CA1\u6709\u5176\u5B83\u8981\u505A\u7684\uFF0C\u5148\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":e}isMessagePollingIdleCommand(t){const e=t.trim();if(!e)return!1;const o=e.toLowerCase();return o.includes("poll_message")||o.includes("get_message")||e.includes("\u53D6\u6D88\u606F")}}export{Q as OpencodeSdkAdapter};
|
|
4
4
|
|
package/dist/adapter/types.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{EventEmitter as
|
|
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(a){return a.replace(y,m).replace(P,m).replace(w,m)}function $(a){const e=a.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(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",hire_colleagues_batch:"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 b=h[a];if(b)return{actionType:"mcp",actionLabel:"\u8C03\u7528MCP",actionDetail:`${b}/${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};
|
|
2
2
|
|
package/dist/config.d.ts
CHANGED
|
@@ -1,7 +1,27 @@
|
|
|
1
1
|
|
|
2
2
|
|
|
3
|
+
export declare function isDevMode(): boolean;
|
|
4
|
+
|
|
5
|
+
export declare function getUserHomeDir(): string;
|
|
6
|
+
|
|
7
|
+
export declare function getRuntimeHomeDir(): string;
|
|
8
|
+
|
|
9
|
+
export declare const DEFAULT_BRIDGE_PORT = 18081;
|
|
10
|
+
|
|
11
|
+
export declare const DEV_DEFAULT_BRIDGE_PORT = 28081;
|
|
12
|
+
|
|
3
13
|
export declare const port: number;
|
|
4
14
|
|
|
15
|
+
export declare function getActiveBridgeHttpPort(): number;
|
|
16
|
+
|
|
17
|
+
export declare function setActiveBridgeHttpPort(value: number): void;
|
|
18
|
+
|
|
19
|
+
export declare function resetActiveBridgeHttpPort(): void;
|
|
20
|
+
|
|
21
|
+
export declare function findAvailableListenPort(preferred: number, maxAttempts?: number): Promise<number>;
|
|
22
|
+
|
|
23
|
+
export declare function reserveBridgeListenPort(preferred?: number): Promise<number>;
|
|
24
|
+
|
|
5
25
|
export declare const DEFAULT_SCHEDULER_BASE_URL = "http://localhost:8080";
|
|
6
26
|
export type SchedulerBaseUrlSource = "request" | "instance-id-match" | "env" | "single-auto-register-target" | "default" | "ambiguous-auto-register-targets" | "token-match";
|
|
7
27
|
export interface SchedulerBaseUrlResolution {
|
|
@@ -14,6 +34,12 @@ export interface SchedulerBaseUrlResolution {
|
|
|
14
34
|
instanceName?: string;
|
|
15
35
|
}
|
|
16
36
|
|
|
37
|
+
export declare function getAutoRegisterConfigFilePath(): string;
|
|
38
|
+
|
|
39
|
+
export declare function getBridgeRuntimePropertiesFilePath(): string;
|
|
40
|
+
|
|
41
|
+
export declare function writeBridgeRuntimePropertiesFile(): void;
|
|
42
|
+
|
|
17
43
|
export declare function resolveSchedulerBaseUrl(): SchedulerBaseUrlResolution;
|
|
18
44
|
|
|
19
45
|
export declare function resolveSchedulerBaseUrlFrom(requestSchedulerBaseUrl: unknown, instanceId?: unknown, instanceName?: unknown): SchedulerBaseUrlResolution;
|
|
@@ -28,8 +54,6 @@ export declare const allowedCorsOrigins: string[];
|
|
|
28
54
|
|
|
29
55
|
export declare function validateProductionToken(): void;
|
|
30
56
|
|
|
31
|
-
export declare function getRuntimeHomeDir(): string;
|
|
32
|
-
|
|
33
57
|
export declare function getClaudeConfigFile(runtimeHome: string): string;
|
|
34
58
|
|
|
35
59
|
export declare function getClaudeMcpConfigFile(runtimeHome: string): string;
|
|
@@ -38,7 +62,9 @@ export declare function getClaudeSkillsDir(runtimeHome: string): string;
|
|
|
38
62
|
|
|
39
63
|
export declare function getOpencodeConfigFile(runtimeHome: string): string;
|
|
40
64
|
|
|
41
|
-
export declare function
|
|
65
|
+
export declare function getAcodeDataHome(): string;
|
|
66
|
+
|
|
67
|
+
export declare function getAcodeConfigFile(): string;
|
|
42
68
|
|
|
43
69
|
export declare function getCodexConfigFile(runtimeHome: string): string;
|
|
44
70
|
|
|
@@ -46,7 +72,7 @@ export declare function getCodexSkillsDir(runtimeHome: string): string;
|
|
|
46
72
|
|
|
47
73
|
export declare function getOpencodeSkillsDir(runtimeHome: string): string;
|
|
48
74
|
|
|
49
|
-
export declare function getAcodeSkillsDir(
|
|
75
|
+
export declare function getAcodeSkillsDir(): string;
|
|
50
76
|
|
|
51
77
|
|
|
52
78
|
export declare const ORPHAN_SCAN_INTERVAL: number;
|
package/dist/config.js
CHANGED
|
@@ -1,2 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import u from"node:fs";import D from"node:net";import{homedir as L}from"node:os";import o from"node:path";import{fileURLToPath as f}from"node:url";import{logger as C}from"./utils/logger.js";function m(){return String(process.env.AWS_RUNTIME_ENV||"").trim().toLowerCase()==="development"}let E;function P(){if(E!==void 0)return E;const e=o.dirname(f(import.meta.url)),t=o.resolve(e,".."),r=o.resolve(t,".."),n=u.existsSync(o.join(r,".git"))||u.existsSync(o.join(r,"package.json"));return E=o.join(n?r:t,".dev-home"),E}function T(){return String(process.env.AWS_TEST_HOME||"").trim()||String(process.env.AWS_RUNTIME_HOME_DIR||"").trim()||L()}function N(){return m()?String(process.env.AWS_TEST_HOME||"").trim()||String(process.env.AWS_RUNTIME_HOME_DIR||"").trim()||P():T()}const h=18081,H=28081,O=Number(process.env.AWS_RUNTIME_BRIDGE_PORT||(m()?H:h));let A;function M(){return A??O}function W(e){A=e}function z(){A=void 0}function I(e){return new Promise(t=>{const r=D.createServer();r.once("error",n=>{const s=n.code==="EADDRINUSE"||n.code==="EACCES"||n.code==="EPERM";t(!s)}),r.once("listening",()=>{r.close(()=>t(!0))}),r.listen(e)})}async function U(e){return await I({port:e})&&await I({port:e,host:"0.0.0.0"})?e:null}async function B(e,t=20){let r=Math.floor(e);for(let s=0;s<t;s+=1){if(r>=1&&r<=65535){const c=await U(r);if(c!==null)return c}r+=1}return await U(0)??e}async function J(e=O){const t=await B(e);return W(t),process.env.AWS_RUNTIME_BRIDGE_PORT=String(t),t!==e&&C.warn(`[runtime-bridge] \u9996\u9009\u7AEF\u53E3 ${e} \u5DF2\u88AB\u5360\u7528\uFF0C\u81EA\u52A8\u6539\u7528 ${t} \u542F\u52A8`),t}const S="http://localhost:8080";function R(e){return e==null?void 0:String(e).trim()||void 0}function _(e){const t=R(e);if(!t)return;const r=t.replace(/^((?:https?|wss?):\/\/(?:\[[^\]]+\]|[^/:?#]+):\d+):\d+(?=\/|$)/i,"$1");try{const n=new URL(r);return n.protocol==="ws:"?n.protocol="http:":n.protocol==="wss:"?n.protocol="https:":n.protocol=n.protocol.toLowerCase(),n.hostname=n.hostname.toLowerCase(),n.origin}catch{return r.replace(/\/+$/,"")}}function w(){return o.join(N(),".aws-bridge","config.json")}function F(){return o.join(N(),".aws-bridge","bridge-runtime.properties")}function Y(){const e=F();u.mkdirSync(o.dirname(e),{recursive:!0});const t=[`port=${M()}`,`pid=${process.pid}`,`startedAt=${new Date().toISOString()}`];u.writeFileSync(e,`${t.join(`
|
|
2
|
+
`)}
|
|
3
|
+
`,{encoding:"utf8",mode:384})}function v(){const e=w();try{if(!u.existsSync(e))return[];const t=JSON.parse(u.readFileSync(e,"utf-8")),r=i=>({serverUrl:_(i.serverUrl)||_(i.schedulerBaseUrl),instanceId:R(i.instanceId),instanceName:R(i.instanceName)}),s=(Array.isArray(t.autoRegisterTargets)?t.autoRegisterTargets:[]).filter(i=>!!(i&&typeof i=="object"&&!Array.isArray(i))).map(r).filter(i=>!!i.serverUrl);if(s.length>0)return s;const c=r(t);return c.serverUrl?[c]:[]}catch{return[]}}function j(){const t=v().map(r=>r.serverUrl).filter(r=>!!r);return Array.from(new Set(t))}function q(){return k(void 0)}function k(e,t,r){const n=_(e);if(n)return{url:n,source:"request",ambiguousTargetUrls:[]};const s=typeof t=="string"?t.trim():"",c=typeof r=="string"?r.trim():"";if(s||c){const g=v();let a;if(s&&(a=g.find(p=>p.instanceId===s)),!a&&c&&(a=g.find(p=>p.instanceName===c)),!a&&s&&!c&&(a=g.find(p=>p.instanceName===s)),a?.serverUrl)return{url:a.serverUrl,source:"instance-id-match",ambiguousTargetUrls:[],instanceId:a.instanceId,instanceName:a.instanceName}}const i=_(process.env.AWS_RUNTIME_SCHEDULER_BASE_URL);if(i)return{url:i,source:"env",ambiguousTargetUrls:[]};const l=j();return l.length===1?{url:l[0]||S,source:"single-auto-register-target",ambiguousTargetUrls:[]}:l.length>1?{url:S,source:"ambiguous-auto-register-targets",ambiguousTargetUrls:l}:{url:S,source:"default",ambiguousTargetUrls:[]}}const X=_(process.env.AWS_RUNTIME_SCHEDULER_BASE_URL)||S,Q=process.env.NODE_ENV||"development",Z=process.env.AWS_ALLOW_HOST_FILE_BROWSER==="true",ee=String(process.env.AWS_RUNTIME_CORS_ORIGINS||"http://localhost:3000,http://127.0.0.1:3000,http://localhost:5173,http://127.0.0.1:5173").split(",").map(e=>e.trim()).filter(e=>e.length>0);function te(){}function re(e){return String(process.env.AWS_RUNTIME_CLAUDE_CONFIG_FILE||"").trim()||o.join(e,".claude","settings.json")}function ne(e){return String(process.env.AWS_RUNTIME_CLAUDE_MCP_CONFIG_FILE||"").trim()||o.join(e,".claude.json")}function oe(e){return String(process.env.AWS_RUNTIME_CLAUDE_SKILLS_DIR||"").trim()||o.join(e,".claude","skills")}function se(e){return String(process.env.AWS_RUNTIME_OPENCODE_CONFIG_FILE||"").trim()||o.join(e,".config","opencode","opencode.json")}function x(){return String(process.env.ACODE_HOME||"").trim()||o.join(T(),".acode")}function ie(){return String(process.env.AWS_RUNTIME_ACODE_CONFIG_FILE||"").trim()||o.join(x(),"config.json")}function ce(e){return String(process.env.AWS_RUNTIME_CODEX_CONFIG_FILE||"").trim()||o.join(e,".codex","config.toml")}function ae(e){return String(process.env.AWS_RUNTIME_CODEX_SKILLS_DIR||"").trim()||o.join(e,".codex","skills")}function ue(e){return String(process.env.AWS_RUNTIME_OPENCODE_SKILLS_DIR||"").trim()||o.join(e,".opencode","skills")}function le(){return String(process.env.AWS_RUNTIME_ACODE_SKILLS_DIR||"").trim()||o.join(x(),"skills")}const pe=Number(process.env.AWS_ORPHAN_SCAN_INTERVAL||3e4),_e=process.env.AWS_ORPHAN_AUTO_CLEAN_MODE||"alert",Ee=process.env.AWS_ORPHAN_SCAN_ENABLED!=="false",Se=Number(process.env.AWS_ORPHAN_UNRESPONSIVE_TIMEOUT||3e5),ge=Number(process.env.AWS_ORPHAN_CPU_THRESHOLD||100),Ae=Number(process.env.AWS_ORPHAN_MEMORY_THRESHOLD||2048),Re=process.env.AWS_AUTO_REGISTER==="true",de=process.env.AWS_TENANT_ID||"",fe=process.env.AWS_USER_KEY||"",me=process.env.AWS_INSTANCE_NAME||"",Te=process.env.AWS_PROJECT_NAME||"",Ne=process.env.AWS_ROLE_NAME||"",Oe=process.env.AWS_WORKSPACE_PATH||"",Ie=process.env.AWS_REGISTER_IP||process.env.AWS_VIRTUAL_IP||"";let d;function Ue(){if(d!==void 0)return d;let e="unknown";try{const t=o.dirname(f(import.meta.url)),r=o.resolve(t,"..","package.json");u.existsSync(r)&&(e=JSON.parse(u.readFileSync(r,"utf-8")).version||"unknown")}catch{}return d=e,e}export{Re as AUTO_REGISTER_ENABLED,me as AUTO_REGISTER_INSTANCE_NAME,Te as AUTO_REGISTER_PROJECT_NAME,Ne as AUTO_REGISTER_ROLE_NAME,de as AUTO_REGISTER_TENANT_ID,fe as AUTO_REGISTER_USER_KEY,Ie as AUTO_REGISTER_VIRTUAL_IP,Oe as AUTO_REGISTER_WORKSPACE_PATH,h as DEFAULT_BRIDGE_PORT,S as DEFAULT_SCHEDULER_BASE_URL,H as DEV_DEFAULT_BRIDGE_PORT,_e as ORPHAN_AUTO_CLEAN_MODE,ge as ORPHAN_CPU_THRESHOLD,Ae as ORPHAN_MEMORY_THRESHOLD,Ee as ORPHAN_SCAN_ENABLED,pe as ORPHAN_SCAN_INTERVAL,Se as ORPHAN_UNRESPONSIVE_TIMEOUT,Z as allowHostFileBrowser,ee as allowedCorsOrigins,B as findAvailableListenPort,ie as getAcodeConfigFile,x as getAcodeDataHome,le as getAcodeSkillsDir,M as getActiveBridgeHttpPort,w as getAutoRegisterConfigFilePath,F as getBridgeRuntimePropertiesFilePath,Ue as getBridgeVersion,re as getClaudeConfigFile,ne as getClaudeMcpConfigFile,oe as getClaudeSkillsDir,ce as getCodexConfigFile,ae as getCodexSkillsDir,se as getOpencodeConfigFile,ue as getOpencodeSkillsDir,N as getRuntimeHomeDir,T as getUserHomeDir,m as isDevMode,Q as nodeEnv,O as port,J as reserveBridgeListenPort,z as resetActiveBridgeHttpPort,q as resolveSchedulerBaseUrl,k as resolveSchedulerBaseUrlFrom,X as schedulerBaseUrl,W as setActiveBridgeHttpPort,te as validateProductionToken,Y as writeBridgeRuntimePropertiesFile};
|
|
2
4
|
|