aws-runtime-bridge 1.9.170 → 1.9.172
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +83 -0
- package/dist/adapter/AcodeSdkAdapter.d.ts +6 -12
- package/dist/adapter/AcodeSdkAdapter.js +3 -3
- package/dist/adapter/ClaudeSdkAdapter.d.ts +2 -0
- package/dist/adapter/ClaudeSdkAdapter.js +3 -3
- package/dist/adapter/types.d.ts +4 -7
- package/dist/index.js +1 -1
- package/dist/routes/terminal.d.ts +8 -0
- package/dist/routes/terminal.js +27 -33
- package/dist/services/agent-startup-memory.d.ts +11 -0
- package/dist/services/agent-startup-memory.js +8 -0
- package/dist/services/log-retention.d.ts +37 -0
- package/dist/services/log-retention.js +2 -0
- package/dist/services/request-invalid-dump.d.ts +21 -0
- package/dist/services/request-invalid-dump.js +2 -0
- package/dist/services/session-output.d.ts +2 -0
- package/dist/services/session-output.js +2 -2
- package/dist/utils/lifecycle-log.d.ts +2 -0
- package/dist/utils/lifecycle-log.js +2 -2
- package/package/acode/dist/ask-user-question-tool.d.ts +11 -1
- package/package/acode/dist/ask-user-question-tool.js +3 -3
- package/package/acode/dist/built-in-file-tools.js +2 -2
- package/package/acode/dist/compaction.d.ts +143 -31
- package/package/acode/dist/compaction.js +20 -6
- package/package/acode/dist/image-utils.js +1 -1
- package/package/acode/dist/runtime-environment.js +1 -1
- package/package/acode/dist/runtime.d.ts +13 -4
- package/package/acode/dist/runtime.js +31 -28
- package/package/acode/dist/types.d.ts +1 -1
- package/package/aws-client-agent-mcp/dist/agent-client.d.ts +2 -0
- package/package/aws-client-agent-mcp/dist/agent-client.js +1 -1
- package/package/aws-client-agent-mcp/dist/mcp-server.js +1 -1
- package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts +4 -0
- package/package/aws-client-agent-mcp/dist/mcp-tools.js +32 -18
- package/package/aws-client-agent-mcp/dist/status-reporter.js +1 -1
- package/package/aws-client-agent-mcp/dist/tool-groups.js +2 -2
- package/package/aws-client-agent-mcp/dist/types.d.ts +15 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,89 @@ files 白名单),供调度中心「查看本次更新内容」弹窗按 `##
|
|
|
5
5
|
展示。发布新版本时须在仓库中先写好 `## v<version>` 段(prepack-guard 校验缺段
|
|
6
6
|
即阻断发布);Bridge 自更新成功后的运行时追加仅作为包内缺段时的兜底。
|
|
7
7
|
|
|
8
|
+
## v1.9.172
|
|
9
|
+
|
|
10
|
+
_发布日期:2026-10-21_
|
|
11
|
+
|
|
12
|
+
### 上下文压缩重构、提问取消作答与消息中心体验收敛
|
|
13
|
+
|
|
14
|
+
- ACode 上下文压缩改为「高保真级联」统一策略(完整摘要 → 降级 → 截断),不再由
|
|
15
|
+
前端勾选压缩类别;移除 `compaction-preview` 与「先行压缩」配置弹窗,输入区入口
|
|
16
|
+
直接启用开关,压缩范围由运行时决定。
|
|
17
|
+
- 压缩摘要改为流式上报:runtime 逐 chunk 发射 `compaction_summary`,bridge 按
|
|
18
|
+
120 字符 / 120ms 积攒后推送,时间线实时滚动展示;摘要正文不落库(bridge 本地
|
|
19
|
+
环 Buffer、per-agent 事件存储、Java 事件表与运行日志全部跳过),刷新后不复活。
|
|
20
|
+
- 修复压缩摘要与思考卡片互相打断、摘要尾部落到压缩结束事件之后、长摘要不跟随
|
|
21
|
+
滚动的问题;压缩摘要使用独立琥珀色卡片样式。
|
|
22
|
+
- 修复 token 用量显示:启动/恢复/压缩后的估算值与 provider 真实值用
|
|
23
|
+
`usageEstimated` 显式区分,真实 usage 变小时不再被 20% 启发式误判为 fallback;
|
|
24
|
+
provider 未上报 input tokens 时不再把上下文清零。
|
|
25
|
+
- 修复时间线重复卡片:`iteration_usage` 等 usage-only 状态变更不再重放上一次
|
|
26
|
+
`ai_request` 动作;工具结果先于调用到达时不再覆盖已完成的同名工具卡片。
|
|
27
|
+
- 支持「取消作答」:提问卡片新增取消入口与可选原因,Java / bridge / ACODE runtime
|
|
28
|
+
全链路解除 Agent 阻塞并把取消结果回传模型;回答与取消共用幂等与回执持久化,
|
|
29
|
+
刷新后展示「已取消」只读态。
|
|
30
|
+
- `read_file` 图片 URL 读取:以魔数为权威格式判据(签名 URL 的
|
|
31
|
+
`application/octet-stream` 不再被误拒),发送最小浏览器请求头规避图床 403/406,
|
|
32
|
+
URL 只保留 origin+path 写调试日志;运行时提示明确「URL 直接读,不要先 curl 落盘」。
|
|
33
|
+
- dashboard:消息通知弹层新增提示音开关(Web Audio 合成、首次手势解锁、静音持久化);
|
|
34
|
+
桌面通知权限入口移至消息通知弹层;移动端弹框最小化新增「飞向收纳按钮」动画;
|
|
35
|
+
普通终端打开期间按钮转圈防重复点击;长文本粘贴统一转为 txt 附件;文件引用图标与
|
|
36
|
+
工作区文件树同源;引用图标视觉修正。
|
|
37
|
+
- 邮件:新增 `imapInternalHost` / `smtpInternalHost` 等后端内网连接地址(留空回退
|
|
38
|
+
客户端展示地址),配置自检展示实际生效地址;compose 为 James 增加
|
|
39
|
+
`mail.<mailDomain>` 网络别名,避免容器经公网/NAT 回环;邮箱别名改用 James
|
|
40
|
+
typed alias 路由 `/address/aliases/{目标}/sources/{别名}`,修复旧路由稳定 404。
|
|
41
|
+
- 消息协作:`send_dm` 的 `replyToCallId` 未命中调用式消息时降级为普通私信并回传
|
|
42
|
+
warning(不再静默丢内容);自动关联 pending call 失败时同样降级发送。
|
|
43
|
+
- 修复 `sendOutput` 在 `skipLocalPersist` 路径于 `finally` 中 `return` 吞掉异常,
|
|
44
|
+
导致上层重试队列收不到失败信号的问题。
|
|
45
|
+
- 内置 `db_connect_client_mcp` 源码随仓库提交(能力市场包仍以 esbuild 单文件
|
|
46
|
+
bundle 发布)。
|
|
47
|
+
|
|
48
|
+
> **验证**:bridge `npm run typecheck`、`npm test`(121 files、1747 passed、
|
|
49
|
+
> 2 skipped)与 `package/acode`(827 passed)、`package/aws-client-agent-mcp`
|
|
50
|
+
> (561 passed)测试通过;Java `mvn test`(2057 passed)通过;dashboard
|
|
51
|
+
> `npm run lint`、`npm run type-check` 与全部 `test:*` 脚本通过。
|
|
52
|
+
|
|
53
|
+
## v1.9.171
|
|
54
|
+
|
|
55
|
+
_发布日期:2026-10-20_
|
|
56
|
+
|
|
57
|
+
### 消息协作、邮箱别名、同事观察与日志治理
|
|
58
|
+
|
|
59
|
+
- 消息中心:发送改为乐观上屏(本地「发送中」→ 服务端 `sent`),网络/5xx/429
|
|
60
|
+
自动退避重试 3 次,失败气泡保留并支持「重试 / 编辑」;WS 回显按发送者+正文+
|
|
61
|
+
时间窗认领本地待发气泡;私信/群聊发送携带客户端幂等键,服务端按
|
|
62
|
+
`(sender, clientMessageId)` 去重,HTTP 响应丢失后的自动重试不会产生重复消息。
|
|
63
|
+
- 群聊支持 @所有人(后端展开为房间/项目实际成员,提及记录与未读口径一致)、
|
|
64
|
+
结构化引用提醒(回表校验被引用消息作者,拒绝客户端伪造 `senderId`),并补充
|
|
65
|
+
引用提醒系统通知。
|
|
66
|
+
- 新增角色实例邮箱「人类只读查看」(收件箱 / 已发送 / 详情,不改变 IMAP 已读
|
|
67
|
+
状态)与邮箱别名设置;别名更新改为「先建新远端映射、再删旧映射」,任一步失败
|
|
68
|
+
不会让旧别名提前失效,失败时补偿恢复远端状态。
|
|
69
|
+
- 同事协作:`get_colleague` 增加在线状态、当前动作、工作区路径与邮箱概要;
|
|
70
|
+
新增 `list_colleague_events` 分页查看同事行为时间线(摘要视图,剥离工具输入/
|
|
71
|
+
结果原文),由 `collaboration.agentObserve` 能力开关控制(默认收纳)。
|
|
72
|
+
- ACode 收口:AI 配置 / MCP 模板 / 终端 CLI 仅保留 ACode,移除 ClaudeCode、
|
|
73
|
+
Codex、OpenCode 的配置入口与文案。
|
|
74
|
+
- 修复:`RuntimeBridgeService` / `RuntimeGlobalSettingsService` 保存 MCP 时补回
|
|
75
|
+
`instantiate` / `packageUrl` / `packageSha256` 字段,避免包型 MCP 初始化丢失。
|
|
76
|
+
- 修复:清空角色实例邮箱别名改为显式 `SET address_alias = NULL`(MyBatis-Plus
|
|
77
|
+
`updateById` 会忽略 null 字段);恢复心跳超时后的 Agent 异常离线告警。
|
|
78
|
+
- bridge 日志治理:新增统一日志保留策略(lifecycle、MCP 子进程、AI 配置调试
|
|
79
|
+
日志,最长保留 7 天),启动即清理 + 每 6h 周期清理,面板下发值夹取到 1..7 天;
|
|
80
|
+
Java Debug 日志清理同步收敛为最长 7 天。
|
|
81
|
+
- bridge 启动记忆加载抽为独立服务并复用;provider 请求体非法(确定性 4xx)时
|
|
82
|
+
落盘完整对话上下文快照(去重 + 保留最近 20 份),便于事后复现工具调用配对问题。
|
|
83
|
+
- dashboard 接入标签页未读标题 / PWA 应用角标;页面隐藏时按私信、群聊 @、系统
|
|
84
|
+
通知弹桌面通知(同会话 4s 合并、点击跳转会话),权限申请放在个人菜单。
|
|
85
|
+
|
|
86
|
+
> **验证**:bridge `npm run typecheck` 与 `npm test` 通过
|
|
87
|
+
> (120 files、1724 passed、2 skipped);Java `mvn -q test` 通过;
|
|
88
|
+
> dashboard `npm run lint`、`npm run type-check` 与 99 个 `test:*` 脚本
|
|
89
|
+
> 全部通过。
|
|
90
|
+
|
|
8
91
|
## v1.9.170
|
|
9
92
|
|
|
10
93
|
_发布日期:2026-10-17_
|
|
@@ -18,12 +18,7 @@ type ACodeRuntimeInstance = {
|
|
|
18
18
|
abort(): Promise<void>;
|
|
19
19
|
resetContext?(): Promise<void>;
|
|
20
20
|
|
|
21
|
-
compactContext?(
|
|
22
|
-
pruneCategories?: string[];
|
|
23
|
-
summarize?: boolean;
|
|
24
|
-
}): unknown;
|
|
25
|
-
|
|
26
|
-
getCompactionPreview?(): unknown;
|
|
21
|
+
compactContext?(): unknown;
|
|
27
22
|
stop(): Promise<void>;
|
|
28
23
|
|
|
29
24
|
exportConversation?(): unknown[];
|
|
@@ -32,6 +27,8 @@ type ACodeRuntimeInstance = {
|
|
|
32
27
|
|
|
33
28
|
submitQuestionAnswer?(toolCallId: string, answers: Record<string, string>): boolean;
|
|
34
29
|
|
|
30
|
+
cancelQuestionAnswer?(toolCallId: string, reason?: string): boolean;
|
|
31
|
+
|
|
35
32
|
detachCurrentToolExecution?(): boolean;
|
|
36
33
|
|
|
37
34
|
hasActiveBlockingToolCall?(): boolean;
|
|
@@ -154,15 +151,12 @@ export declare class AcodeSdkAdapter extends EventEmitter implements BaseProvide
|
|
|
154
151
|
}>;
|
|
155
152
|
|
|
156
153
|
sendQuestionAnswer(sessionId: string, answers: Record<string, string>): Promise<void>;
|
|
154
|
+
|
|
155
|
+
cancelQuestionAnswer(sessionId: string, reason?: string): Promise<void>;
|
|
157
156
|
abortCurrentTurn(sessionId: string): Promise<void>;
|
|
158
157
|
resetContext(sessionId: string): Promise<void>;
|
|
159
158
|
|
|
160
|
-
compactContext(sessionId: string
|
|
161
|
-
pruneCategories?: string[];
|
|
162
|
-
summarize?: boolean;
|
|
163
|
-
}): unknown;
|
|
164
|
-
|
|
165
|
-
getCompactionPreview(sessionId: string): unknown;
|
|
159
|
+
compactContext(sessionId: string): unknown;
|
|
166
160
|
terminateSession(sessionId: string): Promise<void>;
|
|
167
161
|
getConversation(sessionId: string): ConversationMessage[];
|
|
168
162
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import{EventEmitter as nt}from"node:events";import rt from"node:fs/promises";import H from"node:path";import{pathToFileURL as lt}from"node:url";import{isMcpGroupKey as ut}from"@agentswork/acode";import{v4 as x}from"uuid";import{getBridgeInstancePluginsDir as dt,getBridgeInstanceSkillsDir as ct,getBridgeTemplateConfigFile as v,getBridgeTemplateSkillsDir as pt}from"../config.js";import{getReleasedAcodeEntryPath as mt}from"../services/acode-package.js";import{syncAgentSkillFarm as K}from"../services/agent-capability-sync.js";import{agentPtyManager as ft}from"../services/agent-pty-manager.js";import{getBrowserTools as R,closeBrowserSession as gt,registerListenerWakeHook as ht,unregisterListenerWakeHook as j}from"../services/browser-session-manager.js";import{getDesktopTools as M,getDesktopToolsIfReady as Tt}from"../services/desktop-mcp-manager.js";import{redactForLog as G}from"../services/instance-ai-config-service.js";import{BROWSER_FEATURE_KEY as L,DESKTOP_FEATURE_KEY as P,getAgentToolPermissions as At,getFeatureState as U,isFeatureEnabled as yt,resolveAgentToolPermissions as St,resolveGroupFeatureKey as bt}from"../services/instance-features.js";import{pluginManager as O}from"../services/plugin-manager.js";import{buildRuntimeResourcesSnapshot as _t}from"../services/runtime-resources-snapshot.js";import{subAgentManager as Ct}from"../services/sub-agent-manager-instance.js";import{recordAgentFileChange as kt}from"../services/workspaceTaskChangeWatcher.js";import{getInstanceAiConfigDebugLogger as F}from"../utils/instance-ai-config-debug-logger.js";import{recordLifecycleEvent as k}from"../utils/lifecycle-log.js";import{isMessagePollingIdleCommand as q,isPollMessageToolDescriptor as wt}from"./acode-tool-names.js";import{IdlePollLoop as Pt}from"./idle-poll-loop.js";import{resolveAcodeProviderConfig as $t}from"./instance-ai-config-resolver.js";import{MESSAGE_POLLING_IDLE_PROMPT as z}from"./prompts.js";import{getCanonicalMcpDetail as J,getToolActionInfo as Et}from"./types.js";const xt=process.env.ACODE_COMPACTION_DEBUG==="1";function r(...u){xt&&console.log(...u)}const Lt=process.env.ACODE_TOKEN_DEBUG==="1";function w(...u){Lt&&console.log("[TokenDebug][Adapter]",...u)}const It=z,Dt=5e3;function $(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 Q=$("ACODE_DATA_FLOW_WATCHDOG_MS",12e4),Mt=5*6e4,Ot=$("ACODE_STUCK_AUTOPOLL_TIMEOUT_MS",5*6e4),Y=$("ACODE_LIVENESS_POLL_INTERVAL_MS",15e3),B=$("ACODE_LIVENESS_STALL_TIMEOUT_MS",10*6e4),vt=250,Rt=1e3,Ut=$("ACODE_DEFERRED_IDLE_REARM_MS",3e3),V=[2e3,3e3,1e4,4e4],X=4e3;function Z(u){const t=String(u||"").trim();if(t)return t.length>X?`${t.slice(0,X)}\u2026(truncated)`:t}function Ft(u){const t=u.toLowerCase();return/tool[_ ]?call/.test(t)||t.includes("invalid_request")?!0:/(?:failed:\s*|http[\s/]*|status[\s:="']*|code[\s:="']*)(400|401|403|404|422)(?!\d)/.test(t)}const N={[L]:"browser_",[P]:"desktop_"};function qt(u){if(!u||typeof u!="object")return;const t=u,e=typeof t.exposedName=="string"&&t.exposedName||typeof t.toolName=="string"&&t.toolName||typeof t.name=="string"&&t.name||"";if(!e)return;const o=typeof t.execute=="function"?t.execute:void 0;return{name:e,...typeof t.description=="string"?{description:t.description}:{},...t.inputSchema!==void 0?{inputSchema:t.inputSchema}:{},definition:t,...o?{execute:o}:{}}}const tt=$("ACODE_SUBMIT_TIMEOUT_MS",12e4),et=3e3,Bt=z;function Nt(){return H.resolve(mt())}function Wt(u){return lt(H.resolve(u)).href}const ot=128e3,E={"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 Ht(u){if(!u)return ot;const t=u.toLowerCase().trim(),e=E[t];if(e)return e.contextLimit;const o=Object.keys(E).filter(a=>t.startsWith(a)).sort((a,i)=>i.length-a.length),s=o[0]!==void 0?E[o[0]]:void 0;return s?s.contextLimit:ot}const st=4096;function Kt(u){if(!u)return st;const t=u.toLowerCase().trim(),e=E[t];if(e)return e.maxOutput;const o=Object.keys(E).filter(a=>t.startsWith(a)).sort((a,i)=>i.length-a.length),s=o[0]!==void 0?E[o[0]]:void 0;return s?s.maxOutput:st}function it(u){if(!u||typeof u!="object")return;const t=u,e=y(t.inputTokens,t.input_tokens,t.promptTokens,t.prompt_tokens),o=y(t.outputTokens,t.output_tokens,t.completionTokens,t.completion_tokens);if(e===0&&o===0)return;let s=y(t.cacheHitTokens,t.promptCacheHitTokens,t.prompt_cache_hit_tokens),a=y(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=y(t.cache_read_input_tokens),d=y(t.cache_creation_input_tokens);if(n>0||d>0){const m=t.input_tokens!==void 0&&Number.isFinite(Number(t.input_tokens))&&Number(t.input_tokens)>=0?y(t.input_tokens):Math.max(0,e-n-d);s=n,a=d+m,i=!0}else s=y(t.cache_hit_tokens),a=y(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=y(t.prompt_tokens_details?.cached_tokens);n>0&&(s=n,a=e>n?e-n:0,i=!0)}return{inputTokens:e,outputTokens:o,...i?{cacheHitTokens:s,cacheMissTokens:a}:{},...i?{hasCache:!0}:{}}}function y(...u){for(const t of u){const e=Number(t);if(Number.isFinite(e)&&e>0)return e}return 0}function jt(u){return u==="stderr"||u==="mixed"?u:"stdout"}function I(u){const t=Number(u);return Number.isFinite(t)?t:0}function W(u){if(u==null)return;const t=Number(u);return Number.isFinite(t)?t:void 0}function Gt(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 zt(u){return u.failed===!0}function at(u,t,e){if(!u)return e?`${t}/${e}`:t;const o=`${t}__`;return u.startsWith(o)?J(`${t}__${u.slice(o.length)}`):J(u.replace("/","__"))}function Jt(u){return u==="read_file"||u==="edit_file"||u==="write_file"||u==="bash"}function Qt(u){const t=Yt(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 Yt(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 Ce extends nt{constructor(){super(),this.providerId="acode",this.displayName="ACode",this.sessions=new Map,this.expandedBuiltInCapabilities=new Map,this.builtInCapabilityToolCache=new Map,this.listenerWakeHooks=new Map,O.setOnPluginsChanged(t=>{this.syncPluginCommands(t)})}async syncPluginCommands(t){try{const e=await O.getPluginCommands(t);for(const o of this.sessions.values())o.config.agentId===t&&(o.runtime.addPluginCommands?.(e),o.runtime.syncPluginGroups?.())}catch(e){r(`[acode-adapter] syncPluginCommands failed for agent ${t}:`,e.message)}}async startSession(t,e){const o=e.mcpConfigPath||v(),{resolved:s,configContextLimit:a,supportsImage:i}=await this.resolveAcodeProvider(e,o),n=s.model,d=a??Ht(n),l=Kt(n),m={sessionId:t,status:"starting",messages:[],createdAt:new Date().toISOString(),totalUsage:{inputTokens:0,outputTokens:0,contextLimit:d,maxOutput:l,cacheHitTokens:0,cacheMissTokens:0}};this.sessions.set(t,{adapterSession:m,config:e,runtime:await this.createRuntime(t,n,e,s,i),autoPollActive:!1,retryAttempt:0,retryActive:!1,retryEpoch:0}),this.emit("status-change",t,"starting");const c=this.sessions.get(t);if(!c)throw new Error("ACode session was not initialized");this.startLivenessWatchdog(t,c);const p=()=>{const f=this.sessions.get(t);f&&(f.autoPollDelayMs=void 0,this.getIdlePollLoop(f).start())};this.listenerWakeHooks.set(t,p),ht(e.agentId,p);try{if(await c.runtime.start(),console.log(`[HIBERNATE-REPLAY] startSession: agentId=${e.agentId??"?"} resumeTranscript=${Array.isArray(c.config.resumeTranscript)?`${c.config.resumeTranscript.length}\u6761`:"\u65E0"} importTranscript\u652F\u6301=${typeof c.runtime.importTranscript=="function"}`),m.status="waiting_input",this.emit("status-change",t,"waiting_input",{usage:c.adapterSession.totalUsage}),c.config.resumeTranscript&&c.runtime.importTranscript)try{const f=await c.runtime.importTranscript(c.config.resumeTranscript);console.log(`[HIBERNATE-REPLAY] importTranscript \u5B8C\u6210: agentId=${e.agentId??"?"} \u91CD\u653E=${f}\u6761 conversation=${c.runtime.exportConversation?.().length??"?"}\u6761`),f>0&&c.adapterSession.messages.push({id:x(),sessionId:t,role:"assistant",content:`[\u4F11\u7720\u6062\u590D] \u5DF2\u91CD\u653E\u4F11\u7720\u524D\u7684 ${f} \u6761\u5BF9\u8BDD\u8BB0\u5F55\uFF0C\u4E0A\u4E0B\u6587\u5DF2\u63A5\u7EED\u3002`,timestamp:new Date().toISOString()})}catch(f){console.error(`[HIBERNATE-REPLAY] importTranscript \u5931\u8D25\uFF08\u964D\u7EA7\u4E3A\u6458\u8981\u901A\u9053\uFF09: agentId=${e.agentId??"?"}`,f instanceof Error?f.stack:f)}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 T=this.sessions.get(t);throw T?.capabilitiesFallbackTimer&&clearTimeout(T.capabilitiesFallbackTimer),T&&this.stopLivenessWatchdog(T),this.sessions.delete(t),j(e.agentId,this.listenerWakeHooks.get(t)),this.listenerWakeHooks.delete(t),f}}async sendMessage(t,e){const o=Date.now();r("[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"),r("[ACode] \u25B6\uFE0F sendMessage STARTED"),r(`[ACode] Session: ${t}`),r(`[ACode] Message: ${e.slice(0,100)}${e.length>100?"...":""}`),r("[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;r(`[ACode] Previous status: ${a}`),this.cancelScheduledAutoPoll(s),s.failedTurnRecoveryScheduled=!1,s.idlePollLoop?.stop(),s.idleListeningIntentionallyStopped=!1,this.cancelRequestRetry(s),s.retryAttempt=0,s.retryCircuitBroken=!1,s.retryEpoch+=1,s.turnModelRequestSucceeded=!1;const i={id:x(),sessionId:t,role:"user",content:e,timestamp:new Date().toISOString()};s.adapterSession.messages.push(i),this.emit("conversation-message",t,i),r(`[ACode] Changing status: ${a} \u2192 thinking`),s.adapterSession.status="thinking",this.emit("status-change",t,"thinking"),s.autoPollObservedAssistantText=!1,s.autoPollObservedAnyTool=!1,s.autoPollObservedPollingTool=!1,s.lastSubmittedPrompt=e,s.retryEpoch+=1,s.turnModelRequestSucceeded=!1,this.startSubmitTimeoutDetection(t,s,"sendMessage");try{r("[ACode] \u25B6\uFE0F Calling runtime.submit()...");const n=Date.now();await s.runtime.submit(e);const d=Date.now()-n;this.cancelSubmitTimeoutDetection(s),r(`[ACode] \u2705 runtime.submit() completed in ${d}ms`),r(`[ACode] Current status after submit: ${s.adapterSession.status}`),r("[ACode] \u25B6\uFE0F Calling recoverResolvedTurnWithoutTerminalEvent()..."),this.recoverResolvedTurnWithoutTerminalEvent(t),r(`[ACode] Status after recovery: ${s.adapterSession.status}`);const l=Date.now()-o;r("[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"),r(`[ACode] \u2705 sendMessage COMPLETED in ${l}ms`),r("[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 d=Date.now()-o;console.error(`[ACode] \u274C sendMessage FAILED after ${d}ms:`,n instanceof Error?n.message:String(n)),this.cancelSubmitTimeoutDetection(s),r("[ACode] \u25B6\uFE0F sendMessage failed, scheduling request retry..."),this.emitRuntimeErrorEvent(t,n),this.scheduleRequestRetry(t,"sendMessage"),r(`[ACode] Status after failure: ${s.adapterSession.status}`)}}async sendConfirmation(t,e){}submitToolPermissionDecision(t,e,o){const s=this.sessions.get(t);if(!s)return!1;s.pendingToolAuthRequests?.delete(e);const a=s.runtime.submitToolPermissionDecision?.(e,o)??!1;return a&&this.startSubmitTimeoutDetection(t,s,"submitToolPermissionDecision"),a}getPendingToolAuthRequests(t){const e=this.sessions.get(t);return e?.pendingToolAuthRequests?Array.from(e.pendingToolAuthRequests.entries()).map(([o,s])=>({requestId:o,capability:s.capability,detail:s.detail,requestedAt:s.requestedAt})):[]}async sendQuestionAnswer(t,e){const o=this.sessions.get(t);if(!o)return;const s=o.pendingQuestionToolCallId;if(!s){r(`[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.idleListeningIntentionallyStopped=!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)}compactContext(t,e){const o=this.requireSession(t);if(!o.runtime.compactContext)throw new Error("ACode runtime does not support manual context compaction");return o.runtime.compactContext(e)}getCompactionPreview(t){const e=this.requireSession(t);if(!e.runtime.getCompactionPreview)throw new Error("ACode runtime does not support compaction preview");return e.runtime.getCompactionPreview()}async terminateSession(t){const e=this.sessions.get(t);if(!e)return;this.cancelScheduledAutoPoll(e),e.failedTurnRecoveryScheduled=!1,e.idlePollLoop?.stop(),this.stopLivenessWatchdog(e),this.cancelRequestRetry(e),e.capabilitiesFallbackTimer&&(clearTimeout(e.capabilitiesFallbackTimer),e.capabilitiesFallbackTimer=void 0),await e.runtime.stop();const o=e.config.agentId;o&&(j(o,this.listenerWakeHooks.get(t)),gt(o)),this.listenerWakeHooks.delete(t),e.adapterSession.status="terminated",this.sessions.delete(t),o&&![...this.sessions.values()].some(s=>s.config.agentId===o)&&(this.expandedBuiltInCapabilities.delete(o),this.builtInCapabilityToolCache.delete(o)),this.emit("status-change",t,"terminated")}getConversation(t){return this.sessions.get(t)?.adapterSession.messages??[]}exportRawTranscript(t){const e=this.sessions.get(t);if(e?.runtime.exportConversation)try{const o=e.runtime.exportConversation();return Array.isArray(o)?o:void 0}catch{return}}async importRawTranscript(t,e){const o=this.sessions.get(t);return!o?.runtime.importTranscript||!Array.isArray(e)?0:o.runtime.importTranscript(e)}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}getTotalUsage(t){const e=this.sessions.get(t)?.adapterSession.totalUsage;if(e)return{inputTokens:e.inputTokens,outputTokens:e.outputTokens}}notifyForceMessage(t){const e=this.sessions.get(t);return e?.runtime?.notifyForceMessage?(e.autoPollDelayMs=void 0,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||v(),{resolved:s,supportsImage:a}=await this.resolveAcodeProvider(e.config,o);return s?.model?{model:s.model,supportsImage:a===!0,...s.baseURL?{baseURL:s.baseURL}:{},...s.apiKey?{apiKey:s.apiKey}:{}}:void 0}catch{return}}resolveAgentSkillsDir(t){if(t){try{const e=K(t);if(e)return e}catch(e){r(`[acode-adapter] skill farm sync failed for agent ${t}:`,e.message)}return ct(t)}return pt()}async applyAgentFeatures(t){if(!t)return;const e=this.shouldInjectCapabilityTools(t,P),o=this.shouldInjectCapabilityTools(t,L);for(const[a,i]of this.sessions){if(i.config.agentId!==t)continue;const n=i.runtime,d=e,l=o;try{if(d){const m=await M(t,await this.resolveAgentAiInfo(t)),c=n.addBuiltInTools?.(m)??0;c>0&&r(`[acode-adapter] session ${a}: ${c} desktop tools hot-added for agent ${t}`)}else{const m=n.removeBuiltInToolsByPrefix?.("desktop_")??0;m>0&&r(`[acode-adapter] session ${a}: ${m} desktop tools hot-removed for agent ${t}`)}}catch(m){r(`[acode-adapter] session ${a}: desktop feature hot-sync failed for agent ${t}:`,m.message)}if(l)try{const m=await R(t,i.config.scopeKey,typeof i.config.browserAllowPrivate=="boolean"?{allowPrivate:i.config.browserAllowPrivate}:void 0),c=n.addBuiltInTools?.(m)??0;c>0&&r(`[acode-adapter] session ${a}: ${c} browser tools hot-added for agent ${t}`)}catch(m){r(`[acode-adapter] session ${a}: browser feature hot-sync failed for agent ${t}:`,m.message)}else{const m=n.removeBuiltInToolsByPrefix?.("browser_")??0;m>0&&r(`[acode-adapter] session ${a}: ${m} browser tools hot-removed for agent ${t}`)}}this.syncMcpToolsForAgent(t);try{K(t)}catch(a){r(`[acode-adapter] skill farm hot-sync failed for agent ${t}:`,a.message)}try{await O.applyCapabilities(t)}catch(a){r(`[acode-adapter] plugin capability hot-sync failed for agent ${t}:`,a.message)}const s=St(t);for(const[a,i]of this.sessions)if(i.config.agentId===t)try{i.runtime.setToolPermissionPolicy?.(s)}catch(n){r(`[acode-adapter] session ${a}: tool permission policy hot-sync failed for agent ${t}:`,n.message)}}syncMcpToolsForAgent(t){if(t){for(const[e,o]of this.sessions)if(o.config.agentId===t)try{o.runtime.requestMcpToolsRefresh?.()}catch(s){r(`[acode-adapter] session ${e}: mcp tools refresh failed for agent ${t}:`,s.message)}}}async debugMountMcpServer(t,e,o){if(!t)return{ok:!1,mounted:!1,sessions:0,tools:0,error:"agentId is required"};let s=0,a=0,i,n;for(const[d,l]of this.sessions)if(l.config.agentId===t&&typeof l.runtime.addMcpServer=="function")try{const m=await l.runtime.addMcpServer(e,o);s+=1,m.ok?(a=m.tools,i=m.toolNames):n=m.error}catch(m){n=m.message,r(`[acode-adapter] session ${d}: debug mount mcp ${e} failed for agent ${t}:`,n)}return s===0?{ok:!1,mounted:!1,sessions:0,tools:0,error:`No active SDK session for agentId "${t}"\uFF08\u8C03\u8BD5\u6302\u8F7D\u4EC5\u5BF9\u8FD0\u884C\u4E2D\u7684\u4F1A\u8BDD\u751F\u6548\uFF09`}:{ok:!n,mounted:!0,sessions:s,tools:a,toolNames:i,error:n}}async debugUnmountMcpServer(t,e){if(!t)return{ok:!1,sessions:0};let o=0;for(const[,s]of this.sessions)if(s.config.agentId===t&&typeof s.runtime.removeMcpServer=="function")try{await s.runtime.removeMcpServer(e),o+=1}catch(a){r(`[acode-adapter] debug unmount mcp ${e} failed for agent ${t}:`,a.message)}return{ok:o>0,sessions:o}}getMcpServerStderr(t,e,o=100){if(!t)return[];for(const[,s]of this.sessions)if(s.config.agentId===t&&typeof s.runtime.getMcpServerStderr=="function")return s.runtime.getMcpServerStderr(e,o);return[]}shouldInjectCapabilityTools(t,e){return t?U(t,e)==="expanded":!0}resolveCapabilityToolPrefix(t){return N[String(t??"").trim()]}async loadCapabilityToolsForSession(t,e,o){const s=t===L?await R(e,o.config.scopeKey,typeof o.config.browserAllowPrivate=="boolean"?{allowPrivate:o.config.browserAllowPrivate}:void 0):await M(e,await this.resolveAgentAiInfo(e)),a=[];for(const i of s){const n=qt(i);n&&a.push(n)}return a}async setBuiltInCapabilityTools(t,e,o){const s=String(t??"").trim(),a=this.resolveCapabilityToolPrefix(e);if(!s||!a)return{sessions:0,tools:0};const i=[...this.sessions.entries()].filter(([,l])=>l.config.agentId===s);if(i.length===0)return{sessions:0,tools:0};if(o==="collapse"){let l=0;for(const[m,c]of i){const p=c.runtime.removeBuiltInToolsByPrefix?.(a)??0;l+=p,p>0&&r(`[acode-adapter] session ${m}: ${p} ${e} tools removed on collapse (agent ${s})`)}return this.expandedBuiltInCapabilities.get(s)?.delete(e),this.builtInCapabilityToolCache.get(s)?.delete(e),r(`[acode-adapter] capability collapse: agent=${s} capability=${e} sessions=${i.length} removedTools=${l}`),{sessions:i.length,tools:l}}const n=new Map;for(const[l,m]of i){let c;try{c=await this.loadCapabilityToolsForSession(e,s,m)}catch(p){throw r(`[acode-adapter] session ${l}: capability ${e} tool load failed for agent ${s}:`,p.message),p}for(const p of c)n.has(p.name)||n.set(p.name,p)}const d=this.expandedBuiltInCapabilities.get(s)??new Set;return d.add(e),this.expandedBuiltInCapabilities.set(s,d),this.builtInCapabilityToolCache.set(s,n),r(`[acode-adapter] capability expand: agent=${s} capability=${e} sessions=${i.length} tools=${n.size} (manifests only, no session tool injection)`),{sessions:i.length,tools:n.size,manifests:[...n.values()].map(l=>({name:l.name,...l.description!==void 0?{description:l.description}:{},...l.inputSchema!==void 0?{inputSchema:l.inputSchema}:{}}))}}async callBuiltInCapabilityTool(t,e,o,s){const a=String(t??"").trim(),i=this.resolveCapabilityToolPrefix(e);if(!i)return{ok:!1,error:`\u672A\u77E5\u80FD\u529B\u300C${String(e)}\u300D\uFF1A\u4EC5\u652F\u6301 browser / desktop`};const n=String(o??"").trim();if(!n)return{ok:!1,error:"\u5DE5\u5177\u540D\u7F3A\u5931"};if(!n.startsWith(i))return{ok:!1,error:`\u5DE5\u5177\u300C${n}\u300D\u4E0D\u5C5E\u4E8E\u80FD\u529B\u300C${e}\u300D`};if(a&&U(a,e)==="disabled")return{ok:!1,error:`\u80FD\u529B\u300C${e}\u300D\u5DF2\u7981\u7528\uFF0C\u65E0\u6CD5\u8C03\u5EA6\u8BE5\u5DE5\u5177`};if(!(this.expandedBuiltInCapabilities.get(a)?.has(e)??!1))return{ok:!1,error:`\u80FD\u529B\u300C${e}\u300D\u5C1A\u672A\u5C55\u5F00\uFF0C\u8BF7\u5148\u8C03\u7528 expand_tools \u5C55\u5F00\u540E\u518D\u8C03\u5EA6\u8BE5\u5DE5\u5177`};const l=this.builtInCapabilityToolCache.get(a)?.get(n);return l?typeof l.execute!="function"?{ok:!1,error:`\u5DE5\u5177\u300C${n}\u300D\u4E0D\u53EF\u8C03\u5EA6\uFF08\u7F3A\u5C11 execute \u5B9E\u73B0\uFF09`}:{ok:!0,result:await l.execute.call(l.definition,s??{})}:{ok:!1,error:`\u5DE5\u5177\u300C${n}\u300D\u65E0\u7F13\u5B58\u5B9A\u4E49\uFF0C\u8BF7\u91CD\u65B0\u8C03\u7528 expand_tools \u5237\u65B0`}}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&&q(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 rt.readFile(t,"utf-8"),o=JSON.parse(e),a=o.provider?.default,i=a?.options,n=y(o.contextLimit),d={},l={},m=a?.models;if(m&&typeof m=="object"){for(const[c,p]of Object.entries(m))if(p&&typeof p=="object"){const f=y(p.contextLimit);f>0&&(d[c.trim()]=f);const T=p.modalities?.input,g=Array.isArray(T)&&T.includes("image")||p.supportsImageInput===!0;l[c.trim()]=g===!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(d).length>0?{modelContextLimits:d}:{},...Object.keys(l).length>0?{modelImageSupport:l}:{}}}catch(e){const o=e instanceof Error?e.message:String(e);return F().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=F();s.log({level:"info",category:"resolve",message:"resolveAcodeProvider \u8F93\u5165",source:"bridge",details:{configModel:t.model??null,configInstanceAiConfig:t.instanceAiConfig?G(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 l=o||t.instanceAiConfig?.model||i.model;l&&i.modelContextLimits[l]&&(n=i.modelContextLimits[l])}const d=$t(a,i,"acode-default");return s.log({level:"info",category:"resolve",message:"resolveAcodeProvider \u89E3\u6790\u7ED3\u679C",source:"bridge",details:{instanceConfig:G(a),globalConfigModel:i?.model??null,resolvedModel:d.model,resolvedBaseURL:d.baseURL??null,resolvedApiKey:d.apiKey?"[set]":null,configContextLimit:n,resolvedSource:d.source}}),{resolved:d,configPath:e,perSessionModel:o,configContextLimit:n,supportsImage:i.modelImageSupport?.[d.model]===!0}}async createRuntime(t,e,o,s,a){const i=await this.loadRuntimeConstructor(),n=o.mcpConfigPath||v();let d=[];try{d=await R(o.agentId,o.scopeKey,typeof o.browserAllowPrivate=="boolean"?{allowPrivate:o.browserAllowPrivate}:void 0)}catch(p){r(`[acode-adapter] browser tools injection skipped for agent ${o.agentId}:`,p.message)}let l=[];if(this.shouldInjectCapabilityTools(o.agentId??"",L)&&(l=d),o.agentId&&this.shouldInjectCapabilityTools(o.agentId,P))try{const p=s?.model?{model:s.model,supportsImage:a===!0,...s.baseURL?{baseURL:s.baseURL}:{},...s.apiKey?{apiKey:s.apiKey}:{}}:void 0,f=await M(o.agentId,p);f.length>0&&(l=[...l,...f])}catch(p){r(`[acode-adapter] desktop tools injection skipped for agent ${o.agentId}:`,p.message)}const m=new i({sessionId:t,agentId:o.agentId,workingDirectory:o.workingDirectory,configPath:n,skillsDir:this.resolveAgentSkillsDir(o.agentId),pluginsDir:o.agentId?dt(o.agentId):void 0,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,resumeContext:typeof o.resumeContext=="string"?o.resumeContext:void 0,env:o.envOverrides,subAgentManager:Ct,terminalManager:ft,capabilityState:p=>ut(p)?"collapsed":U(o.agentId??"",bt(p)),capabilityToolRelay:o.agentId?{handlesGroup:p=>this.resolveCapabilityToolPrefix(p)!==void 0,handlesTool:p=>Object.values(N).some(f=>p.startsWith(f)),expand:async p=>(await this.setBuiltInCapabilityTools(o.agentId??"",p,"expand")).manifests??[],collapse:async p=>{await this.setBuiltInCapabilityTools(o.agentId??"",p,"collapse")},call:async(p,f)=>{const T=p.startsWith(N[P]??"desktop_")?P:L;return this.callBuiltInCapabilityTool(o.agentId??"",T,p,f)}}:void 0,pluginBridge:o.agentId?O.forAgent(o.agentId):void 0,runtimeResourcesProvider:o.agentId?()=>_t(o.agentId):void 0,...o.subAgentModel?{subAgentModel:o.subAgentModel}:{},...o.subAgentEffort?{subAgentEffort:o.subAgentEffort}:{},...o.instanceAiConfig?.effort?{effort:o.instanceAiConfig.effort}:{},onFileChange:p=>kt({...p,agentId:o.agentId,workspacePath:o.workingDirectory}),extraBuiltInTools:l,...o.agentId?{toolPermissionPolicy:At(o.agentId)??void 0}:{},subAgentSuiteTools:d,subAgentSuiteToolProvider:this.buildSubAgentSuiteToolProvider(o.agentId)});return F().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:n}}),m.on("event",p=>this.forwardAcodeEvent(p)),m}buildSubAgentSuiteToolProvider(t){return async e=>{if(!t)return[];if(!yt(t,P))return[];if(e.length===0)return Tt();if(!e.some(a=>{const i=a.trim().replace(/[.*]+$/,"");return i==="desktop"||i.startsWith("desktop.")}))return[];const s=await this.resolveAgentAiInfo(t);return M(t,s)}}async loadRuntimeConstructor(){if(this.runtimeConstructor)return this.runtimeConstructor;const t=Nt(),e=await import(Wt(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"),o.autoPollObservedAssistantText=!1,o.autoPollObservedAnyTool=!1,o.autoPollObservedPollingTool=!1,o.lastSubmittedPrompt=e,o.retryEpoch+=1,o.turnModelRequestSucceeded=!1,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),a.lastErrorText=s instanceof Error?s.message:String(s),this.emitRuntimeErrorEvent(t,s),this.scheduleRequestRetry(t,"startInitialPromptTurn"))}))}forwardAcodeEvent(t){const e=this.sessions.get(t.sessionId);if(e){if(e.lastAcodeEventAt=Date.now(),e.autoPollActive&&(e.autoPollLastActivityAt=Date.now()),t.type==="assistant_delta"){const o=typeof t.data.text=="string"?t.data.text:"";e.turnModelRequestSucceeded=!0,e.turnModelRequestSucceededEpoch=e.retryEpoch,e.autoPollObservedAssistantText=!0,e.adapterSession.messages.push({id:x(),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:"";e.turnModelRequestSucceeded=!0,e.turnModelRequestSucceededEpoch=e.retryEpoch,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:jt(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=t.data.lastUsage,s=y(o?.inputTokens),a=y(o?.outputTokens),i=y(o?.cacheHitTokens),n=y(o?.cacheMissTokens),d=!!(o&&(s>0||a>0));let l;d&&(s>0&&(e.adapterSession.totalUsage.inputTokens=s),a>0&&(e.adapterSession.totalUsage.outputTokens=a),(o?.cacheHitTokens!==void 0||o?.cacheMissTokens!==void 0)&&(e.adapterSession.totalUsage.cacheHitTokens=i,e.adapterSession.totalUsage.cacheMissTokens=n),l={...e.adapterSession.totalUsage},w(`ai_request lastUsage applied: ${JSON.stringify(o)} -> totalUsage=${JSON.stringify(e.adapterSession.totalUsage)}`)),e.adapterSession.status==="compacting"&&(e.adapterSession.status="thinking"),e.adapterSession.status==="waiting_input"&&(e.adapterSession.status="thinking");const c={actionType:"ai_request",actionLabel:"AI\u8BF7\u6C42",actionDetail:this.formatAiRequestActionDetail(t.data)};l&&(c.usage=l),w(`ai_request handled: estimatedContextTokens=${t.data.estimatedContextTokens??"n/a"} totalUsage=${JSON.stringify(e.adapterSession.totalUsage)} displayUsage=${JSON.stringify(l??null)}`),this.emit("status-change",t.sessionId,e.adapterSession.status,c),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:Gt(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});return}if(t.type==="iteration_usage"){const o=it(t.data);o&&(e.adapterSession.totalUsage.inputTokens=o.inputTokens,e.adapterSession.totalUsage.outputTokens=o.outputTokens,o.hasCache&&(e.adapterSession.totalUsage.cacheHitTokens=o.cacheHitTokens,e.adapterSession.totalUsage.cacheMissTokens=o.cacheMissTokens),w(`iteration_usage applied: raw=${JSON.stringify(t.data)} -> totalUsage=${JSON.stringify(e.adapterSession.totalUsage)}`),this.emit("status-change",t.sessionId,e.adapterSession.status,{usage:{...e.adapterSession.totalUsage}}));return}if(t.type==="turn_complete"){const o=it(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.hasCache&&(e.adapterSession.totalUsage.cacheHitTokens=o.cacheHitTokens,e.adapterSession.totalUsage.cacheMissTokens=o.cacheMissTokens,r(`[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(r(`[ACode] turn_complete event received (session: ${t.sessionId}), previous status: ${s}, failed: ${t.data.failed===!0}, aborted: ${t.data.aborted===!0}`),zt(t.data)){r(`[ACode] Scheduling retry from failed turn_complete (session: ${t.sessionId})`),this.cancelDataFlowWatchdog(e),this.recoverTurnFailure(t.sessionId,e);return}if(t.data.aborted===!0&&(e.autoPollActive||e.retryActive||e.retryTimer)){r(`[ACode] Scheduling retry from aborted turn_complete (session: ${t.sessionId})`),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",k("turn_complete_to_waiting_input",{sessionId:t.sessionId,autoPollActive:!!e.autoPollActive,observedAnyTool:!!e.autoPollObservedAnyTool,observedPollingTool:!!e.autoPollObservedPollingTool,observedAssistantText:!!e.autoPollObservedAssistantText}),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)}`),r(`[ACode] Status changed to waiting_input after turn_complete (session: ${t.sessionId})`),e.autoPollActive&&e.autoPollObservedAssistantText&&!e.autoPollObservedPollingTool&&!e.autoPollObservedAnyTool){e.stopAutoPollAfterCurrentTurn=!0,e.idleListeningIntentionallyStopped=!0,console.warn(`[${this.displayName}] Auto-poll turn produced assistant text without calling any tool; stopping auto-poll rearm for session ${t.sessionId}`);return}if(!e.autoPollActive&&e.autoPollObservedAnyTool&&!e.autoPollObservedPollingTool){r(`[ACode] User-message turn called work tools; deferring idle rearm (no immediate dispatch) for this turn (session: ${t.sessionId})`),this.scheduleDeferredIdleRearm(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==="tool_permission_request"){this.cancelDataFlowWatchdog(e),this.cancelSubmitTimeoutDetection(e);const o=typeof t.data.requestId=="string"?t.data.requestId:"";o&&(e.pendingToolAuthRequests||(e.pendingToolAuthRequests=new Map),e.pendingToolAuthRequests.set(o,{capability:String(t.data.capability||""),detail:{path:t.data.path,command:t.data.command,cwd:t.data.cwd,operation:t.data.operation},requestedAt:Date.now()})),this.emit("tool-permission-request",{sessionId:t.sessionId,requestId:o,capability:String(t.data.capability||""),agentId:e.config.agentId,detail:{path:t.data.path,command:t.data.command,cwd:t.data.cwd,operation:t.data.operation}});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",e.lastErrorText=String(t.data.message||""),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 g=t.data.tools;g.some(A=>wt(A))||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 S=Array.isArray(t.data.servers)?t.data.servers:[],b=g.map(A=>({name:String(A.name??""),source:String(A.source??""),description:String(A.description??"")})).filter(A=>A.name),C={kind:"mcp",mcpServers:S,mcpTools:b};e.cachedMcpCapabilities=C,e.lastMcpCapabilities=C,e.lastCombinedCapabilities={kind:"combined",mcpServers:S,mcpTools:b,skills:e.lastCombinedCapabilities?.skills??[],skillsDir:e.lastCombinedCapabilities?.skillsDir,skillGroups:e.lastCombinedCapabilities?.skillGroups??[]},r(`[cap-diag] MCP capabilities cached: ${S.length} servers, ${b.length} tools`,{sessionId:t.sessionId,servers:S,toolNames:b.map(A=>A.name)}),e.capabilitiesFallbackTimer&&clearTimeout(e.capabilitiesFallbackTimer),e.capabilitiesFallbackTimer=setTimeout(()=>{const A=e.cachedMcpCapabilities;if(!A)return;const _={...A,skills:[],skillGroups:[]};this.emitProviderEvent(t,"runtime_capabilities",{capabilities:_,actionType:"runtime_capabilities",actionLabel:"\u8FD0\u884C\u65F6\u80FD\u529B",actionDetail:JSON.stringify(_)}),r(`[cap-diag] MCP capabilities emitted via fallback (skill_status not received within ${et}ms)`,{sessionId:t.sessionId,mcpServers:A.mcpServers,mcpToolsCount:A.mcpTools?.length??0}),e.cachedMcpCapabilities=void 0,e.capabilitiesFallbackTimer=void 0},et);return}const o=String(t.data.action??"");if(o==="tool_batch_start"){const g=typeof t.data.batchId=="string"?t.data.batchId:void 0;if(!g){r(`[ACode] \u{1F9E9} tool_batch_start without batchId, ignored (session=${t.sessionId})`);return}const h=typeof t.data.toolCount=="number"?t.data.toolCount:0,S=Array.isArray(t.data.toolNames)?t.data.toolNames.map(b=>String(b??"")).filter(Boolean):[];r(`[ACode] \u{1F9E9} tool_batch_start: batch=${g.slice(0,20)}\u2026, tools=${h}`),this.emitProviderEvent(t,"tool_batch_start",{batchId:g,batchToolCount:h,batchToolNames:S,actionType:"tool_batch",actionLabel:"\u5E76\u884C\u6267\u884C\u5DE5\u5177",actionDetail:S.length>0?S.join(", "):void 0,actionId:g});return}if(o==="tool_batch_metrics"){const g=typeof t.data.batchId=="string"?t.data.batchId:void 0;if(!g){r(`[ACode] \u26A1 tool_batch_metrics without batchId, ignored (session=${t.sessionId})`);return}const h={toolCount:I(t.data.toolCount),parallelism:I(t.data.parallelism),speedup:I(t.data.speedup),wallClockMs:I(t.data.wallClockMs),totalWaitMs:W(t.data.totalWaitMs),contentionCount:I(t.data.contentionCount),failureCount:W(t.data.failureCount),maxConcurrentObserved:W(t.data.maxConcurrentObserved)};r(`[ACode] \u26A1 tool_batch_metrics: batch=${g.slice(0,20)}\u2026, speedup=${h.speedup}x parallelism=${h.parallelism}x wall=${h.wallClockMs}ms contentions=${h.contentionCount} failures=${h.failureCount??"-"}`),this.emitProviderEvent(t,"tool_batch_metrics",{batchId:g,batchMetrics:h,actionType:"tool_batch",actionLabel:"\u5E76\u884C\u6267\u884C\u5DE5\u5177",actionId:g});return}if(o!=="call_tool"&&o!=="tool_result"){r(`[ACode] \u{1F4AC} mcp_status status report ignored (action=${o||"none"}, server=${typeof t.data.server=="string"?t.data.server:"?"}, session=${t.sessionId})`);return}r(`[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,d=Et(i,n);e.autoPollObservedAnyTool=!0,d.actionType==="idle"&&(e.autoPollObservedPollingTool=!0);const l=Jt(d.actionType)?d.actionDetail||at(void 0,s,a):at(d.actionDetail,s,a),m=typeof t.data.toolUseId=="string"?t.data.toolUseId:void 0,c=n?JSON.stringify(n,null,2):void 0,p=typeof t.data.batchId=="string"?t.data.batchId:void 0,f={toolName:l,rawToolName:i,actionType:d.actionType,actionLabel:d.actionLabel,actionDetail:l,...c?{actionInput:c}:{},...n?{toolInput:n}:{},...m?{toolUseId:m,actionId:m}:{},...p?{batchId:p,parentId:p}:{},metadata:{mcpServer:s}};if(t.data.action==="tool_result"){this.emitProviderEvent(t,"tool_use_end",{...f,toolResult:typeof t.data.result=="string"?t.data.result:JSON.stringify(t.data.result??"")}),e.adapterSession.messages.push({id:x(),sessionId:t.sessionId,role:"tool_result",content:typeof t.data.result=="string"?t.data.result:JSON.stringify(t.data.result??""),timestamp:t.timestamp,toolName:i,toolUseId:m,isError:t.data.failed===!0});const g=d.actionType==="idle"&&!Qt(t.data.result)?"waiting_input":"thinking";e.adapterSession.status=g,d.actionType==="idle"&&(e.idleToolActiveAt=void 0),k("tool_use_end",{sessionId:t.sessionId,actionType:d.actionType,tool:i,nextStatus:g,idleToolActiveAtAfter:e.idleToolActiveAt??null}),this.cancelDataFlowWatchdog(e),e.pendingToolEventData=void 0;const h=d.actionType==="idle";this.emit("status-change",t.sessionId,g,h||g==="thinking"?void 0:f);return}const T=d.actionType==="idle"?"waiting_input":"tool_using";e.adapterSession.status=T,d.actionType==="idle"&&(e.idleToolActiveAt=Date.now()),T==="tool_using"&&(this.resetDataFlowWatchdog(t.sessionId,e),e.pendingToolEventData={...f}),e.adapterSession.messages.push({id:x(),sessionId:t.sessionId,role:"tool_use",content:c??"",timestamp:t.timestamp,toolName:i,toolInput:n,toolUseId:m}),this.emitProviderEvent(t,"tool_use_start",f),this.emit("status-change",t.sessionId,T,f);return}if(t.type==="skill_status"){const s=(Array.isArray(t.data.skills)?t.data.skills:[]).map(c=>({name:String(c.name??""),description:typeof c.description=="string"?c.description:void 0,directory:typeof c.directory=="string"?c.directory:void 0})).filter(c=>c.name),a=typeof t.data.skillsDir=="string"?t.data.skillsDir:void 0,n=(Array.isArray(t.data.skillGroups)?t.data.skillGroups:[]).map(c=>{const p=Array.isArray(c.skills)?c.skills:[];return{dir:typeof c.dir=="string"?c.dir:"",exists:c.exists===!0,skills:p.map(f=>({name:String(f.name??""),description:typeof f.description=="string"?f.description:void 0,directory:typeof f.directory=="string"?f.directory:void 0})).filter(f=>f.name)}}).filter(c=>c.dir),d=e.cachedMcpCapabilities??e.lastMcpCapabilities,l=e.cachedMcpCapabilities!==void 0,m={kind:"combined",mcpServers:d?.mcpServers??[],mcpTools:d?.mcpTools??[],skills:s,skillsDir:a,skillGroups:n};this.emitProviderEvent(t,"runtime_capabilities",{capabilities:m,actionType:"runtime_capabilities",actionLabel:"\u8FD0\u884C\u65F6\u80FD\u529B",actionDetail:JSON.stringify(m)}),e.lastCombinedCapabilities=m,r(`[cap-diag] Combined capabilities emitted ${l?"(startup merge)":"(runtime refresh)"}: ${(d?.mcpTools??[]).length} MCP tools, ${s.length} skills`,{sessionId:t.sessionId,mcpServers:d?.mcpServers??[],skillsDir:a}),e.capabilitiesFallbackTimer&&(clearTimeout(e.capabilitiesFallbackTimer),e.capabilitiesFallbackTimer=void 0),e.cachedMcpCapabilities=void 0;return}if(t.type==="startup_phase"){r(`[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"){r(`[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=y(t.data.contextLimit)||void 0,s=y(t.data.maxOutput)||void 0,a=y(t.data.inputLimit)||void 0,i=y(t.data.compactionThreshold)||void 0;let n=!1;o!==void 0&&(e.adapterSession.totalUsage.contextLimit=o,n=!0),s!==void 0&&(e.adapterSession.totalUsage.maxOutput=s,n=!0),a!==void 0&&(e.adapterSession.totalUsage.inputLimit=a,n=!0),i!==void 0&&(e.adapterSession.totalUsage.compactionThreshold=i,n=!0),n&&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",d=o.parentId,l=o.compactionId;if(o.trigger==="hibernation_replay"){const T=typeof o.replayedMessageCount=="number"?o.replayedMessageCount:void 0,g=o.estimatedTokens;typeof g=="number"&&g>0&&(e.adapterSession.totalUsage.inputTokens=g);const h={actionType:"context_compaction",actionLabel:"\u4F11\u7720\u6062\u590D",actionDetail:T?`\u5DF2\u91CD\u653E\u4F11\u7720\u524D\u7684 ${T} \u6761\u5BF9\u8BDD\u8BB0\u5F55\uFF0C\u4E0A\u4E0B\u6587\u5DF2\u63A5\u7EED`:"\u5DF2\u91CD\u653E\u4F11\u7720\u524D\u7684\u5BF9\u8BDD\u8BB0\u5F55\uFF0C\u4E0A\u4E0B\u6587\u5DF2\u63A5\u7EED",...l?{actionId:l}:{},...g?{usage:{...e.adapterSession.totalUsage,inputTokens:g}}:{}};this.emitProviderEvent(t,"context_compaction",h),this.emit("status-change",t.sessionId,e.adapterSession.status,h);return}let c,p;if(a){const T=String(o.sizeKB??o.sizeBeforeKB??"?"),g=String(o.messageCount??o.messageCountBefore??"?"),h=o.estimatedTokens,S=o.actualInputTokens?`input=${o.actualInputTokens}`:"",b=o.actualOutputTokens?`output=${o.actualOutputTokens}`:"",C=o.trigger;c="\u4E0A\u4E0B\u6587\u538B\u7F29\u5F00\u59CB";const A=C==="provider_overflow_error"?"\u6A21\u578B\u8FD4\u56DE\u4E0A\u4E0B\u6587\u8D85\u9650\u4FE1\u53F7":C==="finish_reason_context_overflow"?"\u54CD\u5E94\u4E2D\u7684\u8D85\u9650\u6807\u8BB0":C==="request_body_byte_limit"?"\u8BF7\u6C42\u4F53\u5B57\u8282\u4E0A\u9650":C,_=A?`, \u89E6\u53D1: ${A}`:"";h!==void 0?p=`\u538B\u7F29\u524D: ~${h} tokens, \u6D88\u606F: ${g}\u6761`+(S?`, \u5B9E\u9645 tokens: ${S} ${b}`:"")+_:p=`\u538B\u7F29\u524D: ${T}KB, \u6D88\u606F: ${g}\u6761`+(S?`, \u5B9E\u9645 tokens: ${S} ${b}`:"")+_}else if(n){const T=String(o.phase??""),g=String(o.phaseLabel??"\u538B\u7F29\u9636\u6BB5"),h=String(o.phaseDetail??"");T==="detect"?(c="\u5F00\u59CB\u89E6\u53D1\u54CD\u5E94\u5F0F\u538B\u7F29",p=h||"\u68C0\u6D4B\u5230\u4E0A\u4E0B\u6587\u8D85\u9650\uFF0C\u5373\u5C06\u5F00\u59CB\u538B\u7F29..."):(c=g,p=h)}else{const T=o.tokensBefore,g=o.tokensAfter,h=o.freedTokens,S=String(o.sizeBeforeKB??"?"),b=String(o.sizeAfterKB??"?"),C=String(o.freedKB??"?"),A=String(o.strategy??"?"),_=Number(o.prunedToolMessages??0),D=Number(o.summarizedMessages??0);c="\u538B\u7F29\u5B8C\u6210",T!==void 0&&g!==void 0?p=`\u91CA\u653E: ${h??T-g} tokens, ${T} tokens \u2192 ${g} tokens, \u7B56\u7565: ${A}`+(_?`, \u88C1\u526A\u5DE5\u5177: ${_}\u6761`:"")+(D?`, \u6458\u8981\u5316: ${D}\u6761`:""):p=`\u91CA\u653E: ${C}KB, ${S}KB \u2192 ${b}KB, \u7B56\u7565: ${A}`+(_?`, \u88C1\u526A\u5DE5\u5177: ${_}\u6761`:"")+(D?`, \u6458\u8981\u5316: ${D}\u6761`:"")}a&&(e.adapterSession.status="compacting");const f={actionType:"context_compaction",actionLabel:c,actionDetail:p};if(a&&l)f.actionId=l;else if((n||i)&&l)if(f.parentId=l,n){const T=String(o.phase??"unknown");f.actionId=`${l}-phase-${T}`}else f.actionId=`${l}-end`;n&&d&&!f.parentId&&(f.parentId=d),i&&(e.adapterSession.totalUsage.inputTokens=y(o.tokensAfter),e.adapterSession.totalUsage.outputTokens=0,f.usage={...e.adapterSession.totalUsage}),this.emitProviderEvent(t,"context_compaction",f),this.emit("status-change",t.sessionId,"compacting",f);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.autoPollTimer&&(clearTimeout(e.autoPollTimer),e.autoPollTimer=void 0),this.cancelRequestRetry(e),e.retryAttempt=0,e.idleCommands?.idleInputCommand){this.getIdlePollLoop(e).start();return}this.scheduleAutoPoll(t)}}scheduleDeferredIdleRearm(t){const e=this.sessions.get(t);!e||e.autoPollActive||e.autoPollTimer||this.isTerminalStatus(e.adapterSession.status)||this.scheduleAutoPoll(t,Ut)}getIdlePollLoop(t){if(t.idlePollLoop)return t.idlePollLoop;const e=t.adapterSession.sessionId;return t.idlePollLoop=new Pt({getStatus:()=>this.sessions.get(e)?.adapterSession.status,getCommand:()=>this.sessions.get(e)?.idleCommands?.idleInputCommand,isPollingCommand:o=>q(o),preDispatchHook:()=>null,dispatchPollingPrompt:(o,s)=>this.submitAutoPollPrompt(e,s?o:Bt,{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.idleListeningIntentionallyStopped=!1,s.autoPollQueuedAt=Date.now(),s.autoPollLastActivityAt=Date.now(),s.idleToolActiveAt=void 0,s.lastSubmittedPrompt=e,s.retryEpoch+=1,s.turnModelRequestSucceeded=!1,o?.keepWaitingStatus||(s.adapterSession.status="thinking",this.emit("status-change",t,"thinking")),this.startSubmitTimeoutDetection(t,s,"submitAutoPollPrompt"),s.runtime.submit(e).catch(i=>{this.emitRuntimeErrorEvent(t,i),this.scheduleRequestRetry(t,"submitAutoPollPrompt")}).finally(()=>{const i=this.sessions.get(t);if(i){if(i.autoPollToken!==a){r(`[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){const o=this.sessions.get(t);if(!o||o.autoPollActive||o.autoPollTimer||this.isTerminalStatus(o.adapterSession.status))return;const s=e??o.autoPollDelayMs??vt;e===void 0&&(o.autoPollDelayMs=Math.min(s*2,Rt)),o.autoPollTimer=setTimeout(()=>{const a=this.sessions.get(t);!a||a.autoPollActive||this.isTerminalStatus(a.adapterSession.status)||(a.autoPollTimer=void 0,this.submitAutoPollPrompt(t,It,{keepWaitingStatus:!0}))},s)}cancelScheduledAutoPoll(t){t.autoPollDelayMs=void 0,t.autoPollTimer&&(clearTimeout(t.autoPollTimer),t.autoPollTimer=void 0)}scheduleRequestRetry(t,e){const o=this.sessions.get(t);if(!o||this.isTerminalStatus(o.adapterSession.status))return;if(o.retryCircuitBroken){r(`[ACode] scheduleRequestRetry(${e}): retry terminated by non-retryable error, suppress further auto-retry`);return}if(o.retryActive||o.retryTimer)return;if(!o.lastSubmittedPrompt){o.adapterSession.status="error",this.emit("status-change",t,"error");return}if(o.turnModelRequestSucceeded&&o.turnModelRequestSucceededEpoch===o.retryEpoch&&(o.turnModelRequestSucceeded=!1,o.retryAttempt=0),o.lastErrorText&&Ft(o.lastErrorText)){r(`[ACode] scheduleRequestRetry(${e}): non-retryable provider error, giving up retry: ${o.lastErrorText.slice(0,200)}`),this.cancelRequestRetry(o),o.retryAttempt=0,o.retryCircuitBroken=!0,o.adapterSession.status="error",this.emit("status-change",t,"error",{actionType:"retry_aborted",actionLabel:"\u8BF7\u6C42\u65E0\u6548",actionDetail:"Provider \u8FD4\u56DE 4xx \u8BF7\u6C42\u9519\u8BEF\uFF08\u539F\u6837\u91CD\u8BD5\u5FC5\u7136\u5931\u8D25\uFF09\uFF0C\u5DF2\u505C\u6B62\u81EA\u52A8\u91CD\u8BD5\uFF0C\u8BF7\u68C0\u67E5\u6E20\u9053\u914D\u7F6E\u6216\u91CD\u542F\u4F1A\u8BDD\u3002",actionError:Z(o.lastErrorText)});return}o.retryAttempt+=1,o.retryActive=!0,this.cancelScheduledAutoPoll(o),o.idlePollLoop?.stop();const s=V[Math.min(o.retryAttempt-1,V.length-1)];o.adapterSession.status="error",this.emit("status-change",t,"error",{actionType:"retry",actionLabel:"\u91CD\u8BD5\u4E2D",actionDetail:`\u7B2C${o.retryAttempt}\u6B21 \xB7 ${Math.round(s/1e3)}s\u540E`,actionError:Z(o.lastErrorText)}),r(`[ACode] scheduleRequestRetry(${e}): attempt=${o.retryAttempt} delay=${s}ms`),o.retryTimer=setTimeout(()=>{o.retryTimer=void 0,this.retryFailedRequest(t,e)},s)}retryFailedRequest(t,e){const o=this.sessions.get(t);if(!o)return;if(o.retryTimer=void 0,this.isTerminalStatus(o.adapterSession.status)||!o.lastSubmittedPrompt){o.retryActive=!1;return}o.retryActive=!1;const s=o.lastSubmittedPrompt;r(`[ACode] retryFailedRequest(${e}): attempt=${o.retryAttempt} re-submitting...`),o.retryEpoch+=1,o.turnModelRequestSucceeded=!1,o.autoPollObservedAssistantText=!1,o.autoPollObservedAnyTool=!1,o.autoPollObservedPollingTool=!1,o.adapterSession.status="thinking",this.emit("status-change",t,"thinking",{usage:o.adapterSession.totalUsage}),this.startSubmitTimeoutDetection(t,o,"retryFailedRequest"),o.runtime.submit(s,{resume:!0}).then(()=>{const a=this.sessions.get(t);!a||a.retryTimer||(this.cancelSubmitTimeoutDetection(a),a.retryAttempt=0,a.retryActive=!1,a.retryCircuitBroken=!1,this.recoverResolvedTurnWithoutTerminalEvent(t))}).catch(a=>{const i=this.sessions.get(t);i&&(this.cancelSubmitTimeoutDetection(i),i.lastErrorText=a instanceof Error?a.message:String(a),this.emitRuntimeErrorEvent(t,a),this.scheduleRequestRetry(t,`retry#${i.retryAttempt+1}`))})}cancelRequestRetry(t){t.retryTimer&&(clearTimeout(t.retryTimer),t.retryTimer=void 0),t.retryActive=!1}isTerminalStatus(t){return t==="completed"||t==="terminated"}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.pendingToolAuthRequests?.size&&e.pendingToolAuthRequests.clear(),e.adapterSession.status==="tool_using"&&e.pendingToolEventData){const s=e.pendingToolEventData;r(`[ACode] recoverTurnFailure: \u8865\u53D1 tool_use_end (tool: ${s.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:{...s,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 s=e.adapterSession.totalUsage.outputTokens;e.adapterSession.totalUsage.outputTokens=o,r(`[ACode] recoverTurnFailure: \u4F30\u7B97\u8986\u76D6 output tokens ${s} -> ${o} (totalUsage now: input=${e.adapterSession.totalUsage.inputTokens}, output=${e.adapterSession.totalUsage.outputTokens})`)}this.cancelScheduledAutoPoll(e),this.scheduleRequestRetry(t,"recoverTurnFailure")}recoverResolvedTurnWithoutTerminalEvent(t){r(`[ACode] \u25B6\uFE0F recoverResolvedTurnWithoutTerminalEvent called for session ${t}`);const e=this.sessions.get(t);if(!e||this.isTerminalStatus(e.adapterSession.status)){r(`[ACode] Skipping recovery: entry=${!!e}, isTerminal=${e?this.isTerminalStatus(e.adapterSession.status):"N/A"}`);return}if(r(`[ACode] Current status: ${e.adapterSession.status}`),e.adapterSession.status!=="thinking"&&e.adapterSession.status!=="tool_using"){r(`[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.`),r("[ACode] Recovering to waiting_input..."),e.adapterSession.status="waiting_input";const o=e.idleCommands?.idleInputCommand,a=!!(o&&q(o))?{actionType:"idle",actionLabel:"\u76D1\u542C\u6D88\u606F",actionDetail:"aws-mcp/poll_message"}:void 0;if(this.emit("status-change",t,"waiting_input",a),r(`[ACode] \u2705 Recovery complete, status now: ${e.adapterSession.status}`),r("[ACode] \u25B6\uFE0F Arming idle loop or auto-poll..."),!e.autoPollActive&&e.autoPollObservedAnyTool&&!e.autoPollObservedPollingTool){r(`[ACode] User-message turn called work tools; deferring idle rearm in recoverResolvedTurnWithoutTerminalEvent (session: ${t})`),this.scheduleDeferredIdleRearm(t);return}this.armIdleLoopOrAutoPoll(t),r("[ACode] \u2705 Idle loop armed, recovery process complete")}startSubmitTimeoutDetection(t,e,o){this.cancelSubmitTimeoutDetection(e),e.watchdogSubmitStartTime=Date.now(),e.watchdogLastDataFlowTime=Date.now(),k("turn_watchdog_arm",{sessionId:t,source:o,status:e.adapterSession.status,autoPollActive:!!e.autoPollActive,idleToolActiveAt:e.idleToolActiveAt??null}),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&&!this.hasActiveBlockingToolCall(s)&&i-s.autoPollLastActivityAt>=Ot){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 l=i-(s.watchdogLastDataFlowTime||i);if(l>=Mt){const m=String(s.pendingToolEventData?.rawToolName??"");if((s.pendingToolAuthRequests?.size??0)>0){const c=s.pendingToolAuthRequests?.size??0;console.warn(`[ACode] tool_using elapsed ${Math.round(l/1e3)}s but ${c} tool permission request(s) awaiting user decision (session: ${t}), skipping recovery`),s.watchdogSubmitStartTime=i,s.watchdogLastDataFlowTime=i;return}if(m.endsWith("await_complete")){console.warn(`[ACode] tool_using elapsed ${Math.round(l/1e3)}s but await_complete is running (session: ${t}, tool: ${m}), 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(l/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(l/1e3)}s): detached tool ${m} 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",l);return}s.watchdogSubmitStartTime=i;return}if(a!=="thinking")return;const n=i-(s.watchdogSubmitStartTime||i),d=i-(s.watchdogLastDataFlowTime||i);if(Q>0&&d>=Q){console.warn(`[ACode] CRITICAL: Data flow watchdog triggered after ${Math.round(d/1e3)}s (source: ${o}, session: ${t}, status: ${a}). No stream data received. Forcing recovery via recoverTurnFailure.`),this.executeWatchdogRecovery(t,s,o,"data_flow",d);return}if(tt>0&&n>=tt){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}},Dt)}executeWatchdogRecovery(t,e,o,s,a){k("turn_watchdog_trigger",{sessionId:t,source:o,reason:s,elapsedMs:a,status:e.adapterSession.status,autoPollActive:!!e.autoPollActive,idleToolActiveAt:e.idleToolActiveAt??null,pendingTool:e.pendingToolEventData?.rawToolName??null}),r(`[ACode] Watchdog (${s}): calling runtime.abort() after ${Math.round(a/1e3)}s...`);try{e.runtime.abort(),r(`[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,k("turn_watchdog_cancel",{sessionId:t.adapterSession.sessionId,status:t.adapterSession.status,autoPollActive:!!t.autoPollActive,idleToolActiveAt:t.idleToolActiveAt??null})),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()}startLivenessWatchdog(t,e){this.stopLivenessWatchdog(e),e.lastAcodeEventAt=Date.now(),!(B<=0)&&(e.livenessTimer=setInterval(()=>{const o=this.sessions.get(t);if(!o){this.stopLivenessWatchdog(e);return}this.checkSessionLiveness(t,o)},Y),k("liveness_watchdog_arm",{sessionId:t,stallTimeoutMs:B,pollIntervalMs:Y}))}stopLivenessWatchdog(t){t.livenessTimer&&(clearInterval(t.livenessTimer),t.livenessTimer=void 0)}checkSessionLiveness(t,e){if(this.isTerminalStatus(e.adapterSession.status)){this.stopLivenessWatchdog(e);return}if(e.adapterSession.status!=="waiting_input"||e.autoPollActive||e.idleListeningIntentionallyStopped||e.pendingQuestionToolCallId||(e.pendingToolAuthRequests?.size??0)>0||this.hasActiveBlockingToolCall(e))return;e.idleToolActiveAt!==void 0&&(r(`[ACode] liveness: runtime \u672A\u62A5\u544A\u963B\u585E\u578B\u5DE5\u5177\u5728\u98DE\uFF0C\u6E05\u9664\u6B8B\u7559 idleToolActiveAt \u6807\u8BB0 (session: ${t})`),e.idleToolActiveAt=void 0);const o=e.lastAcodeEventAt??Date.now(),s=Date.now()-o;if(s<B)return;console.warn(`[ACode] CRITICAL: session liveness stall detected \u2014 no runtime event for ${Math.round(s/1e3)}s (session: ${t}, status: waiting_input). Forcing recovery (abort + re-arm listening loop).`),k("liveness_stall_detected",{sessionId:t,stalledForMs:s,status:e.adapterSession.status,idleToolActiveAt:e.idleToolActiveAt??null}),this.recoverIdleStall(t,e,s);const a=this.sessions.get(t);a&&(a.lastAcodeEventAt=Date.now())}recoverIdleStall(t,e,o){try{e.runtime.abort()}catch(s){console.warn(`[ACode] liveness recovery: runtime.abort() threw: ${s instanceof Error?s.message:String(s)}`)}this.cancelScheduledAutoPoll(e),e.autoPollActive=!1,e.idleToolActiveAt=void 0,this.isTerminalStatus(e.adapterSession.status)||(e.adapterSession.status="waiting_input",this.armIdleLoopOrAutoPoll(t)),k("liveness_recovery",{sessionId:t,stalledForMs:o,rearmedStatus:e.adapterSession.status}),console.warn(`[ACode] liveness recovery complete: session ${t} re-armed listening loop after ${Math.round(o/1e3)}s stall`)}hasActiveBlockingToolCall(t){const e=t.runtime.hasActiveBlockingToolCall;if(typeof e=="function")try{return e.call(t.runtime)===!0}catch(o){r(`[ACode] hasActiveBlockingToolCall probe threw, falling back to idle marker: ${o instanceof Error?o.message:String(o)}`)}return t.idleToolActiveAt!==void 0}formatAiRequestActionDetail(t){const e=`
|
|
1
|
+
import{EventEmitter as nt}from"node:events";import rt from"node:fs/promises";import H from"node:path";import{pathToFileURL as lt}from"node:url";import{isMcpGroupKey as ut}from"@agentswork/acode";import{v4 as x}from"uuid";import{getBridgeInstancePluginsDir as dt,getBridgeInstanceSkillsDir as ct,getBridgeTemplateConfigFile as v,getBridgeTemplateSkillsDir as pt}from"../config.js";import{getReleasedAcodeEntryPath as mt}from"../services/acode-package.js";import{syncAgentSkillFarm as K}from"../services/agent-capability-sync.js";import{agentPtyManager as ft}from"../services/agent-pty-manager.js";import{getBrowserTools as R,closeBrowserSession as gt,registerListenerWakeHook as ht,unregisterListenerWakeHook as j}from"../services/browser-session-manager.js";import{getDesktopTools as M,getDesktopToolsIfReady as Tt}from"../services/desktop-mcp-manager.js";import{redactForLog as Q}from"../services/instance-ai-config-service.js";import{BROWSER_FEATURE_KEY as I,DESKTOP_FEATURE_KEY as P,getAgentToolPermissions as At,getFeatureState as U,isFeatureEnabled as yt,resolveAgentToolPermissions as St,resolveGroupFeatureKey as bt}from"../services/instance-features.js";import{pluginManager as O}from"../services/plugin-manager.js";import{dumpInvalidProviderRequest as _t}from"../services/request-invalid-dump.js";import{buildRuntimeResourcesSnapshot as Ct}from"../services/runtime-resources-snapshot.js";import{subAgentManager as kt}from"../services/sub-agent-manager-instance.js";import{recordAgentFileChange as wt}from"../services/workspaceTaskChangeWatcher.js";import{getInstanceAiConfigDebugLogger as F}from"../utils/instance-ai-config-debug-logger.js";import{recordLifecycleEvent as k}from"../utils/lifecycle-log.js";import{isMessagePollingIdleCommand as q,isPollMessageToolDescriptor as Pt}from"./acode-tool-names.js";import{IdlePollLoop as $t}from"./idle-poll-loop.js";import{resolveAcodeProviderConfig as Et}from"./instance-ai-config-resolver.js";import{MESSAGE_POLLING_IDLE_PROMPT as G}from"./prompts.js";import{getCanonicalMcpDetail as z,getToolActionInfo as xt}from"./types.js";const It=process.env.ACODE_COMPACTION_DEBUG==="1";function r(...u){It&&console.log(...u)}const Lt=process.env.ACODE_TOKEN_DEBUG==="1";function w(...u){Lt&&console.log("[TokenDebug][Adapter]",...u)}const Dt=G,Mt=5e3;function $(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 J=$("ACODE_DATA_FLOW_WATCHDOG_MS",12e4),Ot=5*6e4,vt=$("ACODE_STUCK_AUTOPOLL_TIMEOUT_MS",5*6e4),Y=$("ACODE_LIVENESS_POLL_INTERVAL_MS",15e3),B=$("ACODE_LIVENESS_STALL_TIMEOUT_MS",10*6e4),Rt=250,Ut=1e3,Ft=$("ACODE_DEFERRED_IDLE_REARM_MS",3e3),V=[2e3,3e3,1e4,4e4],X=4e3;function Z(u){const t=String(u||"").trim();if(t)return t.length>X?`${t.slice(0,X)}\u2026(truncated)`:t}function qt(u){const t=u.toLowerCase();return/tool[_ ]?call/.test(t)||t.includes("invalid_request")?!0:/(?:failed:\s*|http[\s/]*|status[\s:="']*|code[\s:="']*)(400|401|403|404|422)(?!\d)/.test(t)}const N={[I]:"browser_",[P]:"desktop_"};function Bt(u){if(!u||typeof u!="object")return;const t=u,e=typeof t.exposedName=="string"&&t.exposedName||typeof t.toolName=="string"&&t.toolName||typeof t.name=="string"&&t.name||"";if(!e)return;const o=typeof t.execute=="function"?t.execute:void 0;return{name:e,...typeof t.description=="string"?{description:t.description}:{},...t.inputSchema!==void 0?{inputSchema:t.inputSchema}:{},definition:t,...o?{execute:o}:{}}}const tt=$("ACODE_SUBMIT_TIMEOUT_MS",12e4),et=3e3,Nt=G;function Wt(){return H.resolve(mt())}function Ht(u){return lt(H.resolve(u)).href}const ot=128e3,E={"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 ot;const t=u.toLowerCase().trim(),e=E[t];if(e)return e.contextLimit;const o=Object.keys(E).filter(i=>t.startsWith(i)).sort((i,a)=>a.length-i.length),s=o[0]!==void 0?E[o[0]]:void 0;return s?s.contextLimit:ot}const st=4096;function jt(u){if(!u)return st;const t=u.toLowerCase().trim(),e=E[t];if(e)return e.maxOutput;const o=Object.keys(E).filter(i=>t.startsWith(i)).sort((i,a)=>a.length-i.length),s=o[0]!==void 0?E[o[0]]:void 0;return s?s.maxOutput:st}function it(u){if(!u||typeof u!="object")return;const t=u,e=y(t.inputTokens,t.input_tokens,t.promptTokens,t.prompt_tokens),o=y(t.outputTokens,t.output_tokens,t.completionTokens,t.completion_tokens);if(e===0&&o===0)return;let s=y(t.cacheHitTokens,t.promptCacheHitTokens,t.prompt_cache_hit_tokens),i=y(t.cacheMissTokens,t.promptCacheMissTokens,t.prompt_cache_miss_tokens),a=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&&i===0){const n=y(t.cache_read_input_tokens),d=y(t.cache_creation_input_tokens);if(n>0||d>0){const m=t.input_tokens!==void 0&&Number.isFinite(Number(t.input_tokens))&&Number(t.input_tokens)>=0?y(t.input_tokens):Math.max(0,e-n-d);s=n,i=d+m,a=!0}else s=y(t.cache_hit_tokens),i=y(t.cache_miss_tokens),a=a||t.cache_hit_tokens!==void 0||t.cache_miss_tokens!==void 0}if(s===0&&i===0){const n=y(t.prompt_tokens_details?.cached_tokens);n>0&&(s=n,i=e>n?e-n:0,a=!0)}return{inputTokens:e,outputTokens:o,...a?{cacheHitTokens:s,cacheMissTokens:i}:{},...a?{hasCache:!0}:{}}}function y(...u){for(const t of u){const e=Number(t);if(Number.isFinite(e)&&e>0)return e}return 0}function Qt(u){return u==="stderr"||u==="mixed"?u:"stdout"}function L(u){const t=Number(u);return Number.isFinite(t)?t:0}function W(u){if(u==null)return;const t=Number(u);return Number.isFinite(t)?t:void 0}function Gt(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 zt(u){return u.failed===!0}function at(u,t,e){if(!u)return e?`${t}/${e}`:t;const o=`${t}__`;return u.startsWith(o)?z(`${t}__${u.slice(o.length)}`):z(u.replace("/","__"))}function Jt(u){return u==="read_file"||u==="edit_file"||u==="write_file"||u==="bash"}function Yt(u){const t=Vt(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 Vt(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 we extends nt{constructor(){super(),this.providerId="acode",this.displayName="ACode",this.sessions=new Map,this.expandedBuiltInCapabilities=new Map,this.builtInCapabilityToolCache=new Map,this.listenerWakeHooks=new Map,O.setOnPluginsChanged(t=>{this.syncPluginCommands(t)})}async syncPluginCommands(t){try{const e=await O.getPluginCommands(t);for(const o of this.sessions.values())o.config.agentId===t&&(o.runtime.addPluginCommands?.(e),o.runtime.syncPluginGroups?.())}catch(e){r(`[acode-adapter] syncPluginCommands failed for agent ${t}:`,e.message)}}async startSession(t,e){const o=e.mcpConfigPath||v(),{resolved:s,configContextLimit:i,supportsImage:a}=await this.resolveAcodeProvider(e,o),n=s.model,d=i??Kt(n),l=jt(n),m={sessionId:t,status:"starting",messages:[],createdAt:new Date().toISOString(),totalUsage:{inputTokens:0,outputTokens:0,contextLimit:d,maxOutput:l,cacheHitTokens:0,cacheMissTokens:0}};this.sessions.set(t,{adapterSession:m,config:e,runtime:await this.createRuntime(t,n,e,s,a),autoPollActive:!1,retryAttempt:0,retryActive:!1,retryEpoch:0}),this.emit("status-change",t,"starting");const c=this.sessions.get(t);if(!c)throw new Error("ACode session was not initialized");this.startLivenessWatchdog(t,c);const p=()=>{const f=this.sessions.get(t);f&&(f.autoPollDelayMs=void 0,this.getIdlePollLoop(f).start())};this.listenerWakeHooks.set(t,p),ht(e.agentId,p);try{if(await c.runtime.start(),console.log(`[HIBERNATE-REPLAY] startSession: agentId=${e.agentId??"?"} resumeTranscript=${Array.isArray(c.config.resumeTranscript)?`${c.config.resumeTranscript.length}\u6761`:"\u65E0"} importTranscript\u652F\u6301=${typeof c.runtime.importTranscript=="function"}`),m.status="waiting_input",this.emit("status-change",t,"waiting_input",{usage:c.adapterSession.totalUsage}),c.config.resumeTranscript&&c.runtime.importTranscript)try{const f=await c.runtime.importTranscript(c.config.resumeTranscript);console.log(`[HIBERNATE-REPLAY] importTranscript \u5B8C\u6210: agentId=${e.agentId??"?"} \u91CD\u653E=${f}\u6761 conversation=${c.runtime.exportConversation?.().length??"?"}\u6761`),f>0&&c.adapterSession.messages.push({id:x(),sessionId:t,role:"assistant",content:`[\u4F11\u7720\u6062\u590D] \u5DF2\u91CD\u653E\u4F11\u7720\u524D\u7684 ${f} \u6761\u5BF9\u8BDD\u8BB0\u5F55\uFF0C\u4E0A\u4E0B\u6587\u5DF2\u63A5\u7EED\u3002`,timestamp:new Date().toISOString()})}catch(f){console.error(`[HIBERNATE-REPLAY] importTranscript \u5931\u8D25\uFF08\u964D\u7EA7\u4E3A\u6458\u8981\u901A\u9053\uFF09: agentId=${e.agentId??"?"}`,f instanceof Error?f.stack:f)}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 T=this.sessions.get(t);throw T?.capabilitiesFallbackTimer&&clearTimeout(T.capabilitiesFallbackTimer),T&&this.stopLivenessWatchdog(T),this.sessions.delete(t),j(e.agentId,this.listenerWakeHooks.get(t)),this.listenerWakeHooks.delete(t),f}}async sendMessage(t,e){const o=Date.now();r("[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"),r("[ACode] \u25B6\uFE0F sendMessage STARTED"),r(`[ACode] Session: ${t}`),r(`[ACode] Message: ${e.slice(0,100)}${e.length>100?"...":""}`),r("[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),i=s.adapterSession.status;r(`[ACode] Previous status: ${i}`),this.cancelScheduledAutoPoll(s),s.failedTurnRecoveryScheduled=!1,s.idlePollLoop?.stop(),s.idleListeningIntentionallyStopped=!1,this.cancelRequestRetry(s),s.retryAttempt=0,s.retryCircuitBroken=!1,s.retryEpoch+=1,s.turnModelRequestSucceeded=!1;const a={id:x(),sessionId:t,role:"user",content:e,timestamp:new Date().toISOString()};s.adapterSession.messages.push(a),this.emit("conversation-message",t,a),r(`[ACode] Changing status: ${i} \u2192 thinking`),s.adapterSession.status="thinking",this.emit("status-change",t,"thinking"),s.autoPollObservedAssistantText=!1,s.autoPollObservedAnyTool=!1,s.autoPollObservedPollingTool=!1,s.lastSubmittedPrompt=e,s.retryEpoch+=1,s.turnModelRequestSucceeded=!1,this.startSubmitTimeoutDetection(t,s,"sendMessage");try{r("[ACode] \u25B6\uFE0F Calling runtime.submit()...");const n=Date.now();await s.runtime.submit(e);const d=Date.now()-n;this.cancelSubmitTimeoutDetection(s),r(`[ACode] \u2705 runtime.submit() completed in ${d}ms`),r(`[ACode] Current status after submit: ${s.adapterSession.status}`),r("[ACode] \u25B6\uFE0F Calling recoverResolvedTurnWithoutTerminalEvent()..."),this.recoverResolvedTurnWithoutTerminalEvent(t),r(`[ACode] Status after recovery: ${s.adapterSession.status}`);const l=Date.now()-o;r("[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"),r(`[ACode] \u2705 sendMessage COMPLETED in ${l}ms`),r("[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 d=Date.now()-o;console.error(`[ACode] \u274C sendMessage FAILED after ${d}ms:`,n instanceof Error?n.message:String(n)),this.cancelSubmitTimeoutDetection(s),r("[ACode] \u25B6\uFE0F sendMessage failed, scheduling request retry..."),this.emitRuntimeErrorEvent(t,n),this.scheduleRequestRetry(t,"sendMessage"),r(`[ACode] Status after failure: ${s.adapterSession.status}`)}}async sendConfirmation(t,e){}submitToolPermissionDecision(t,e,o){const s=this.sessions.get(t);if(!s)return!1;s.pendingToolAuthRequests?.delete(e);const i=s.runtime.submitToolPermissionDecision?.(e,o)??!1;return i&&this.startSubmitTimeoutDetection(t,s,"submitToolPermissionDecision"),i}getPendingToolAuthRequests(t){const e=this.sessions.get(t);return e?.pendingToolAuthRequests?Array.from(e.pendingToolAuthRequests.entries()).map(([o,s])=>({requestId:o,capability:s.capability,detail:s.detail,requestedAt:s.requestedAt})):[]}async sendQuestionAnswer(t,e){const o=this.sessions.get(t);if(!o)return;const s=o.pendingQuestionToolCallId;if(!s){r(`[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 cancelQuestionAnswer(t,e){const o=this.sessions.get(t);if(!o)return;const s=o.pendingQuestionToolCallId;if(!s){r(`[AcodeSdkAdapter] cancelQuestionAnswer: no pending question for session ${t}`);return}if(!o.runtime.cancelQuestionAnswer)throw new Error("ACode runtime does not support cancelling a question");const i=o.runtime.cancelQuestionAnswer(s,e);o.pendingQuestionToolCallId=void 0,o.pendingQuestions=void 0,r(`[AcodeSdkAdapter] cancelQuestionAnswer: session=${t}, toolCallId=${s}, settled=${i}, hasReason=${!!String(e||"").trim()}`),this.startSubmitTimeoutDetection(t,o,"cancelQuestionAnswer")}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.idleListeningIntentionallyStopped=!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.usageInputEstimated=!1,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)}compactContext(t){const e=this.requireSession(t);if(!e.runtime.compactContext)throw new Error("ACode runtime does not support manual context compaction");return e.runtime.compactContext()}async terminateSession(t){const e=this.sessions.get(t);if(!e)return;this.cancelScheduledAutoPoll(e),e.failedTurnRecoveryScheduled=!1,e.idlePollLoop?.stop(),this.stopLivenessWatchdog(e),this.cancelRequestRetry(e),e.capabilitiesFallbackTimer&&(clearTimeout(e.capabilitiesFallbackTimer),e.capabilitiesFallbackTimer=void 0),await e.runtime.stop();const o=e.config.agentId;o&&(j(o,this.listenerWakeHooks.get(t)),gt(o)),this.listenerWakeHooks.delete(t),e.adapterSession.status="terminated",this.sessions.delete(t),o&&![...this.sessions.values()].some(s=>s.config.agentId===o)&&(this.expandedBuiltInCapabilities.delete(o),this.builtInCapabilityToolCache.delete(o)),this.emit("status-change",t,"terminated")}getConversation(t){return this.sessions.get(t)?.adapterSession.messages??[]}exportRawTranscript(t){const e=this.sessions.get(t);if(e?.runtime.exportConversation)try{const o=e.runtime.exportConversation();return Array.isArray(o)?o:void 0}catch{return}}async importRawTranscript(t,e){const o=this.sessions.get(t);return!o?.runtime.importTranscript||!Array.isArray(e)?0:o.runtime.importTranscript(e)}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}getTotalUsage(t){const e=this.sessions.get(t)?.adapterSession.totalUsage;if(e)return{inputTokens:e.inputTokens,outputTokens:e.outputTokens}}notifyForceMessage(t){const e=this.sessions.get(t);return e?.runtime?.notifyForceMessage?(e.autoPollDelayMs=void 0,e.runtime.notifyForceMessage(),!0):!1}getCapabilities(t){return this.sessions.get(t)?.lastCombinedCapabilities}async resolveAgentAiInfo(t){try{const e=[...this.sessions.values()].find(a=>a.config.agentId===t);if(!e)return;const o=e.config.mcpConfigPath||v(),{resolved:s,supportsImage:i}=await this.resolveAcodeProvider(e.config,o);return s?.model?{model:s.model,supportsImage:i===!0,...s.baseURL?{baseURL:s.baseURL}:{},...s.apiKey?{apiKey:s.apiKey}:{}}:void 0}catch{return}}resolveAgentSkillsDir(t){if(t){try{const e=K(t);if(e)return e}catch(e){r(`[acode-adapter] skill farm sync failed for agent ${t}:`,e.message)}return ct(t)}return pt()}async applyAgentFeatures(t){if(!t)return;const e=this.shouldInjectCapabilityTools(t,P),o=this.shouldInjectCapabilityTools(t,I);for(const[i,a]of this.sessions){if(a.config.agentId!==t)continue;const n=a.runtime,d=e,l=o;try{if(d){const m=await M(t,await this.resolveAgentAiInfo(t)),c=n.addBuiltInTools?.(m)??0;c>0&&r(`[acode-adapter] session ${i}: ${c} desktop tools hot-added for agent ${t}`)}else{const m=n.removeBuiltInToolsByPrefix?.("desktop_")??0;m>0&&r(`[acode-adapter] session ${i}: ${m} desktop tools hot-removed for agent ${t}`)}}catch(m){r(`[acode-adapter] session ${i}: desktop feature hot-sync failed for agent ${t}:`,m.message)}if(l)try{const m=await R(t,a.config.scopeKey,typeof a.config.browserAllowPrivate=="boolean"?{allowPrivate:a.config.browserAllowPrivate}:void 0),c=n.addBuiltInTools?.(m)??0;c>0&&r(`[acode-adapter] session ${i}: ${c} browser tools hot-added for agent ${t}`)}catch(m){r(`[acode-adapter] session ${i}: browser feature hot-sync failed for agent ${t}:`,m.message)}else{const m=n.removeBuiltInToolsByPrefix?.("browser_")??0;m>0&&r(`[acode-adapter] session ${i}: ${m} browser tools hot-removed for agent ${t}`)}}this.syncMcpToolsForAgent(t);try{K(t)}catch(i){r(`[acode-adapter] skill farm hot-sync failed for agent ${t}:`,i.message)}try{await O.applyCapabilities(t)}catch(i){r(`[acode-adapter] plugin capability hot-sync failed for agent ${t}:`,i.message)}const s=St(t);for(const[i,a]of this.sessions)if(a.config.agentId===t)try{a.runtime.setToolPermissionPolicy?.(s)}catch(n){r(`[acode-adapter] session ${i}: tool permission policy hot-sync failed for agent ${t}:`,n.message)}}syncMcpToolsForAgent(t){if(t){for(const[e,o]of this.sessions)if(o.config.agentId===t)try{o.runtime.requestMcpToolsRefresh?.()}catch(s){r(`[acode-adapter] session ${e}: mcp tools refresh failed for agent ${t}:`,s.message)}}}async debugMountMcpServer(t,e,o){if(!t)return{ok:!1,mounted:!1,sessions:0,tools:0,error:"agentId is required"};let s=0,i=0,a,n;for(const[d,l]of this.sessions)if(l.config.agentId===t&&typeof l.runtime.addMcpServer=="function")try{const m=await l.runtime.addMcpServer(e,o);s+=1,m.ok?(i=m.tools,a=m.toolNames):n=m.error}catch(m){n=m.message,r(`[acode-adapter] session ${d}: debug mount mcp ${e} failed for agent ${t}:`,n)}return s===0?{ok:!1,mounted:!1,sessions:0,tools:0,error:`No active SDK session for agentId "${t}"\uFF08\u8C03\u8BD5\u6302\u8F7D\u4EC5\u5BF9\u8FD0\u884C\u4E2D\u7684\u4F1A\u8BDD\u751F\u6548\uFF09`}:{ok:!n,mounted:!0,sessions:s,tools:i,toolNames:a,error:n}}async debugUnmountMcpServer(t,e){if(!t)return{ok:!1,sessions:0};let o=0;for(const[,s]of this.sessions)if(s.config.agentId===t&&typeof s.runtime.removeMcpServer=="function")try{await s.runtime.removeMcpServer(e),o+=1}catch(i){r(`[acode-adapter] debug unmount mcp ${e} failed for agent ${t}:`,i.message)}return{ok:o>0,sessions:o}}getMcpServerStderr(t,e,o=100){if(!t)return[];for(const[,s]of this.sessions)if(s.config.agentId===t&&typeof s.runtime.getMcpServerStderr=="function")return s.runtime.getMcpServerStderr(e,o);return[]}shouldInjectCapabilityTools(t,e){return t?U(t,e)==="expanded":!0}resolveCapabilityToolPrefix(t){return N[String(t??"").trim()]}async loadCapabilityToolsForSession(t,e,o){const s=t===I?await R(e,o.config.scopeKey,typeof o.config.browserAllowPrivate=="boolean"?{allowPrivate:o.config.browserAllowPrivate}:void 0):await M(e,await this.resolveAgentAiInfo(e)),i=[];for(const a of s){const n=Bt(a);n&&i.push(n)}return i}async setBuiltInCapabilityTools(t,e,o){const s=String(t??"").trim(),i=this.resolveCapabilityToolPrefix(e);if(!s||!i)return{sessions:0,tools:0};const a=[...this.sessions.entries()].filter(([,l])=>l.config.agentId===s);if(a.length===0)return{sessions:0,tools:0};if(o==="collapse"){let l=0;for(const[m,c]of a){const p=c.runtime.removeBuiltInToolsByPrefix?.(i)??0;l+=p,p>0&&r(`[acode-adapter] session ${m}: ${p} ${e} tools removed on collapse (agent ${s})`)}return this.expandedBuiltInCapabilities.get(s)?.delete(e),this.builtInCapabilityToolCache.get(s)?.delete(e),r(`[acode-adapter] capability collapse: agent=${s} capability=${e} sessions=${a.length} removedTools=${l}`),{sessions:a.length,tools:l}}const n=new Map;for(const[l,m]of a){let c;try{c=await this.loadCapabilityToolsForSession(e,s,m)}catch(p){throw r(`[acode-adapter] session ${l}: capability ${e} tool load failed for agent ${s}:`,p.message),p}for(const p of c)n.has(p.name)||n.set(p.name,p)}const d=this.expandedBuiltInCapabilities.get(s)??new Set;return d.add(e),this.expandedBuiltInCapabilities.set(s,d),this.builtInCapabilityToolCache.set(s,n),r(`[acode-adapter] capability expand: agent=${s} capability=${e} sessions=${a.length} tools=${n.size} (manifests only, no session tool injection)`),{sessions:a.length,tools:n.size,manifests:[...n.values()].map(l=>({name:l.name,...l.description!==void 0?{description:l.description}:{},...l.inputSchema!==void 0?{inputSchema:l.inputSchema}:{}}))}}async callBuiltInCapabilityTool(t,e,o,s){const i=String(t??"").trim(),a=this.resolveCapabilityToolPrefix(e);if(!a)return{ok:!1,error:`\u672A\u77E5\u80FD\u529B\u300C${String(e)}\u300D\uFF1A\u4EC5\u652F\u6301 browser / desktop`};const n=String(o??"").trim();if(!n)return{ok:!1,error:"\u5DE5\u5177\u540D\u7F3A\u5931"};if(!n.startsWith(a))return{ok:!1,error:`\u5DE5\u5177\u300C${n}\u300D\u4E0D\u5C5E\u4E8E\u80FD\u529B\u300C${e}\u300D`};if(i&&U(i,e)==="disabled")return{ok:!1,error:`\u80FD\u529B\u300C${e}\u300D\u5DF2\u7981\u7528\uFF0C\u65E0\u6CD5\u8C03\u5EA6\u8BE5\u5DE5\u5177`};if(!(this.expandedBuiltInCapabilities.get(i)?.has(e)??!1))return{ok:!1,error:`\u80FD\u529B\u300C${e}\u300D\u5C1A\u672A\u5C55\u5F00\uFF0C\u8BF7\u5148\u8C03\u7528 expand_tools \u5C55\u5F00\u540E\u518D\u8C03\u5EA6\u8BE5\u5DE5\u5177`};const l=this.builtInCapabilityToolCache.get(i)?.get(n);return l?typeof l.execute!="function"?{ok:!1,error:`\u5DE5\u5177\u300C${n}\u300D\u4E0D\u53EF\u8C03\u5EA6\uFF08\u7F3A\u5C11 execute \u5B9E\u73B0\uFF09`}:{ok:!0,result:await l.execute.call(l.definition,s??{})}:{ok:!1,error:`\u5DE5\u5177\u300C${n}\u300D\u65E0\u7F13\u5B58\u5B9A\u4E49\uFF0C\u8BF7\u91CD\u65B0\u8C03\u7528 expand_tools \u5237\u65B0`}}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&&q(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 rt.readFile(t,"utf-8"),o=JSON.parse(e),i=o.provider?.default,a=i?.options,n=y(o.contextLimit),d={},l={},m=i?.models;if(m&&typeof m=="object"){for(const[c,p]of Object.entries(m))if(p&&typeof p=="object"){const f=y(p.contextLimit);f>0&&(d[c.trim()]=f);const T=p.modalities?.input,g=Array.isArray(T)&&T.includes("image")||p.supportsImageInput===!0;l[c.trim()]=g===!0}}return{...i?.model?{model:i.model}:{},...a?.baseURL||a?.baseUrl?{baseURL:a?.baseURL||a?.baseUrl}:{},...a?.apiKey?{apiKey:a.apiKey}:{},...n>0?{contextLimit:n}:{},...Object.keys(d).length>0?{modelContextLimits:d}:{},...Object.keys(l).length>0?{modelImageSupport:l}:{}}}catch(e){const o=e instanceof Error?e.message:String(e);return F().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=F();s.log({level:"info",category:"resolve",message:"resolveAcodeProvider \u8F93\u5165",source:"bridge",details:{configModel:t.model??null,configInstanceAiConfig:t.instanceAiConfig?Q(t.instanceAiConfig):null,configPath:e}});const i={...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}:{}},a=await this.loadAcodeProviderSection(e);let n=a.contextLimit;if(!n&&a.modelContextLimits){const l=o||t.instanceAiConfig?.model||a.model;l&&a.modelContextLimits[l]&&(n=a.modelContextLimits[l])}const d=Et(i,a,"acode-default");return s.log({level:"info",category:"resolve",message:"resolveAcodeProvider \u89E3\u6790\u7ED3\u679C",source:"bridge",details:{instanceConfig:Q(i),globalConfigModel:a?.model??null,resolvedModel:d.model,resolvedBaseURL:d.baseURL??null,resolvedApiKey:d.apiKey?"[set]":null,configContextLimit:n,resolvedSource:d.source}}),{resolved:d,configPath:e,perSessionModel:o,configContextLimit:n,supportsImage:a.modelImageSupport?.[d.model]===!0}}async createRuntime(t,e,o,s,i){const a=await this.loadRuntimeConstructor(),n=o.mcpConfigPath||v();let d=[];try{d=await R(o.agentId,o.scopeKey,typeof o.browserAllowPrivate=="boolean"?{allowPrivate:o.browserAllowPrivate}:void 0)}catch(p){r(`[acode-adapter] browser tools injection skipped for agent ${o.agentId}:`,p.message)}let l=[];if(this.shouldInjectCapabilityTools(o.agentId??"",I)&&(l=d),o.agentId&&this.shouldInjectCapabilityTools(o.agentId,P))try{const p=s?.model?{model:s.model,supportsImage:i===!0,...s.baseURL?{baseURL:s.baseURL}:{},...s.apiKey?{apiKey:s.apiKey}:{}}:void 0,f=await M(o.agentId,p);f.length>0&&(l=[...l,...f])}catch(p){r(`[acode-adapter] desktop tools injection skipped for agent ${o.agentId}:`,p.message)}const m=new a({sessionId:t,agentId:o.agentId,workingDirectory:o.workingDirectory,configPath:n,skillsDir:this.resolveAgentSkillsDir(o.agentId),pluginsDir:o.agentId?dt(o.agentId):void 0,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,resumeContext:typeof o.resumeContext=="string"?o.resumeContext:void 0,env:o.envOverrides,subAgentManager:kt,terminalManager:ft,capabilityState:p=>ut(p)?"collapsed":U(o.agentId??"",bt(p)),capabilityToolRelay:o.agentId?{handlesGroup:p=>this.resolveCapabilityToolPrefix(p)!==void 0,handlesTool:p=>Object.values(N).some(f=>p.startsWith(f)),expand:async p=>(await this.setBuiltInCapabilityTools(o.agentId??"",p,"expand")).manifests??[],collapse:async p=>{await this.setBuiltInCapabilityTools(o.agentId??"",p,"collapse")},call:async(p,f)=>{const T=p.startsWith(N[P]??"desktop_")?P:I;return this.callBuiltInCapabilityTool(o.agentId??"",T,p,f)}}:void 0,pluginBridge:o.agentId?O.forAgent(o.agentId):void 0,runtimeResourcesProvider:o.agentId?()=>Ct(o.agentId):void 0,...o.subAgentModel?{subAgentModel:o.subAgentModel}:{},...o.subAgentEffort?{subAgentEffort:o.subAgentEffort}:{},...o.instanceAiConfig?.effort?{effort:o.instanceAiConfig.effort}:{},onFileChange:p=>wt({...p,agentId:o.agentId,workspacePath:o.workingDirectory}),extraBuiltInTools:l,...o.agentId?{toolPermissionPolicy:At(o.agentId)??void 0}:{},subAgentSuiteTools:d,subAgentSuiteToolProvider:this.buildSubAgentSuiteToolProvider(o.agentId)});return F().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:n}}),m.on("event",p=>this.forwardAcodeEvent(p)),m}buildSubAgentSuiteToolProvider(t){return async e=>{if(!t)return[];if(!yt(t,P))return[];if(e.length===0)return Tt();if(!e.some(i=>{const a=i.trim().replace(/[.*]+$/,"");return a==="desktop"||a.startsWith("desktop.")}))return[];const s=await this.resolveAgentAiInfo(t);return M(t,s)}}async loadRuntimeConstructor(){if(this.runtimeConstructor)return this.runtimeConstructor;const t=Wt(),e=await import(Ht(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"),o.autoPollObservedAssistantText=!1,o.autoPollObservedAnyTool=!1,o.autoPollObservedPollingTool=!1,o.lastSubmittedPrompt=e,o.retryEpoch+=1,o.turnModelRequestSucceeded=!1,this.startSubmitTimeoutDetection(t,o,"startInitialPromptTurn"),o.runtime.submit(e).then(()=>{this.cancelSubmitTimeoutDetection(o),this.recoverResolvedTurnWithoutTerminalEvent(t)}).catch(s=>{const i=this.sessions.get(t);i&&(this.cancelSubmitTimeoutDetection(i),i.lastErrorText=s instanceof Error?s.message:String(s),this.emitRuntimeErrorEvent(t,s),this.scheduleRequestRetry(t,"startInitialPromptTurn"))}))}forwardAcodeEvent(t){const e=this.sessions.get(t.sessionId);if(e){if(e.lastAcodeEventAt=Date.now(),e.autoPollActive&&(e.autoPollLastActivityAt=Date.now()),t.type==="assistant_delta"){const o=typeof t.data.text=="string"?t.data.text:"";e.turnModelRequestSucceeded=!0,e.turnModelRequestSucceededEpoch=e.retryEpoch,e.autoPollObservedAssistantText=!0,e.adapterSession.messages.push({id:x(),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:"";e.turnModelRequestSucceeded=!0,e.turnModelRequestSucceededEpoch=e.retryEpoch,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:Qt(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=t.data.lastUsage,s=y(o?.inputTokens),i=y(o?.outputTokens),a=y(o?.cacheHitTokens),n=y(o?.cacheMissTokens),d=!!(o&&(s>0||i>0));let l;d&&(s>0&&(e.adapterSession.totalUsage.inputTokens=s,e.usageInputEstimated=!1),i>0&&(e.adapterSession.totalUsage.outputTokens=i),(o?.cacheHitTokens!==void 0||o?.cacheMissTokens!==void 0)&&(e.adapterSession.totalUsage.cacheHitTokens=a,e.adapterSession.totalUsage.cacheMissTokens=n),l={...e.adapterSession.totalUsage},w(`ai_request lastUsage applied: ${JSON.stringify(o)} -> totalUsage=${JSON.stringify(e.adapterSession.totalUsage)}`)),e.adapterSession.status==="compacting"&&(e.adapterSession.status="thinking"),e.adapterSession.status==="waiting_input"&&(e.adapterSession.status="thinking");const c={actionType:"ai_request",actionLabel:"AI\u8BF7\u6C42",actionDetail:this.formatAiRequestActionDetail(t.data)};l&&(c.usage=l),w(`ai_request handled: estimatedContextTokens=${t.data.estimatedContextTokens??"n/a"} totalUsage=${JSON.stringify(e.adapterSession.totalUsage)} displayUsage=${JSON.stringify(l??null)}`),this.emit("status-change",t.sessionId,e.adapterSession.status,c),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:Gt(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});return}if(t.type==="iteration_usage"){const o=it(t.data);o&&(o.inputTokens>0&&(e.adapterSession.totalUsage.inputTokens=o.inputTokens,e.usageInputEstimated=!1),e.adapterSession.totalUsage.outputTokens=o.outputTokens,o.hasCache&&(e.adapterSession.totalUsage.cacheHitTokens=o.cacheHitTokens,e.adapterSession.totalUsage.cacheMissTokens=o.cacheMissTokens),w(`iteration_usage applied: raw=${JSON.stringify(t.data)} -> totalUsage=${JSON.stringify(e.adapterSession.totalUsage)}`),this.emit("status-change",t.sessionId,e.adapterSession.status,{usage:{...e.adapterSession.totalUsage}}));return}if(t.type==="turn_complete"){const o=it(t.data.usage);if(o){const i=e.adapterSession.totalUsage.inputTokens,n=typeof t.data.usageEstimated=="boolean"?t.data.usageEstimated===!0:i>0&&o.inputTokens<Math.floor(i*.2)&&!o.hasCache&&!e.usageInputEstimated;w(`turn_complete usage: raw=${JSON.stringify(t.data.usage)} parsed=${JSON.stringify(o)} currentInput=${i} threshold20pct=${Math.floor(i*.2)} isFallbackUsage=${n}`),n?o.outputTokens>0&&(e.adapterSession.totalUsage.outputTokens=o.outputTokens):(o.inputTokens>0&&(e.adapterSession.totalUsage.inputTokens=o.inputTokens,e.usageInputEstimated=!1),e.adapterSession.totalUsage.outputTokens=o.outputTokens),o.hasCache&&(e.adapterSession.totalUsage.cacheHitTokens=o.cacheHitTokens,e.adapterSession.totalUsage.cacheMissTokens=o.cacheMissTokens,r(`[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(r(`[ACode] turn_complete event received (session: ${t.sessionId}), previous status: ${s}, failed: ${t.data.failed===!0}, aborted: ${t.data.aborted===!0}`),zt(t.data)){r(`[ACode] Scheduling retry from failed turn_complete (session: ${t.sessionId})`),this.cancelDataFlowWatchdog(e),this.recoverTurnFailure(t.sessionId,e);return}if(t.data.aborted===!0&&(e.autoPollActive||e.retryActive||e.retryTimer)){r(`[ACode] Scheduling retry from aborted turn_complete (session: ${t.sessionId})`),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",k("turn_complete_to_waiting_input",{sessionId:t.sessionId,autoPollActive:!!e.autoPollActive,observedAnyTool:!!e.autoPollObservedAnyTool,observedPollingTool:!!e.autoPollObservedPollingTool,observedAssistantText:!!e.autoPollObservedAssistantText}),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)}`),r(`[ACode] Status changed to waiting_input after turn_complete (session: ${t.sessionId})`),e.autoPollActive&&e.autoPollObservedAssistantText&&!e.autoPollObservedPollingTool&&!e.autoPollObservedAnyTool){e.stopAutoPollAfterCurrentTurn=!0,e.idleListeningIntentionallyStopped=!0,console.warn(`[${this.displayName}] Auto-poll turn produced assistant text without calling any tool; stopping auto-poll rearm for session ${t.sessionId}`);return}if(!e.autoPollActive&&e.autoPollObservedAnyTool&&!e.autoPollObservedPollingTool){r(`[ACode] User-message turn called work tools; deferring idle rearm (no immediate dispatch) for this turn (session: ${t.sessionId})`),this.scheduleDeferredIdleRearm(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==="tool_permission_request"){this.cancelDataFlowWatchdog(e),this.cancelSubmitTimeoutDetection(e);const o=typeof t.data.requestId=="string"?t.data.requestId:"";o&&(e.pendingToolAuthRequests||(e.pendingToolAuthRequests=new Map),e.pendingToolAuthRequests.set(o,{capability:String(t.data.capability||""),detail:{path:t.data.path,command:t.data.command,cwd:t.data.cwd,operation:t.data.operation},requestedAt:Date.now()})),this.emit("tool-permission-request",{sessionId:t.sessionId,requestId:o,capability:String(t.data.capability||""),agentId:e.config.agentId,detail:{path:t.data.path,command:t.data.command,cwd:t.data.cwd,operation:t.data.operation}});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",e.lastErrorText=String(t.data.message||""),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 g=t.data.tools;g.some(A=>Pt(A))||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 S=Array.isArray(t.data.servers)?t.data.servers:[],b=g.map(A=>({name:String(A.name??""),source:String(A.source??""),description:String(A.description??"")})).filter(A=>A.name),C={kind:"mcp",mcpServers:S,mcpTools:b};e.cachedMcpCapabilities=C,e.lastMcpCapabilities=C,e.lastCombinedCapabilities={kind:"combined",mcpServers:S,mcpTools:b,skills:e.lastCombinedCapabilities?.skills??[],skillsDir:e.lastCombinedCapabilities?.skillsDir,skillGroups:e.lastCombinedCapabilities?.skillGroups??[]},r(`[cap-diag] MCP capabilities cached: ${S.length} servers, ${b.length} tools`,{sessionId:t.sessionId,servers:S,toolNames:b.map(A=>A.name)}),e.capabilitiesFallbackTimer&&clearTimeout(e.capabilitiesFallbackTimer),e.capabilitiesFallbackTimer=setTimeout(()=>{const A=e.cachedMcpCapabilities;if(!A)return;const _={...A,skills:[],skillGroups:[]};this.emitProviderEvent(t,"runtime_capabilities",{capabilities:_,actionType:"runtime_capabilities",actionLabel:"\u8FD0\u884C\u65F6\u80FD\u529B",actionDetail:JSON.stringify(_)}),r(`[cap-diag] MCP capabilities emitted via fallback (skill_status not received within ${et}ms)`,{sessionId:t.sessionId,mcpServers:A.mcpServers,mcpToolsCount:A.mcpTools?.length??0}),e.cachedMcpCapabilities=void 0,e.capabilitiesFallbackTimer=void 0},et);return}const o=String(t.data.action??"");if(o==="tool_batch_start"){const g=typeof t.data.batchId=="string"?t.data.batchId:void 0;if(!g){r(`[ACode] \u{1F9E9} tool_batch_start without batchId, ignored (session=${t.sessionId})`);return}const h=typeof t.data.toolCount=="number"?t.data.toolCount:0,S=Array.isArray(t.data.toolNames)?t.data.toolNames.map(b=>String(b??"")).filter(Boolean):[];r(`[ACode] \u{1F9E9} tool_batch_start: batch=${g.slice(0,20)}\u2026, tools=${h}`),this.emitProviderEvent(t,"tool_batch_start",{batchId:g,batchToolCount:h,batchToolNames:S,actionType:"tool_batch",actionLabel:"\u5E76\u884C\u6267\u884C\u5DE5\u5177",actionDetail:S.length>0?S.join(", "):void 0,actionId:g});return}if(o==="tool_batch_metrics"){const g=typeof t.data.batchId=="string"?t.data.batchId:void 0;if(!g){r(`[ACode] \u26A1 tool_batch_metrics without batchId, ignored (session=${t.sessionId})`);return}const h={toolCount:L(t.data.toolCount),parallelism:L(t.data.parallelism),speedup:L(t.data.speedup),wallClockMs:L(t.data.wallClockMs),totalWaitMs:W(t.data.totalWaitMs),contentionCount:L(t.data.contentionCount),failureCount:W(t.data.failureCount),maxConcurrentObserved:W(t.data.maxConcurrentObserved)};r(`[ACode] \u26A1 tool_batch_metrics: batch=${g.slice(0,20)}\u2026, speedup=${h.speedup}x parallelism=${h.parallelism}x wall=${h.wallClockMs}ms contentions=${h.contentionCount} failures=${h.failureCount??"-"}`),this.emitProviderEvent(t,"tool_batch_metrics",{batchId:g,batchMetrics:h,actionType:"tool_batch",actionLabel:"\u5E76\u884C\u6267\u884C\u5DE5\u5177",actionId:g});return}if(o!=="call_tool"&&o!=="tool_result"){r(`[ACode] \u{1F4AC} mcp_status status report ignored (action=${o||"none"}, server=${typeof t.data.server=="string"?t.data.server:"?"}, session=${t.sessionId})`);return}r(`[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",i=typeof t.data.tool=="string"?t.data.tool:"",a=s&&i?`${s}__${i}`:i||s,n=t.data.arguments&&typeof t.data.arguments=="object"&&!Array.isArray(t.data.arguments)?t.data.arguments:void 0,d=xt(a,n);e.autoPollObservedAnyTool=!0,d.actionType==="idle"&&(e.autoPollObservedPollingTool=!0);const l=Jt(d.actionType)?d.actionDetail||at(void 0,s,i):at(d.actionDetail,s,i),m=typeof t.data.toolUseId=="string"?t.data.toolUseId:void 0,c=n?JSON.stringify(n,null,2):void 0,p=typeof t.data.batchId=="string"?t.data.batchId:void 0,f={toolName:l,rawToolName:a,actionType:d.actionType,actionLabel:d.actionLabel,actionDetail:l,...c?{actionInput:c}:{},...n?{toolInput:n}:{},...m?{toolUseId:m,actionId:m}:{},...p?{batchId:p,parentId:p}:{},metadata:{mcpServer:s}};if(t.data.action==="tool_result"){this.emitProviderEvent(t,"tool_use_end",{...f,toolResult:typeof t.data.result=="string"?t.data.result:JSON.stringify(t.data.result??"")}),e.adapterSession.messages.push({id:x(),sessionId:t.sessionId,role:"tool_result",content:typeof t.data.result=="string"?t.data.result:JSON.stringify(t.data.result??""),timestamp:t.timestamp,toolName:a,toolUseId:m,isError:t.data.failed===!0});const g=d.actionType==="idle"&&!Yt(t.data.result)?"waiting_input":"thinking";e.adapterSession.status=g,d.actionType==="idle"&&(e.idleToolActiveAt=void 0),k("tool_use_end",{sessionId:t.sessionId,actionType:d.actionType,tool:a,nextStatus:g,idleToolActiveAtAfter:e.idleToolActiveAt??null}),this.cancelDataFlowWatchdog(e),e.pendingToolEventData=void 0;const h=d.actionType==="idle";this.emit("status-change",t.sessionId,g,h||g==="thinking"?void 0:f);return}const T=d.actionType==="idle"?"waiting_input":"tool_using";e.adapterSession.status=T,d.actionType==="idle"&&(e.idleToolActiveAt=Date.now()),T==="tool_using"&&(this.resetDataFlowWatchdog(t.sessionId,e),e.pendingToolEventData={...f}),e.adapterSession.messages.push({id:x(),sessionId:t.sessionId,role:"tool_use",content:c??"",timestamp:t.timestamp,toolName:a,toolInput:n,toolUseId:m}),this.emitProviderEvent(t,"tool_use_start",f),this.emit("status-change",t.sessionId,T,f);return}if(t.type==="skill_status"){const s=(Array.isArray(t.data.skills)?t.data.skills:[]).map(c=>({name:String(c.name??""),description:typeof c.description=="string"?c.description:void 0,directory:typeof c.directory=="string"?c.directory:void 0})).filter(c=>c.name),i=typeof t.data.skillsDir=="string"?t.data.skillsDir:void 0,n=(Array.isArray(t.data.skillGroups)?t.data.skillGroups:[]).map(c=>{const p=Array.isArray(c.skills)?c.skills:[];return{dir:typeof c.dir=="string"?c.dir:"",exists:c.exists===!0,skills:p.map(f=>({name:String(f.name??""),description:typeof f.description=="string"?f.description:void 0,directory:typeof f.directory=="string"?f.directory:void 0})).filter(f=>f.name)}}).filter(c=>c.dir),d=e.cachedMcpCapabilities??e.lastMcpCapabilities,l=e.cachedMcpCapabilities!==void 0,m={kind:"combined",mcpServers:d?.mcpServers??[],mcpTools:d?.mcpTools??[],skills:s,skillsDir:i,skillGroups:n};this.emitProviderEvent(t,"runtime_capabilities",{capabilities:m,actionType:"runtime_capabilities",actionLabel:"\u8FD0\u884C\u65F6\u80FD\u529B",actionDetail:JSON.stringify(m)}),e.lastCombinedCapabilities=m,r(`[cap-diag] Combined capabilities emitted ${l?"(startup merge)":"(runtime refresh)"}: ${(d?.mcpTools??[]).length} MCP tools, ${s.length} skills`,{sessionId:t.sessionId,mcpServers:d?.mcpServers??[],skillsDir:i}),e.capabilitiesFallbackTimer&&(clearTimeout(e.capabilitiesFallbackTimer),e.capabilitiesFallbackTimer=void 0),e.cachedMcpCapabilities=void 0;return}if(t.type==="compaction_summary"){const o=typeof t.data.text=="string"?t.data.text:"";o&&this.emitProviderEvent(t,"compaction_summary",{text:o});return}if(t.type==="startup_phase"){r(`[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"){r(`[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"){w(`session_started estimate intentionally not displayed as context size: estimatedContextTokens=${t.data.estimatedContextTokens??"n/a"} (waiting for provider usage)`);const o=y(t.data.contextLimit)||void 0,s=y(t.data.maxOutput)||void 0,i=y(t.data.inputLimit)||void 0,a=y(t.data.compactionThreshold)||void 0;let n=!1;o!==void 0&&(e.adapterSession.totalUsage.contextLimit=o,n=!0),s!==void 0&&(e.adapterSession.totalUsage.maxOutput=s,n=!0),i!==void 0&&(e.adapterSession.totalUsage.inputLimit=i,n=!0),a!==void 0&&(e.adapterSession.totalUsage.compactionThreshold=a,n=!0),n&&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,i=s==="start",a=s==="end",n=s==="phase",d=o.parentId,l=o.compactionId;if(o.trigger==="hibernation_replay"){const T=typeof o.replayedMessageCount=="number"?o.replayedMessageCount:void 0,g=o.estimatedTokens;typeof g=="number"&&g>0&&(e.adapterSession.totalUsage.inputTokens=g,e.usageInputEstimated=!0);const h={actionType:"context_compaction",actionLabel:"\u4F11\u7720\u6062\u590D",actionDetail:T?`\u5DF2\u91CD\u653E\u4F11\u7720\u524D\u7684 ${T} \u6761\u5BF9\u8BDD\u8BB0\u5F55\uFF0C\u4E0A\u4E0B\u6587\u5DF2\u63A5\u7EED`:"\u5DF2\u91CD\u653E\u4F11\u7720\u524D\u7684\u5BF9\u8BDD\u8BB0\u5F55\uFF0C\u4E0A\u4E0B\u6587\u5DF2\u63A5\u7EED",...l?{actionId:l}:{},...g?{usage:{...e.adapterSession.totalUsage,inputTokens:g}}:{}};this.emitProviderEvent(t,"context_compaction",h),this.emit("status-change",t.sessionId,e.adapterSession.status,h);return}let c,p;if(i){const T=String(o.sizeKB??o.sizeBeforeKB??"?"),g=String(o.messageCount??o.messageCountBefore??"?"),h=o.estimatedTokens,S=o.actualInputTokens?`input=${o.actualInputTokens}`:"",b=o.actualOutputTokens?`output=${o.actualOutputTokens}`:"",C=o.trigger;c="\u4E0A\u4E0B\u6587\u538B\u7F29\u5F00\u59CB";const A=C==="provider_overflow_error"?"\u6A21\u578B\u8FD4\u56DE\u4E0A\u4E0B\u6587\u8D85\u9650\u4FE1\u53F7":C==="finish_reason_context_overflow"?"\u54CD\u5E94\u4E2D\u7684\u8D85\u9650\u6807\u8BB0":C==="request_body_byte_limit"?"\u8BF7\u6C42\u4F53\u5B57\u8282\u4E0A\u9650":C,_=A?`, \u89E6\u53D1: ${A}`:"";h!==void 0?p=`\u538B\u7F29\u524D: ~${h} tokens, \u6D88\u606F: ${g}\u6761`+(S?`, \u5B9E\u9645 tokens: ${S} ${b}`:"")+_:p=`\u538B\u7F29\u524D: ${T}KB, \u6D88\u606F: ${g}\u6761`+(S?`, \u5B9E\u9645 tokens: ${S} ${b}`:"")+_}else if(n){const T=String(o.phase??""),g=String(o.phaseLabel??"\u538B\u7F29\u9636\u6BB5"),h=String(o.phaseDetail??"");T==="detect"?(c="\u5F00\u59CB\u89E6\u53D1\u54CD\u5E94\u5F0F\u538B\u7F29",p=h||"\u68C0\u6D4B\u5230\u4E0A\u4E0B\u6587\u8D85\u9650\uFF0C\u5373\u5C06\u5F00\u59CB\u538B\u7F29..."):(c=g,p=h)}else{const T=o.tokensBefore,g=o.tokensAfter,h=o.freedTokens,S=String(o.sizeBeforeKB??"?"),b=String(o.sizeAfterKB??"?"),C=String(o.freedKB??"?"),A=String(o.strategy??"?"),_=Number(o.prunedToolMessages??0),D=Number(o.summarizedMessages??0);c="\u538B\u7F29\u5B8C\u6210",T!==void 0&&g!==void 0?p=`\u91CA\u653E: ${h??T-g} tokens, ${T} tokens \u2192 ${g} tokens, \u7B56\u7565: ${A}`+(_?`, \u88C1\u526A\u5DE5\u5177: ${_}\u6761`:"")+(D?`, \u6458\u8981\u5316: ${D}\u6761`:""):p=`\u91CA\u653E: ${C}KB, ${S}KB \u2192 ${b}KB, \u7B56\u7565: ${A}`+(_?`, \u88C1\u526A\u5DE5\u5177: ${_}\u6761`:"")+(D?`, \u6458\u8981\u5316: ${D}\u6761`:"")}i&&(e.adapterSession.status="compacting");const f={actionType:"context_compaction",actionLabel:c,actionDetail:p};if(i&&l)f.actionId=l;else if((n||a)&&l)if(f.parentId=l,n){const T=String(o.phase??"unknown");f.actionId=`${l}-phase-${T}`}else f.actionId=`${l}-end`;n&&d&&!f.parentId&&(f.parentId=d),a&&(e.adapterSession.totalUsage.inputTokens=y(o.tokensAfter),e.adapterSession.totalUsage.outputTokens=0,e.usageInputEstimated=!1,f.usage={...e.adapterSession.totalUsage}),this.emitProviderEvent(t,"context_compaction",f),this.emit("status-change",t.sessionId,"compacting",f);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.autoPollTimer&&(clearTimeout(e.autoPollTimer),e.autoPollTimer=void 0),this.cancelRequestRetry(e),e.retryAttempt=0,e.idleCommands?.idleInputCommand){this.getIdlePollLoop(e).start();return}this.scheduleAutoPoll(t)}}scheduleDeferredIdleRearm(t){const e=this.sessions.get(t);!e||e.autoPollActive||e.autoPollTimer||this.isTerminalStatus(e.adapterSession.status)||this.scheduleAutoPoll(t,Ft)}getIdlePollLoop(t){if(t.idlePollLoop)return t.idlePollLoop;const e=t.adapterSession.sessionId;return t.idlePollLoop=new $t({getStatus:()=>this.sessions.get(e)?.adapterSession.status,getCommand:()=>this.sessions.get(e)?.idleCommands?.idleInputCommand,isPollingCommand:o=>q(o),preDispatchHook:()=>null,dispatchPollingPrompt:(o,s)=>this.submitAutoPollPrompt(e,s?o:Nt,{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 i=(s.autoPollToken??0)+1;s.autoPollToken=i,s.autoPollActive=!0,s.autoPollObservedPollingTool=!1,s.autoPollObservedAssistantText=!1,s.autoPollObservedAnyTool=!1,s.stopAutoPollAfterCurrentTurn=!1,s.idleListeningIntentionallyStopped=!1,s.autoPollQueuedAt=Date.now(),s.autoPollLastActivityAt=Date.now(),s.idleToolActiveAt=void 0,s.lastSubmittedPrompt=e,s.retryEpoch+=1,s.turnModelRequestSucceeded=!1,o?.keepWaitingStatus||(s.adapterSession.status="thinking",this.emit("status-change",t,"thinking")),this.startSubmitTimeoutDetection(t,s,"submitAutoPollPrompt"),s.runtime.submit(e).catch(a=>{this.emitRuntimeErrorEvent(t,a),this.scheduleRequestRetry(t,"submitAutoPollPrompt")}).finally(()=>{const a=this.sessions.get(t);if(a){if(a.autoPollToken!==i){r(`[ACode] submitAutoPollPrompt.finally: token mismatch (my=${i}, current=${a.autoPollToken}), skipping cleanup \u2014 newer turn has taken over`);return}if(this.cancelSubmitTimeoutDetection(a),a.autoPollActive=!1,a.failedTurnRecoveryScheduled||a.autoPollTimer){a.failedTurnRecoveryScheduled=!1;return}if(a.stopAutoPollAfterCurrentTurn){a.stopAutoPollAfterCurrentTurn=!1,a.autoPollObservedPollingTool=!1,a.autoPollObservedAssistantText=!1,a.autoPollObservedAnyTool=!1;return}if(a.adapterSession.status==="error"){this.recoverTurnFailure(t,a);return}if(a.adapterSession.status==="thinking"||a.adapterSession.status==="tool_using"){this.recoverResolvedTurnWithoutTerminalEvent(t);return}a.adapterSession.status==="waiting_input"&&this.armIdleLoopOrAutoPoll(t)}})}scheduleAutoPoll(t,e){const o=this.sessions.get(t);if(!o||o.autoPollActive||o.autoPollTimer||this.isTerminalStatus(o.adapterSession.status))return;const s=e??o.autoPollDelayMs??Rt;e===void 0&&(o.autoPollDelayMs=Math.min(s*2,Ut)),o.autoPollTimer=setTimeout(()=>{const i=this.sessions.get(t);!i||i.autoPollActive||this.isTerminalStatus(i.adapterSession.status)||(i.autoPollTimer=void 0,this.submitAutoPollPrompt(t,Dt,{keepWaitingStatus:!0}))},s)}cancelScheduledAutoPoll(t){t.autoPollDelayMs=void 0,t.autoPollTimer&&(clearTimeout(t.autoPollTimer),t.autoPollTimer=void 0)}scheduleRequestRetry(t,e){const o=this.sessions.get(t);if(!o||this.isTerminalStatus(o.adapterSession.status))return;if(o.retryCircuitBroken){r(`[ACode] scheduleRequestRetry(${e}): retry terminated by non-retryable error, suppress further auto-retry`);return}if(o.retryActive||o.retryTimer)return;if(!o.lastSubmittedPrompt){o.adapterSession.status="error",this.emit("status-change",t,"error");return}if(o.turnModelRequestSucceeded&&o.turnModelRequestSucceededEpoch===o.retryEpoch&&(o.turnModelRequestSucceeded=!1,o.retryAttempt=0),o.lastErrorText&&qt(o.lastErrorText)){r(`[ACode] scheduleRequestRetry(${e}): non-retryable provider error, giving up retry: ${o.lastErrorText.slice(0,200)}`),this.cancelRequestRetry(o);const i=Math.max(1,o.retryAttempt+1);o.retryAttempt=0,o.retryCircuitBroken=!0,o.adapterSession.status="error",_t({sessionId:t,agentId:o.config.agentId,model:o.config.model,attempt:i,errorText:o.lastErrorText,conversation:this.exportRawTranscript(t),extra:{reason:e,status:o.adapterSession.status}}),this.emit("status-change",t,"error",{actionType:"retry_aborted",actionLabel:"\u8BF7\u6C42\u65E0\u6548",actionDetail:"Provider \u8FD4\u56DE 4xx \u8BF7\u6C42\u9519\u8BEF\uFF08\u539F\u6837\u91CD\u8BD5\u5FC5\u7136\u5931\u8D25\uFF09\uFF0C\u5DF2\u505C\u6B62\u81EA\u52A8\u91CD\u8BD5\uFF0C\u8BF7\u68C0\u67E5\u6E20\u9053\u914D\u7F6E\u6216\u91CD\u542F\u4F1A\u8BDD\u3002",actionError:Z(o.lastErrorText)});return}o.retryAttempt+=1,o.retryActive=!0,this.cancelScheduledAutoPoll(o),o.idlePollLoop?.stop();const s=V[Math.min(o.retryAttempt-1,V.length-1)];o.adapterSession.status="error",this.emit("status-change",t,"error",{actionType:"retry",actionLabel:"\u91CD\u8BD5\u4E2D",actionDetail:`\u7B2C${o.retryAttempt}\u6B21 \xB7 ${Math.round(s/1e3)}s\u540E`,actionError:Z(o.lastErrorText)}),r(`[ACode] scheduleRequestRetry(${e}): attempt=${o.retryAttempt} delay=${s}ms`),o.retryTimer=setTimeout(()=>{o.retryTimer=void 0,this.retryFailedRequest(t,e)},s)}retryFailedRequest(t,e){const o=this.sessions.get(t);if(!o)return;if(o.retryTimer=void 0,this.isTerminalStatus(o.adapterSession.status)||!o.lastSubmittedPrompt){o.retryActive=!1;return}o.retryActive=!1;const s=o.lastSubmittedPrompt;r(`[ACode] retryFailedRequest(${e}): attempt=${o.retryAttempt} re-submitting...`),o.retryEpoch+=1,o.turnModelRequestSucceeded=!1,o.autoPollObservedAssistantText=!1,o.autoPollObservedAnyTool=!1,o.autoPollObservedPollingTool=!1,o.adapterSession.status="thinking",this.emit("status-change",t,"thinking",{usage:o.adapterSession.totalUsage}),this.startSubmitTimeoutDetection(t,o,"retryFailedRequest"),o.runtime.submit(s,{resume:!0}).then(()=>{const i=this.sessions.get(t);!i||i.retryTimer||(this.cancelSubmitTimeoutDetection(i),i.retryAttempt=0,i.retryActive=!1,i.retryCircuitBroken=!1,this.recoverResolvedTurnWithoutTerminalEvent(t))}).catch(i=>{const a=this.sessions.get(t);a&&(this.cancelSubmitTimeoutDetection(a),a.lastErrorText=i instanceof Error?i.message:String(i),this.emitRuntimeErrorEvent(t,i),this.scheduleRequestRetry(t,`retry#${a.retryAttempt+1}`))})}cancelRequestRetry(t){t.retryTimer&&(clearTimeout(t.retryTimer),t.retryTimer=void 0),t.retryActive=!1}isTerminalStatus(t){return t==="completed"||t==="terminated"}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.pendingToolAuthRequests?.size&&e.pendingToolAuthRequests.clear(),e.adapterSession.status==="tool_using"&&e.pendingToolEventData){const s=e.pendingToolEventData;r(`[ACode] recoverTurnFailure: \u8865\u53D1 tool_use_end (tool: ${s.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:{...s,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 s=e.adapterSession.totalUsage.outputTokens;e.adapterSession.totalUsage.outputTokens=o,r(`[ACode] recoverTurnFailure: \u4F30\u7B97\u8986\u76D6 output tokens ${s} -> ${o} (totalUsage now: input=${e.adapterSession.totalUsage.inputTokens}, output=${e.adapterSession.totalUsage.outputTokens})`)}this.cancelScheduledAutoPoll(e),this.scheduleRequestRetry(t,"recoverTurnFailure")}recoverResolvedTurnWithoutTerminalEvent(t){r(`[ACode] \u25B6\uFE0F recoverResolvedTurnWithoutTerminalEvent called for session ${t}`);const e=this.sessions.get(t);if(!e||this.isTerminalStatus(e.adapterSession.status)){r(`[ACode] Skipping recovery: entry=${!!e}, isTerminal=${e?this.isTerminalStatus(e.adapterSession.status):"N/A"}`);return}if(r(`[ACode] Current status: ${e.adapterSession.status}`),e.adapterSession.status!=="thinking"&&e.adapterSession.status!=="tool_using"){r(`[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.`),r("[ACode] Recovering to waiting_input..."),e.adapterSession.status="waiting_input";const o=e.idleCommands?.idleInputCommand,i=!!(o&&q(o))?{actionType:"idle",actionLabel:"\u76D1\u542C\u6D88\u606F",actionDetail:"aws-mcp/poll_message"}:void 0;if(this.emit("status-change",t,"waiting_input",i),r(`[ACode] \u2705 Recovery complete, status now: ${e.adapterSession.status}`),r("[ACode] \u25B6\uFE0F Arming idle loop or auto-poll..."),!e.autoPollActive&&e.autoPollObservedAnyTool&&!e.autoPollObservedPollingTool){r(`[ACode] User-message turn called work tools; deferring idle rearm in recoverResolvedTurnWithoutTerminalEvent (session: ${t})`),this.scheduleDeferredIdleRearm(t);return}this.armIdleLoopOrAutoPoll(t),r("[ACode] \u2705 Idle loop armed, recovery process complete")}startSubmitTimeoutDetection(t,e,o){this.cancelSubmitTimeoutDetection(e),e.watchdogSubmitStartTime=Date.now(),e.watchdogLastDataFlowTime=Date.now(),k("turn_watchdog_arm",{sessionId:t,source:o,status:e.adapterSession.status,autoPollActive:!!e.autoPollActive,idleToolActiveAt:e.idleToolActiveAt??null}),e.watchdogTimer=setInterval(()=>{const s=this.sessions.get(t);if(!s){this.cancelSubmitTimeoutDetection(e);return}const i=s.adapterSession.status,a=Date.now();if(i==="waiting_input"){if(s.autoPollActive&&s.autoPollLastActivityAt&&!this.hasActiveBlockingToolCall(s)&&a-s.autoPollLastActivityAt>=vt){console.warn(`[ACode] CRITICAL: stuck auto-poll detected after ${Math.round((a-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",a-s.autoPollLastActivityAt);return}s.watchdogSubmitStartTime=a,s.watchdogLastDataFlowTime=a;return}if(i==="tool_using"){const l=a-(s.watchdogLastDataFlowTime||a);if(l>=Ot){const m=String(s.pendingToolEventData?.rawToolName??"");if((s.pendingToolAuthRequests?.size??0)>0){const c=s.pendingToolAuthRequests?.size??0;console.warn(`[ACode] tool_using elapsed ${Math.round(l/1e3)}s but ${c} tool permission request(s) awaiting user decision (session: ${t}), skipping recovery`),s.watchdogSubmitStartTime=a,s.watchdogLastDataFlowTime=a;return}if(m.endsWith("await_complete")){console.warn(`[ACode] tool_using elapsed ${Math.round(l/1e3)}s but await_complete is running (session: ${t}, tool: ${m}), skipping recovery (sub-agents have their own watchdogs, bg commands have timeout limits)`),s.watchdogSubmitStartTime=a,s.watchdogLastDataFlowTime=a;return}if(console.warn(`[ACode] CRITICAL: tool_using slow timeout triggered after ${Math.round(l/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(l/1e3)}s): detached tool ${m} to background (session: ${t}); waiting for the real tool_result to continue the turn`),s.watchdogSubmitStartTime=a,s.watchdogLastDataFlowTime=a;return}this.executeWatchdogRecovery(t,s,o,"tool_using_slow",l);return}s.watchdogSubmitStartTime=a;return}if(i!=="thinking")return;const n=a-(s.watchdogSubmitStartTime||a),d=a-(s.watchdogLastDataFlowTime||a);if(J>0&&d>=J){console.warn(`[ACode] CRITICAL: Data flow watchdog triggered after ${Math.round(d/1e3)}s (source: ${o}, session: ${t}, status: ${i}). No stream data received. Forcing recovery via recoverTurnFailure.`),this.executeWatchdogRecovery(t,s,o,"data_flow",d);return}if(tt>0&&n>=tt){console.warn(`[ACode] CRITICAL: submit timeout detected after ${Math.round(n/1e3)}s (source: ${o}, session: ${t}, status: ${i}). Forcing recovery to prevent permanent state stuck.`),this.executeWatchdogRecovery(t,s,o,"submit_timeout",n);return}},Mt)}executeWatchdogRecovery(t,e,o,s,i){k("turn_watchdog_trigger",{sessionId:t,source:o,reason:s,elapsedMs:i,status:e.adapterSession.status,autoPollActive:!!e.autoPollActive,idleToolActiveAt:e.idleToolActiveAt??null,pendingTool:e.pendingToolEventData?.rawToolName??null}),r(`[ACode] Watchdog (${s}): calling runtime.abort() after ${Math.round(i/1e3)}s...`);try{e.runtime.abort(),r(`[ACode] Watchdog (${s}): runtime.abort() called`)}catch(a){console.warn(`[ACode] \u26A0\uFE0F Watchdog (${s}): runtime.abort() threw: ${a instanceof Error?a.message:String(a)}`)}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,k("turn_watchdog_cancel",{sessionId:t.adapterSession.sessionId,status:t.adapterSession.status,autoPollActive:!!t.autoPollActive,idleToolActiveAt:t.idleToolActiveAt??null})),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()}startLivenessWatchdog(t,e){this.stopLivenessWatchdog(e),e.lastAcodeEventAt=Date.now(),!(B<=0)&&(e.livenessTimer=setInterval(()=>{const o=this.sessions.get(t);if(!o){this.stopLivenessWatchdog(e);return}this.checkSessionLiveness(t,o)},Y),k("liveness_watchdog_arm",{sessionId:t,stallTimeoutMs:B,pollIntervalMs:Y}))}stopLivenessWatchdog(t){t.livenessTimer&&(clearInterval(t.livenessTimer),t.livenessTimer=void 0)}checkSessionLiveness(t,e){if(this.isTerminalStatus(e.adapterSession.status)){this.stopLivenessWatchdog(e);return}if(e.adapterSession.status!=="waiting_input"||e.autoPollActive||e.idleListeningIntentionallyStopped||e.pendingQuestionToolCallId||(e.pendingToolAuthRequests?.size??0)>0||this.hasActiveBlockingToolCall(e))return;e.idleToolActiveAt!==void 0&&(r(`[ACode] liveness: runtime \u672A\u62A5\u544A\u963B\u585E\u578B\u5DE5\u5177\u5728\u98DE\uFF0C\u6E05\u9664\u6B8B\u7559 idleToolActiveAt \u6807\u8BB0 (session: ${t})`),e.idleToolActiveAt=void 0);const o=e.lastAcodeEventAt??Date.now(),s=Date.now()-o;if(s<B)return;console.warn(`[ACode] CRITICAL: session liveness stall detected \u2014 no runtime event for ${Math.round(s/1e3)}s (session: ${t}, status: waiting_input). Forcing recovery (abort + re-arm listening loop).`),k("liveness_stall_detected",{sessionId:t,stalledForMs:s,status:e.adapterSession.status,idleToolActiveAt:e.idleToolActiveAt??null}),this.recoverIdleStall(t,e,s);const i=this.sessions.get(t);i&&(i.lastAcodeEventAt=Date.now())}recoverIdleStall(t,e,o){try{e.runtime.abort()}catch(s){console.warn(`[ACode] liveness recovery: runtime.abort() threw: ${s instanceof Error?s.message:String(s)}`)}this.cancelScheduledAutoPoll(e),e.autoPollActive=!1,e.idleToolActiveAt=void 0,this.isTerminalStatus(e.adapterSession.status)||(e.adapterSession.status="waiting_input",this.armIdleLoopOrAutoPoll(t)),k("liveness_recovery",{sessionId:t,stalledForMs:o,rearmedStatus:e.adapterSession.status}),console.warn(`[ACode] liveness recovery complete: session ${t} re-armed listening loop after ${Math.round(o/1e3)}s stall`)}hasActiveBlockingToolCall(t){const e=t.runtime.hasActiveBlockingToolCall;if(typeof e=="function")try{return e.call(t.runtime)===!0}catch(o){r(`[ACode] hasActiveBlockingToolCall probe threw, falling back to idle marker: ${o instanceof Error?o.message:String(o)}`)}return t.idleToolActiveAt!==void 0}formatAiRequestActionDetail(t){const e=`
|
|
2
2
|
|
|
3
3
|
\u8BF7\u6C42\u5934:
|
|
4
|
-
`,o=typeof t.model=="string"?t.model:"",s=typeof t.endpoint=="string"?t.endpoint:typeof t.requestUrl=="string"?t.requestUrl:"",
|
|
4
|
+
`,o=typeof t.model=="string"?t.model:"",s=typeof t.endpoint=="string"?t.endpoint:typeof t.requestUrl=="string"?t.requestUrl:"",i=typeof t.requestMethod=="string"?t.requestMethod:"",a=typeof t.stream=="boolean"?t.stream:void 0,n=typeof t.messageCount=="number"?t.messageCount:void 0,d=typeof t.toolCount=="number"?t.toolCount:void 0,l=typeof t.lastUserMessagePreview=="string"?t.lastUserMessagePreview:"",m=[o?`\u6A21\u578B: ${o}`:void 0,s?`\u63A5\u53E3: ${s}`:void 0,i?`\u65B9\u6CD5: ${i}`:void 0,a!==void 0?`\u6D41\u5F0F: ${a?"\u662F":"\u5426"}`:void 0,n!==void 0?`\u4E0A\u4E0B\u6587\u6D88\u606F: ${n}`:void 0,d!==void 0?`\u53EF\u7528\u5DE5\u5177: ${d}`:void 0,l?`\u6700\u540E\u8BF7\u6C42: ${l}`:void 0].filter(h=>!!h),c=/^(authorization|x-api-key|api-key|cookie|set-cookie|x-auth-token|token)$/i,p=t.requestHeaders,f=p?Object.entries(p).filter(([h])=>!c.test(h)).map(([h,S])=>`${h}: ${S}`).filter(h=>h.trim().length>0):[],T=m.join(`
|
|
5
5
|
`)||"ACode \u6B63\u5728\u53D1\u9001 AI \u8BF7\u6C42",g=f.length>0?`${e}${f.join(`
|
|
6
|
-
`)}`:"";return`${T}${g}`}}export{
|
|
6
|
+
`)}`:"";return`${T}${g}`}}export{we as AcodeSdkAdapter,zt as isFailedAcodeTurnComplete,Ht as toAcodeEsmImportSpecifier};
|
|
7
7
|
|
|
@@ -21,6 +21,8 @@ export declare class ClaudeSdkAdapter extends EventEmitter implements BaseProvid
|
|
|
21
21
|
private parseMessageContent;
|
|
22
22
|
sendConfirmation(sessionId: string, accept: boolean): Promise<void>;
|
|
23
23
|
sendQuestionAnswer(sessionId: string, answers: Record<string, string>): Promise<void>;
|
|
24
|
+
|
|
25
|
+
cancelQuestionAnswer(sessionId: string, reason?: string): Promise<void>;
|
|
24
26
|
abortCurrentTurn(sessionId: string): Promise<void>;
|
|
25
27
|
terminateSession(sessionId: string): Promise<void>;
|
|
26
28
|
getConversation(sessionId: string): ConversationMessage[];
|