aws-runtime-bridge 1.9.179 → 1.9.181
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 +61 -0
- package/dist/adapter/AcodeSdkAdapter.d.ts +13 -0
- package/dist/adapter/AcodeSdkAdapter.js +2 -2
- package/dist/adapter/types.d.ts +19 -0
- package/dist/routes/terminal.d.ts +9 -0
- package/dist/routes/terminal.js +25 -25
- package/dist/services/bridge-pairing.js +1 -1
- package/dist/services/user-scope.d.ts +11 -0
- package/dist/services/user-scope.js +1 -1
- package/package/acode/dist/runtime.js +18 -18
- package/package/acode/dist/types.d.ts +15 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,67 @@ files 白名单),供调度中心「查看本次更新内容」弹窗按 `##
|
|
|
5
5
|
展示。发布新版本时须在仓库中先写好 `## v<version>` 段(prepack-guard 校验缺段
|
|
6
6
|
即阻断发布);Bridge 自更新成功后的运行时追加仅作为包内缺段时的兜底。
|
|
7
7
|
|
|
8
|
+
## v1.9.181
|
|
9
|
+
|
|
10
|
+
_发布日期:2026-11-01_
|
|
11
|
+
|
|
12
|
+
### 修复:插件等用户路由 403(agent-ownership-mismatch)
|
|
13
|
+
|
|
14
|
+
`requireUserScope` 的解析优先级纠正:validateToken 已按凭据
|
|
15
|
+
(connectionKey / runtime token)解析出的 `req.userScope` 必须原样保留,
|
|
16
|
+
不再被请求头/体无条件覆盖。此前有两个问题:
|
|
17
|
+
|
|
18
|
+
1. 携带合法凭据、但没带 `X-Tenant-Id` / `X-User-Id` 头的服务端调用
|
|
19
|
+
(如调度中心的插件代理)会被降级成 binding.json 的本机用户
|
|
20
|
+
`{tenantId:"_local"}`,与实例 owner.json 登记的真实归属永不相等,
|
|
21
|
+
`requireAgentOwnership` 一律拒绝——表现为插件面板一打开就报 403。
|
|
22
|
+
2. 更严重的是「凭据决定的权威 scope」可被「请求自称的 scope」替换,
|
|
23
|
+
伪造请求头即可跨 target / 跨租户写入别人的用户命名空间。
|
|
24
|
+
|
|
25
|
+
现在头/体身份仅服务于「无 target 凭据」的本机面板 / MCP 子进程链路,
|
|
26
|
+
凭据解析出的 scope 拥有最高优先级。
|
|
27
|
+
|
|
28
|
+
配套调度中心侧:`PluginProxyController` 发往 bridge 的代理请求补注
|
|
29
|
+
`X-Tenant-Id` / `X-User-Id`(按 agent owner,与 RuntimeBridgeService
|
|
30
|
+
同口径),本机面板/子进程链路不再缺身份头;插件面板错误提示优先透出
|
|
31
|
+
bridge 返回的真实原因,不再被 "Request failed with status code 403"
|
|
32
|
+
之类的 HTTP 概括语吞掉。
|
|
33
|
+
|
|
34
|
+
## v1.9.180
|
|
35
|
+
|
|
36
|
+
_发布日期:2026-11-01_
|
|
37
|
+
|
|
38
|
+
### 功能:累计消耗 token(从 Agent 启动起)全链路
|
|
39
|
+
|
|
40
|
+
此前面板只有「当前上下文」口径的输入/输出 token(覆盖式,压缩/清空会回落),
|
|
41
|
+
没有「从启动到此刻一共烧了多少」的累计口径。本次打通 runtime → adapter →
|
|
42
|
+
调度中心的全链路:
|
|
43
|
+
|
|
44
|
+
1. **acode runtime 累计消耗**:新增 `totalInputTokens` / `totalOutputTokens`
|
|
45
|
+
累计字段(Σ 各次请求 provider 真实上报的 prompt/completion tokens,输入含
|
|
46
|
+
缓存命中),跨迭代、跨 turn 只增不减,压缩/清空不影响;与缓存命中计数同
|
|
47
|
+
口径——只累计真实上报值,文本长度兜底不计入,压缩摘要 LLM 请求(独立
|
|
48
|
+
fetch)不计入。`turn_complete` / `iteration_usage` 的 usage 覆盖式携带累计
|
|
49
|
+
快照,前端无需自行累加。
|
|
50
|
+
2. **休眠唤醒跨快照延续**:休眠导出的 tokenUsage 快照(含累计与缓存四字段)
|
|
51
|
+
由调度中心落库,唤醒启动时经 `resumeTokenUsage` 回灌,runtime `start()`
|
|
52
|
+
重建 state 时以 `config.initialTokenUsage` 为累计初值——唤醒后继续累计而非
|
|
53
|
+
清零。普通启动缺省从 0 起;旧快照(无累计字段)按无 seed 处理,不阻断启动。
|
|
54
|
+
3. **adapter / 终端路由透传**:`toUsage` 逐字段解析累计值(独立于 0/0 丢弃与
|
|
55
|
+
fallback 判定,不参与文本长度兜底);`totalUsage` 字段级 presence 覆盖
|
|
56
|
+
(旧版 runtime 不带累计字段时保留现值,不清零不回落);`resolveStatusChangeUsage`
|
|
57
|
+
在 input/output 为 0(如 seed 后、首个请求前)但累计已有值时也照常传出。
|
|
58
|
+
`getTotalUsage`(休眠导出通道)一并带出累计与缓存快照。
|
|
59
|
+
|
|
60
|
+
配套调度中心侧:状态回调透传累计字段、AgentContextPanel 新增「累计消耗」区块、
|
|
61
|
+
休眠快照表补列(cache_hit/miss + total_input/output tokens)。
|
|
62
|
+
|
|
63
|
+
### 修复:唤醒请求的累计 token seed 解析
|
|
64
|
+
|
|
65
|
+
`parseResumeTokenUsage`(与 `parseResumeTranscript` 同模式)只接受四个累计字段,
|
|
66
|
+
非法/缺失字段丢弃、全部非法返回 undefined(累计从 0 起,不阻断启动),
|
|
67
|
+
JSON 文本异常不会让唤醒流程失败。
|
|
68
|
+
|
|
8
69
|
## v1.9.179
|
|
9
70
|
|
|
10
71
|
_发布日期:2026-10-27_
|
|
@@ -118,6 +118,13 @@ type ACodeRuntimeConstructor = new (config: {
|
|
|
118
118
|
memory?: string;
|
|
119
119
|
|
|
120
120
|
resumeContext?: string;
|
|
121
|
+
|
|
122
|
+
initialTokenUsage?: {
|
|
123
|
+
totalInputTokens?: number;
|
|
124
|
+
totalOutputTokens?: number;
|
|
125
|
+
cacheHitTokens?: number;
|
|
126
|
+
cacheMissTokens?: number;
|
|
127
|
+
};
|
|
121
128
|
env?: Record<string, string>;
|
|
122
129
|
subAgentManager?: SubAgentManager;
|
|
123
130
|
|
|
@@ -290,9 +297,15 @@ export declare class AcodeSdkAdapter extends EventEmitter implements BaseProvide
|
|
|
290
297
|
|
|
291
298
|
|
|
292
299
|
|
|
300
|
+
|
|
301
|
+
|
|
293
302
|
getTotalUsage(sessionId: string): {
|
|
294
303
|
inputTokens?: number;
|
|
295
304
|
outputTokens?: number;
|
|
305
|
+
totalInputTokens?: number;
|
|
306
|
+
totalOutputTokens?: number;
|
|
307
|
+
cacheHitTokens?: number;
|
|
308
|
+
cacheMissTokens?: number;
|
|
296
309
|
} | undefined;
|
|
297
310
|
|
|
298
311
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import{EventEmitter as it}from"node:events";import at from"node:fs/promises";import W from"node:path";import{pathToFileURL as nt}from"node:url";import{isMcpGroupKey as rt}from"@agentswork/acode";import{v4 as x}from"uuid";import{getBridgeInstancePluginsDir as lt,getBridgeInstanceSkillsDir as ut,getBridgeTemplateConfigFile as dt,getBridgeTemplateSkillsDir as ct}from"../config.js";import{getReleasedAcodeEntryPath as pt}from"../services/acode-package.js";import{syncAgentSkillFarm as H}from"../services/agent-capability-sync.js";import{getAgentOwner as mt}from"../services/agent-ownership.js";import{agentPtyManager as ft}from"../services/agent-pty-manager.js";import{getBrowserTools as M,closeBrowserSession as gt,registerListenerWakeHook as ht,unregisterListenerWakeHook as K}from"../services/browser-session-manager.js";import{getDesktopTools as O,getDesktopToolsIfReady as Tt}from"../services/desktop-mcp-manager.js";import{redactForLog as j}from"../services/instance-ai-config-service.js";import{BROWSER_FEATURE_KEY as I,DESKTOP_FEATURE_KEY as P,getAgentToolPermissions as At,getFeatureState as R,isFeatureEnabled as yt,resolveAgentToolPermissions as St,resolveGroupFeatureKey as bt}from"../services/instance-features.js";import{resolveOpenDocEvent as _t}from"../services/open-doc-events.js";import{closeOpenDocument as Ct,clearOpenDocuments as kt,recordOpenDocument as wt,removeOpenDocument as Pt}from"../services/open-doc-registry.js";import{pluginManager as v}from"../services/plugin-manager.js";import{dumpInvalidProviderRequest as Et}from"../services/request-invalid-dump.js";import{buildRuntimeResourcesSnapshot as $t}from"../services/runtime-resources-snapshot.js";import{subAgentManager as xt}from"../services/sub-agent-manager-instance.js";import{getUserAiConfigFile as It,isLegacyFallbackDisabled as Lt}from"../services/user-scope.js";import{recordAgentFileChange as Dt}from"../services/workspaceTaskChangeWatcher.js";import{getInstanceAiConfigDebugLogger as U}from"../utils/instance-ai-config-debug-logger.js";import{recordLifecycleEvent as k}from"../utils/lifecycle-log.js";import{isMessagePollingIdleCommand as F,isPollMessageToolDescriptor as Ot}from"./acode-tool-names.js";import{IdlePollLoop as vt}from"./idle-poll-loop.js";import{resolveAcodeProviderConfig as Mt}from"./instance-ai-config-resolver.js";import{MESSAGE_POLLING_IDLE_PROMPT as Q}from"./prompts.js";import{getCanonicalMcpDetail as G,getToolActionInfo as Rt}from"./types.js";const Ut=process.env.ACODE_COMPACTION_DEBUG==="1";function r(...u){Ut&&console.log(...u)}const Ft=process.env.ACODE_TOKEN_DEBUG==="1";function w(...u){Ft&&console.log("[TokenDebug][Adapter]",...u)}const qt=Q,Bt=5e3;function E(u,t){const e=process.env[u];if(e===void 0||e.trim()==="")return t;const o=Number(e.trim());return Number.isFinite(o)&&o>=0?Math.floor(o):t}const z=E("ACODE_DATA_FLOW_WATCHDOG_MS",12e4),Nt=5*6e4,Wt=E("ACODE_STUCK_AUTOPOLL_TIMEOUT_MS",5*6e4),J=E("ACODE_LIVENESS_POLL_INTERVAL_MS",15e3),q=E("ACODE_LIVENESS_STALL_TIMEOUT_MS",10*6e4),Ht=250,Kt=1e3,jt=E("ACODE_DEFERRED_IDLE_REARM_MS",3e3),Y=[2e3,3e3,1e4,4e4],V=4e3;function Qt(u){const t=String(u||"").trim();if(t)return t.length>V?`${t.slice(0,V)}\u2026(truncated)`:t}function Gt(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 B={[I]:"browser_",[P]:"desktop_"};function zt(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 X=E("ACODE_SUBMIT_TIMEOUT_MS",12e4),Z=3e3,Jt=Q;function Yt(){return W.resolve(pt())}function Vt(u){return nt(W.resolve(u)).href}const tt=128e3,$={"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 Xt(u){if(!u)return tt;const t=u.toLowerCase().trim(),e=$[t];if(e)return e.contextLimit;const o=Object.keys($).filter(a=>t.startsWith(a)).sort((a,i)=>i.length-a.length),s=o[0]!==void 0?$[o[0]]:void 0;return s?s.contextLimit:tt}const et=4096;function Zt(u){if(!u)return et;const t=u.toLowerCase().trim(),e=$[t];if(e)return e.maxOutput;const o=Object.keys($).filter(a=>t.startsWith(a)).sort((a,i)=>i.length-a.length),s=o[0]!==void 0?$[o[0]]:void 0;return s?s.maxOutput:et}function ot(u){if(!u||typeof u!="object")return;const t=u,e=A(t.inputTokens,t.input_tokens,t.promptTokens,t.prompt_tokens),o=A(t.outputTokens,t.output_tokens,t.completionTokens,t.completion_tokens);if(e===0&&o===0)return;let s=A(t.cacheHitTokens,t.promptCacheHitTokens,t.prompt_cache_hit_tokens),a=A(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=A(t.cache_read_input_tokens),d=A(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?A(t.input_tokens):Math.max(0,e-n-d);s=n,a=d+m,i=!0}else s=A(t.cache_hit_tokens),a=A(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=A(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 A(...u){for(const t of u){const e=Number(t);if(Number.isFinite(e)&&e>0)return e}return 0}function te(u){return u==="stderr"||u==="mixed"?u:"stdout"}function L(u){const t=Number(u);return Number.isFinite(t)?t:0}function N(u){if(u==null)return;const t=Number(u);return Number.isFinite(t)?t:void 0}function ee(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 oe(u){return u.failed===!0}function st(u,t,e){if(!u)return e?`${t}/${e}`:t;const o=`${t}__`;return u.startsWith(o)?G(`${t}__${u.slice(o.length)}`):G(u.replace("/","__"))}function se(u){return u==="read_file"||u==="edit_file"||u==="write_file"||u==="bash"}function ie(u){const t=ae(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 ae(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 Ue extends it{constructor(){super(),this.providerId="acode",this.displayName="ACode",this.sessions=new Map,this.expandedBuiltInCapabilities=new Map,this.builtInCapabilityToolCache=new Map,this.listenerWakeHooks=new Map,v.setOnPluginsChanged(t=>{this.syncPluginCommands(t)})}async syncPluginCommands(t){try{const e=await v.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)}}resolveAgentConfigPath(t,e){if(e)return e;const o=t?mt(t):null;return o?It(o):Lt()?"":dt()}async startSession(t,e){const o=this.resolveAgentConfigPath(e.agentId,e.mcpConfigPath),{resolved:s,configContextLimit:a,supportsImage:i}=await this.resolveAcodeProvider(e,o),n=s.model,d=a??Xt(n),l=Zt(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),K(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.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..."),s.lastErrorText=n instanceof Error?n.message:String(n),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 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 a=o.runtime.cancelQuestionAnswer(s,e);o.pendingQuestionToolCallId=void 0,o.pendingQuestions=void 0,r(`[AcodeSdkAdapter] cancelQuestionAnswer: session=${t}, toolCallId=${s}, settled=${a}, 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&&(K(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),kt(o)),this.emit("status-change",t,"terminated")}getConversation(t){return this.sessions.get(t)?.adapterSession.messages??[]}trackOpenDocumentEvent(t,e,o,s){const a=t.config.agentId;if(a)try{const i=_t(e,o,s);if(!i)return;i.action==="open"?wt(a,{kind:i.kind,docId:i.docId,name:i.name,...i.detail?{detail:i.detail}:{}}):i.action==="close"?Ct(a,i.kind):Pt(a,i.kind,i.docId)}catch(i){r(`[acode-adapter] open doc registry update failed: ${i?.message}`)}}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}hasActiveBlockingToolCall(t){const e=this.sessions.get(t);return e?this.hasActiveBlockingToolCallEntry(e):!1}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=this.resolveAgentConfigPath(e.config.agentId,e.config.mcpConfigPath),{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=H(t);if(e)return e}catch(e){r(`[acode-adapter] skill farm sync failed for agent ${t}:`,e.message)}return ut(t)}return ct()}async applyAgentFeatures(t){if(!t)return;const e=this.shouldInjectCapabilityTools(t,P),o=this.shouldInjectCapabilityTools(t,I);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 O(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 M(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{H(t)}catch(a){r(`[acode-adapter] skill farm hot-sync failed for agent ${t}:`,a.message)}try{await v.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?R(t,e)==="expanded":!0}resolveCapabilityToolPrefix(t){return B[String(t??"").trim()]}async loadCapabilityToolsForSession(t,e,o){const s=t===I?await M(e,o.config.scopeKey,typeof o.config.browserAllowPrivate=="boolean"?{allowPrivate:o.config.browserAllowPrivate}:void 0):await O(e,await this.resolveAgentAiInfo(e)),a=[];for(const i of s){const n=zt(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&&R(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&&F(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 at.readFile(t,"utf-8"),o=JSON.parse(e),a=o.provider?.default,i=a?.options,n=A(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=A(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 U().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=U();s.log({level:"info",category:"resolve",message:"resolveAcodeProvider \u8F93\u5165",source:"bridge",details:{configModel:t.model??null,configInstanceAiConfig:t.instanceAiConfig?j(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=Mt(a,i,"acode-default");return s.log({level:"info",category:"resolve",message:"resolveAcodeProvider \u89E3\u6790\u7ED3\u679C",source:"bridge",details:{instanceConfig:j(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=this.resolveAgentConfigPath(o.agentId,o.mcpConfigPath);let d=[];try{d=await M(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:a===!0,...s.baseURL?{baseURL:s.baseURL}:{},...s.apiKey?{apiKey:s.apiKey}:{}}:void 0,f=await O(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?lt(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:xt,terminalManager:ft,capabilityState:p=>rt(p)?"collapsed":R(o.agentId??"",bt(p)),capabilityToolRelay:o.agentId?{handlesGroup:p=>this.resolveCapabilityToolPrefix(p)!==void 0,handlesTool:p=>Object.values(B).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(B[P]??"desktop_")?P:I;return this.callBuiltInCapabilityTool(o.agentId??"",T,p,f)}}:void 0,pluginBridge:o.agentId?v.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=>Dt({...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 U().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(t);if(!e.some(a=>{const i=a.trim().replace(/[.*]+$/,"");return i==="desktop"||i.startsWith("desktop.")}))return[];const s=await this.resolveAgentAiInfo(t);return O(t,s)}}async loadRuntimeConstructor(){if(this.runtimeConstructor)return this.runtimeConstructor;const t=Yt(),e=await import(Vt(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:te(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=A(o?.inputTokens),a=A(o?.outputTokens),i=A(o?.cacheHitTokens),n=A(o?.cacheMissTokens),d=!!(o&&(s>0||a>0));let l;d&&(s>0&&(e.adapterSession.totalUsage.inputTokens=s,e.usageInputEstimated=!1),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:ee(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=ot(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=ot(t.data.usage);if(o){const a=e.adapterSession.totalUsage.inputTokens,n=typeof t.data.usageEstimated=="boolean"?t.data.usageEstimated===!0:a>0&&o.inputTokens<Math.floor(a*.2)&&!o.hasCache&&!e.usageInputEstimated;w(`turn_complete usage: raw=${JSON.stringify(t.data.usage)} parsed=${JSON.stringify(o)} currentInput=${a} threshold20pct=${Math.floor(a*.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}`),oe(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(y=>Ot(y))||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(y=>({name:String(y.name??""),source:String(y.source??""),description:String(y.description??"")})).filter(y=>y.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(y=>y.name)}),e.capabilitiesFallbackTimer&&clearTimeout(e.capabilitiesFallbackTimer),e.capabilitiesFallbackTimer=setTimeout(()=>{const y=e.cachedMcpCapabilities;if(!y)return;const _={...y,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 ${Z}ms)`,{sessionId:t.sessionId,mcpServers:y.mcpServers,mcpToolsCount:y.mcpTools?.length??0}),e.cachedMcpCapabilities=void 0,e.capabilitiesFallbackTimer=void 0},Z);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:N(t.data.totalWaitMs),contentionCount:L(t.data.contentionCount),failureCount:N(t.data.failureCount),maxConcurrentObserved:N(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=Rt(i,n);e.autoPollObservedAnyTool=!0,d.actionType==="idle"&&(e.autoPollObservedPollingTool=!0);const l=se(d.actionType)?d.actionDetail||st(void 0,s,a):st(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.trackOpenDocumentEvent(e,i,n,t.data.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"&&!ie(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==="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=A(t.data.contextLimit)||void 0,s=A(t.data.maxOutput)||void 0,a=A(t.data.inputLimit)||void 0,i=A(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,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(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 y=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,_=y?`, \u89E6\u53D1: ${y}`:"";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??"?"),y=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: ${y}`+(_?`, \u88C1\u526A\u5DE5\u5177: ${_}\u6761`:"")+(D?`, \u6458\u8981\u5316: ${D}\u6761`:""):p=`\u91CA\u653E: ${C}KB, ${S}KB \u2192 ${b}KB, \u7B56\u7565: ${y}`+(_?`, \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`;if(n&&d&&!f.parentId&&(f.parentId=d),i){const T=A(o.contextTokensAfter)||A(o.tokensAfter);e.adapterSession.totalUsage.inputTokens=A(T),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,jt)}getIdlePollLoop(t){if(t.idlePollLoop)return t.idlePollLoop;const e=t.adapterSession.sessionId;return t.idlePollLoop=new vt({getStatus:()=>this.sessions.get(e)?.adapterSession.status,getCommand:()=>this.sessions.get(e)?.idleCommands?.idleInputCommand,isPollingCommand:o=>F(o),preDispatchHook:()=>null,dispatchPollingPrompt:(o,s)=>this.submitAutoPollPrompt(e,s?o:Jt,{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=>{const n=this.sessions.get(t);n&&(n.lastErrorText=i instanceof Error?i.message:String(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??Ht;e===void 0&&(o.autoPollDelayMs=Math.min(s*2,Kt)),o.autoPollTimer=setTimeout(()=>{const a=this.sessions.get(t);!a||a.autoPollActive||this.isTerminalStatus(a.adapterSession.status)||(a.autoPollTimer=void 0,this.submitAutoPollPrompt(t,qt,{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)||o.retryActive||o.retryTimer)return;if(!o.lastSubmittedPrompt){o.adapterSession.status="error",this.emit("status-change",t,"error");return}o.turnModelRequestSucceeded&&o.turnModelRequestSucceededEpoch===o.retryEpoch&&(o.turnModelRequestSucceeded=!1,o.retryAttempt=0),o.lastErrorText&&Gt(o.lastErrorText)&&Et({sessionId:t,agentId:o.config.agentId,model:o.config.model,attempt:Math.max(1,o.retryAttempt+1),errorText:o.lastErrorText,conversation:this.exportRawTranscript(t),extra:{reason:e,status:o.adapterSession.status}}),o.retryAttempt+=1,o.retryActive=!0,this.cancelScheduledAutoPoll(o),o.idlePollLoop?.stop();const s=Y[Math.min(o.retryAttempt-1,Y.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:Qt(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,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&&F(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.hasActiveBlockingToolCallEntry(s)&&i-s.autoPollLastActivityAt>=Wt){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>=Nt){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(z>0&&d>=z){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(X>0&&n>=X){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}},Bt)}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(),!(q<=0)&&(e.livenessTimer=setInterval(()=>{const o=this.sessions.get(t);if(!o){this.stopLivenessWatchdog(e);return}this.checkSessionLiveness(t,o)},J),k("liveness_watchdog_arm",{sessionId:t,stallTimeoutMs:q,pollIntervalMs:J}))}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.hasActiveBlockingToolCallEntry(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<q)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`)}hasActiveBlockingToolCallEntry(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 it}from"node:events";import at from"node:fs/promises";import W from"node:path";import{pathToFileURL as nt}from"node:url";import{isMcpGroupKey as rt}from"@agentswork/acode";import{v4 as I}from"uuid";import{getBridgeInstancePluginsDir as lt,getBridgeInstanceSkillsDir as ut,getBridgeTemplateConfigFile as dt,getBridgeTemplateSkillsDir as ct}from"../config.js";import{getReleasedAcodeEntryPath as pt}from"../services/acode-package.js";import{syncAgentSkillFarm as H}from"../services/agent-capability-sync.js";import{getAgentOwner as mt}from"../services/agent-ownership.js";import{agentPtyManager as ft}from"../services/agent-pty-manager.js";import{getBrowserTools as M,closeBrowserSession as gt,registerListenerWakeHook as ht,unregisterListenerWakeHook as K}from"../services/browser-session-manager.js";import{getDesktopTools as D,getDesktopToolsIfReady as Tt}from"../services/desktop-mcp-manager.js";import{redactForLog as j}from"../services/instance-ai-config-service.js";import{BROWSER_FEATURE_KEY as x,DESKTOP_FEATURE_KEY as P,getAgentToolPermissions as At,getFeatureState as R,isFeatureEnabled as yt,resolveAgentToolPermissions as St,resolveGroupFeatureKey as bt}from"../services/instance-features.js";import{resolveOpenDocEvent as _t}from"../services/open-doc-events.js";import{closeOpenDocument as Ct,clearOpenDocuments as kt,recordOpenDocument as wt,removeOpenDocument as Pt}from"../services/open-doc-registry.js";import{pluginManager as v}from"../services/plugin-manager.js";import{dumpInvalidProviderRequest as Et}from"../services/request-invalid-dump.js";import{buildRuntimeResourcesSnapshot as $t}from"../services/runtime-resources-snapshot.js";import{subAgentManager as It}from"../services/sub-agent-manager-instance.js";import{getUserAiConfigFile as xt,isLegacyFallbackDisabled as Lt}from"../services/user-scope.js";import{recordAgentFileChange as Ot}from"../services/workspaceTaskChangeWatcher.js";import{getInstanceAiConfigDebugLogger as U}from"../utils/instance-ai-config-debug-logger.js";import{recordLifecycleEvent as k}from"../utils/lifecycle-log.js";import{isMessagePollingIdleCommand as F,isPollMessageToolDescriptor as Dt}from"./acode-tool-names.js";import{IdlePollLoop as vt}from"./idle-poll-loop.js";import{resolveAcodeProviderConfig as Mt}from"./instance-ai-config-resolver.js";import{MESSAGE_POLLING_IDLE_PROMPT as Q}from"./prompts.js";import{getCanonicalMcpDetail as G,getToolActionInfo as Rt}from"./types.js";const Ut=process.env.ACODE_COMPACTION_DEBUG==="1";function r(...d){Ut&&console.log(...d)}const Ft=process.env.ACODE_TOKEN_DEBUG==="1";function w(...d){Ft&&console.log("[TokenDebug][Adapter]",...d)}const qt=Q,Bt=5e3;function E(d,t){const e=process.env[d];if(e===void 0||e.trim()==="")return t;const o=Number(e.trim());return Number.isFinite(o)&&o>=0?Math.floor(o):t}const z=E("ACODE_DATA_FLOW_WATCHDOG_MS",12e4),Nt=5*6e4,Wt=E("ACODE_STUCK_AUTOPOLL_TIMEOUT_MS",5*6e4),J=E("ACODE_LIVENESS_POLL_INTERVAL_MS",15e3),q=E("ACODE_LIVENESS_STALL_TIMEOUT_MS",10*6e4),Ht=250,Kt=1e3,jt=E("ACODE_DEFERRED_IDLE_REARM_MS",3e3),Y=[2e3,3e3,1e4,4e4],V=4e3;function Qt(d){const t=String(d||"").trim();if(t)return t.length>V?`${t.slice(0,V)}\u2026(truncated)`:t}function Gt(d){const t=d.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 B={[x]:"browser_",[P]:"desktop_"};function zt(d){if(!d||typeof d!="object")return;const t=d,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 X=E("ACODE_SUBMIT_TIMEOUT_MS",12e4),Z=3e3,Jt=Q;function Yt(){return W.resolve(pt())}function Vt(d){return nt(W.resolve(d)).href}const tt=128e3,$={"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 Xt(d){if(!d)return tt;const t=d.toLowerCase().trim(),e=$[t];if(e)return e.contextLimit;const o=Object.keys($).filter(a=>t.startsWith(a)).sort((a,i)=>i.length-a.length),s=o[0]!==void 0?$[o[0]]:void 0;return s?s.contextLimit:tt}const et=4096;function Zt(d){if(!d)return et;const t=d.toLowerCase().trim(),e=$[t];if(e)return e.maxOutput;const o=Object.keys($).filter(a=>t.startsWith(a)).sort((a,i)=>i.length-a.length),s=o[0]!==void 0?$[o[0]]:void 0;return s?s.maxOutput:et}function ot(d){if(!d||typeof d!="object")return;const t=d,e=A(t.inputTokens,t.input_tokens,t.promptTokens,t.prompt_tokens),o=A(t.outputTokens,t.output_tokens,t.completionTokens,t.completion_tokens);if(e===0&&o===0)return;let s=A(t.cacheHitTokens,t.promptCacheHitTokens,t.prompt_cache_hit_tokens),a=A(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 c=A(t.cache_read_input_tokens),u=A(t.cache_creation_input_tokens);if(c>0||u>0){const f=t.input_tokens!==void 0&&Number.isFinite(Number(t.input_tokens))&&Number(t.input_tokens)>=0?A(t.input_tokens):Math.max(0,e-c-u);s=c,a=u+f,i=!0}else s=A(t.cache_hit_tokens),a=A(t.cache_miss_tokens),i=i||t.cache_hit_tokens!==void 0||t.cache_miss_tokens!==void 0}if(s===0&&a===0){const c=A(t.prompt_tokens_details?.cached_tokens);c>0&&(s=c,a=e>c?e-c:0,i=!0)}const n=c=>{const u=Number(c);return Number.isFinite(u)&&u>=0?u:void 0},p=n(t.totalInputTokens??t.total_input_tokens),l=n(t.totalOutputTokens??t.total_output_tokens);return{inputTokens:e,outputTokens:o,...i?{cacheHitTokens:s,cacheMissTokens:a}:{},...i?{hasCache:!0}:{},...p!==void 0||l!==void 0?{totalInputTokens:p,totalOutputTokens:l}:{}}}function A(...d){for(const t of d){const e=Number(t);if(Number.isFinite(e)&&e>0)return e}return 0}function te(d){return d==="stderr"||d==="mixed"?d:"stdout"}function L(d){const t=Number(d);return Number.isFinite(t)?t:0}function N(d){if(d==null)return;const t=Number(d);return Number.isFinite(t)?t:void 0}function ee(d){if(!d||typeof d!="object"||Array.isArray(d))return;const t={};for(const[e,o]of Object.entries(d))typeof o=="string"&&(t[e]=o);return Object.keys(t).length>0?t:void 0}function oe(d){return d.failed===!0}function st(d,t,e){if(!d)return e?`${t}/${e}`:t;const o=`${t}__`;return d.startsWith(o)?G(`${t}__${d.slice(o.length)}`):G(d.replace("/","__"))}function se(d){return d==="read_file"||d==="edit_file"||d==="write_file"||d==="bash"}function ie(d){const t=ae(d);return t?[t.directMessages,t.groupMessages,t.messages].some(e=>Array.isArray(e)&&e.length>0):typeof d=="string"&&d.trim().length>0}function ae(d){if(d&&typeof d=="object"&&!Array.isArray(d))return d;if(!(typeof d!="string"||!d.trim()))try{const t=JSON.parse(d);return t&&typeof t=="object"&&!Array.isArray(t)?t:void 0}catch{return}}class Ue extends it{constructor(){super(),this.providerId="acode",this.displayName="ACode",this.sessions=new Map,this.expandedBuiltInCapabilities=new Map,this.builtInCapabilityToolCache=new Map,this.listenerWakeHooks=new Map,v.setOnPluginsChanged(t=>{this.syncPluginCommands(t)})}async syncPluginCommands(t){try{const e=await v.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)}}resolveAgentConfigPath(t,e){if(e)return e;const o=t?mt(t):null;return o?xt(o):Lt()?"":dt()}async startSession(t,e){const o=this.resolveAgentConfigPath(e.agentId,e.mcpConfigPath),{resolved:s,configContextLimit:a,supportsImage:i}=await this.resolveAcodeProvider(e,o),n=s.model,p=a??Xt(n),l=Zt(n),c={sessionId:t,status:"starting",messages:[],createdAt:new Date().toISOString(),totalUsage:{inputTokens:0,outputTokens:0,contextLimit:p,maxOutput:l,cacheHitTokens:e.resumeTokenUsage?.cacheHitTokens??0,cacheMissTokens:e.resumeTokenUsage?.cacheMissTokens??0,totalInputTokens:e.resumeTokenUsage?.totalInputTokens??0,totalOutputTokens:e.resumeTokenUsage?.totalOutputTokens??0}};this.sessions.set(t,{adapterSession:c,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 u=this.sessions.get(t);if(!u)throw new Error("ACode session was not initialized");this.startLivenessWatchdog(t,u);const m=()=>{const f=this.sessions.get(t);f&&(f.autoPollDelayMs=void 0,this.getIdlePollLoop(f).start())};this.listenerWakeHooks.set(t,m),ht(e.agentId,m);try{if(await u.runtime.start(),console.log(`[HIBERNATE-REPLAY] startSession: agentId=${e.agentId??"?"} resumeTranscript=${Array.isArray(u.config.resumeTranscript)?`${u.config.resumeTranscript.length}\u6761`:"\u65E0"} importTranscript\u652F\u6301=${typeof u.runtime.importTranscript=="function"}`),c.status="waiting_input",this.emit("status-change",t,"waiting_input",{usage:u.adapterSession.totalUsage}),u.config.resumeTranscript&&u.runtime.importTranscript)try{const f=await u.runtime.importTranscript(u.config.resumeTranscript);console.log(`[HIBERNATE-REPLAY] importTranscript \u5B8C\u6210: agentId=${e.agentId??"?"} \u91CD\u653E=${f}\u6761 conversation=${u.runtime.exportConversation?.().length??"?"}\u6761`),f>0&&u.adapterSession.messages.push({id:I(),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){c.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),K(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.retryEpoch+=1,s.turnModelRequestSucceeded=!1;const i={id:I(),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 p=Date.now()-n;this.cancelSubmitTimeoutDetection(s),r(`[ACode] \u2705 runtime.submit() completed in ${p}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 p=Date.now()-o;console.error(`[ACode] \u274C sendMessage FAILED after ${p}ms:`,n instanceof Error?n.message:String(n)),this.cancelSubmitTimeoutDetection(s),r("[ACode] \u25B6\uFE0F sendMessage failed, scheduling request retry..."),s.lastErrorText=n instanceof Error?n.message:String(n),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 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 a=o.runtime.cancelQuestionAnswer(s,e);o.pendingQuestionToolCallId=void 0,o.pendingQuestions=void 0,r(`[AcodeSdkAdapter] cancelQuestionAnswer: session=${t}, toolCallId=${s}, settled=${a}, 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&&(K(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),kt(o)),this.emit("status-change",t,"terminated")}getConversation(t){return this.sessions.get(t)?.adapterSession.messages??[]}trackOpenDocumentEvent(t,e,o,s){const a=t.config.agentId;if(a)try{const i=_t(e,o,s);if(!i)return;i.action==="open"?wt(a,{kind:i.kind,docId:i.docId,name:i.name,...i.detail?{detail:i.detail}:{}}):i.action==="close"?Ct(a,i.kind):Pt(a,i.kind,i.docId)}catch(i){r(`[acode-adapter] open doc registry update failed: ${i?.message}`)}}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}hasActiveBlockingToolCall(t){const e=this.sessions.get(t);return e?this.hasActiveBlockingToolCallEntry(e):!1}getTotalUsage(t){const e=this.sessions.get(t)?.adapterSession.totalUsage;if(e)return{inputTokens:e.inputTokens,outputTokens:e.outputTokens,totalInputTokens:e.totalInputTokens,totalOutputTokens:e.totalOutputTokens,cacheHitTokens:e.cacheHitTokens,cacheMissTokens:e.cacheMissTokens}}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=this.resolveAgentConfigPath(e.config.agentId,e.config.mcpConfigPath),{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=H(t);if(e)return e}catch(e){r(`[acode-adapter] skill farm sync failed for agent ${t}:`,e.message)}return ut(t)}return ct()}async applyAgentFeatures(t){if(!t)return;const e=this.shouldInjectCapabilityTools(t,P),o=this.shouldInjectCapabilityTools(t,x);for(const[a,i]of this.sessions){if(i.config.agentId!==t)continue;const n=i.runtime,p=e,l=o;try{if(p){const c=await D(t,await this.resolveAgentAiInfo(t)),u=n.addBuiltInTools?.(c)??0;u>0&&r(`[acode-adapter] session ${a}: ${u} desktop tools hot-added for agent ${t}`)}else{const c=n.removeBuiltInToolsByPrefix?.("desktop_")??0;c>0&&r(`[acode-adapter] session ${a}: ${c} desktop tools hot-removed for agent ${t}`)}}catch(c){r(`[acode-adapter] session ${a}: desktop feature hot-sync failed for agent ${t}:`,c.message)}if(l)try{const c=await M(t,i.config.scopeKey,typeof i.config.browserAllowPrivate=="boolean"?{allowPrivate:i.config.browserAllowPrivate}:void 0),u=n.addBuiltInTools?.(c)??0;u>0&&r(`[acode-adapter] session ${a}: ${u} browser tools hot-added for agent ${t}`)}catch(c){r(`[acode-adapter] session ${a}: browser feature hot-sync failed for agent ${t}:`,c.message)}else{const c=n.removeBuiltInToolsByPrefix?.("browser_")??0;c>0&&r(`[acode-adapter] session ${a}: ${c} browser tools hot-removed for agent ${t}`)}}this.syncMcpToolsForAgent(t);try{H(t)}catch(a){r(`[acode-adapter] skill farm hot-sync failed for agent ${t}:`,a.message)}try{await v.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[p,l]of this.sessions)if(l.config.agentId===t&&typeof l.runtime.addMcpServer=="function")try{const c=await l.runtime.addMcpServer(e,o);s+=1,c.ok?(a=c.tools,i=c.toolNames):n=c.error}catch(c){n=c.message,r(`[acode-adapter] session ${p}: 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?R(t,e)==="expanded":!0}resolveCapabilityToolPrefix(t){return B[String(t??"").trim()]}async loadCapabilityToolsForSession(t,e,o){const s=t===x?await M(e,o.config.scopeKey,typeof o.config.browserAllowPrivate=="boolean"?{allowPrivate:o.config.browserAllowPrivate}:void 0):await D(e,await this.resolveAgentAiInfo(e)),a=[];for(const i of s){const n=zt(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[c,u]of i){const m=u.runtime.removeBuiltInToolsByPrefix?.(a)??0;l+=m,m>0&&r(`[acode-adapter] session ${c}: ${m} ${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,c]of i){let u;try{u=await this.loadCapabilityToolsForSession(e,s,c)}catch(m){throw r(`[acode-adapter] session ${l}: capability ${e} tool load failed for agent ${s}:`,m.message),m}for(const m of u)n.has(m.name)||n.set(m.name,m)}const p=this.expandedBuiltInCapabilities.get(s)??new Set;return p.add(e),this.expandedBuiltInCapabilities.set(s,p),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&&R(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&&F(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 at.readFile(t,"utf-8"),o=JSON.parse(e),a=o.provider?.default,i=a?.options,n=A(o.contextLimit),p={},l={},c=a?.models;if(c&&typeof c=="object"){for(const[u,m]of Object.entries(c))if(m&&typeof m=="object"){const f=A(m.contextLimit);f>0&&(p[u.trim()]=f);const T=m.modalities?.input,g=Array.isArray(T)&&T.includes("image")||m.supportsImageInput===!0;l[u.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(p).length>0?{modelContextLimits:p}:{},...Object.keys(l).length>0?{modelImageSupport:l}:{}}}catch(e){const o=e instanceof Error?e.message:String(e);return U().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=U();s.log({level:"info",category:"resolve",message:"resolveAcodeProvider \u8F93\u5165",source:"bridge",details:{configModel:t.model??null,configInstanceAiConfig:t.instanceAiConfig?j(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 p=Mt(a,i,"acode-default");return s.log({level:"info",category:"resolve",message:"resolveAcodeProvider \u89E3\u6790\u7ED3\u679C",source:"bridge",details:{instanceConfig:j(a),globalConfigModel:i?.model??null,resolvedModel:p.model,resolvedBaseURL:p.baseURL??null,resolvedApiKey:p.apiKey?"[set]":null,configContextLimit:n,resolvedSource:p.source}}),{resolved:p,configPath:e,perSessionModel:o,configContextLimit:n,supportsImage:i.modelImageSupport?.[p.model]===!0}}async createRuntime(t,e,o,s,a){const i=await this.loadRuntimeConstructor(),n=this.resolveAgentConfigPath(o.agentId,o.mcpConfigPath);let p=[];try{p=await M(o.agentId,o.scopeKey,typeof o.browserAllowPrivate=="boolean"?{allowPrivate:o.browserAllowPrivate}:void 0)}catch(m){r(`[acode-adapter] browser tools injection skipped for agent ${o.agentId}:`,m.message)}let l=[];if(this.shouldInjectCapabilityTools(o.agentId??"",x)&&(l=p),o.agentId&&this.shouldInjectCapabilityTools(o.agentId,P))try{const m=s?.model?{model:s.model,supportsImage:a===!0,...s.baseURL?{baseURL:s.baseURL}:{},...s.apiKey?{apiKey:s.apiKey}:{}}:void 0,f=await D(o.agentId,m);f.length>0&&(l=[...l,...f])}catch(m){r(`[acode-adapter] desktop tools injection skipped for agent ${o.agentId}:`,m.message)}const c=new i({sessionId:t,agentId:o.agentId,workingDirectory:o.workingDirectory,configPath:n,skillsDir:this.resolveAgentSkillsDir(o.agentId),pluginsDir:o.agentId?lt(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,initialTokenUsage:o.resumeTokenUsage,env:o.envOverrides,subAgentManager:It,terminalManager:ft,capabilityState:m=>rt(m)?"collapsed":R(o.agentId??"",bt(m)),capabilityToolRelay:o.agentId?{handlesGroup:m=>this.resolveCapabilityToolPrefix(m)!==void 0,handlesTool:m=>Object.values(B).some(f=>m.startsWith(f)),expand:async m=>(await this.setBuiltInCapabilityTools(o.agentId??"",m,"expand")).manifests??[],collapse:async m=>{await this.setBuiltInCapabilityTools(o.agentId??"",m,"collapse")},call:async(m,f)=>{const T=m.startsWith(B[P]??"desktop_")?P:x;return this.callBuiltInCapabilityTool(o.agentId??"",T,m,f)}}:void 0,pluginBridge:o.agentId?v.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:m=>Ot({...m,agentId:o.agentId,workspacePath:o.workingDirectory}),extraBuiltInTools:l,...o.agentId?{toolPermissionPolicy:At(o.agentId)??void 0}:{},subAgentSuiteTools:p,subAgentSuiteToolProvider:this.buildSubAgentSuiteToolProvider(o.agentId)});return U().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}}),c.on("event",m=>this.forwardAcodeEvent(m)),c}buildSubAgentSuiteToolProvider(t){return async e=>{if(!t)return[];if(!yt(t,P))return[];if(e.length===0)return Tt(t);if(!e.some(a=>{const i=a.trim().replace(/[.*]+$/,"");return i==="desktop"||i.startsWith("desktop.")}))return[];const s=await this.resolveAgentAiInfo(t);return D(t,s)}}async loadRuntimeConstructor(){if(this.runtimeConstructor)return this.runtimeConstructor;const t=Yt(),e=await import(Vt(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:I(),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:te(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=A(o?.inputTokens),a=A(o?.outputTokens),i=A(o?.cacheHitTokens),n=A(o?.cacheMissTokens),p=!!(o&&(s>0||a>0));let l;p&&(s>0&&(e.adapterSession.totalUsage.inputTokens=s,e.usageInputEstimated=!1),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 u={actionType:"ai_request",actionLabel:"AI\u8BF7\u6C42",actionDetail:this.formatAiRequestActionDetail(t.data)};l&&(u.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,u),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:ee(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=ot(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),o.totalInputTokens!==void 0&&(e.adapterSession.totalUsage.totalInputTokens=o.totalInputTokens),o.totalOutputTokens!==void 0&&(e.adapterSession.totalUsage.totalOutputTokens=o.totalOutputTokens),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=ot(t.data.usage);if(o){const a=e.adapterSession.totalUsage.inputTokens,n=typeof t.data.usageEstimated=="boolean"?t.data.usageEstimated===!0:a>0&&o.inputTokens<Math.floor(a*.2)&&!o.hasCache&&!e.usageInputEstimated;w(`turn_complete usage: raw=${JSON.stringify(t.data.usage)} parsed=${JSON.stringify(o)} currentInput=${a} threshold20pct=${Math.floor(a*.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})`)),o.totalInputTokens!==void 0&&(e.adapterSession.totalUsage.totalInputTokens=o.totalInputTokens),o.totalOutputTokens!==void 0&&(e.adapterSession.totalUsage.totalOutputTokens=o.totalOutputTokens),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}`),oe(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(y=>Dt(y))||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(y=>({name:String(y.name??""),source:String(y.source??""),description:String(y.description??"")})).filter(y=>y.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(y=>y.name)}),e.capabilitiesFallbackTimer&&clearTimeout(e.capabilitiesFallbackTimer),e.capabilitiesFallbackTimer=setTimeout(()=>{const y=e.cachedMcpCapabilities;if(!y)return;const _={...y,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 ${Z}ms)`,{sessionId:t.sessionId,mcpServers:y.mcpServers,mcpToolsCount:y.mcpTools?.length??0}),e.cachedMcpCapabilities=void 0,e.capabilitiesFallbackTimer=void 0},Z);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:N(t.data.totalWaitMs),contentionCount:L(t.data.contentionCount),failureCount:N(t.data.failureCount),maxConcurrentObserved:N(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,p=Rt(i,n);e.autoPollObservedAnyTool=!0,p.actionType==="idle"&&(e.autoPollObservedPollingTool=!0);const l=se(p.actionType)?p.actionDetail||st(void 0,s,a):st(p.actionDetail,s,a),c=typeof t.data.toolUseId=="string"?t.data.toolUseId:void 0,u=n?JSON.stringify(n,null,2):void 0,m=typeof t.data.batchId=="string"?t.data.batchId:void 0,f={toolName:l,rawToolName:i,actionType:p.actionType,actionLabel:p.actionLabel,actionDetail:l,...u?{actionInput:u}:{},...n?{toolInput:n}:{},...c?{toolUseId:c,actionId:c}:{},...m?{batchId:m,parentId:m}:{},metadata:{mcpServer:s}};if(t.data.action==="tool_result"){this.trackOpenDocumentEvent(e,i,n,t.data.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:I(),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:c,isError:t.data.failed===!0});const g=p.actionType==="idle"&&!ie(t.data.result)?"waiting_input":"thinking";e.adapterSession.status=g,p.actionType==="idle"&&(e.idleToolActiveAt=void 0),k("tool_use_end",{sessionId:t.sessionId,actionType:p.actionType,tool:i,nextStatus:g,idleToolActiveAtAfter:e.idleToolActiveAt??null}),this.cancelDataFlowWatchdog(e),e.pendingToolEventData=void 0;const h=p.actionType==="idle";this.emit("status-change",t.sessionId,g,h||g==="thinking"?void 0:f);return}const T=p.actionType==="idle"?"waiting_input":"tool_using";e.adapterSession.status=T,p.actionType==="idle"&&(e.idleToolActiveAt=Date.now()),T==="tool_using"&&(this.resetDataFlowWatchdog(t.sessionId,e),e.pendingToolEventData={...f}),e.adapterSession.messages.push({id:I(),sessionId:t.sessionId,role:"tool_use",content:u??"",timestamp:t.timestamp,toolName:i,toolInput:n,toolUseId:c}),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(u=>({name:String(u.name??""),description:typeof u.description=="string"?u.description:void 0,directory:typeof u.directory=="string"?u.directory:void 0})).filter(u=>u.name),a=typeof t.data.skillsDir=="string"?t.data.skillsDir:void 0,n=(Array.isArray(t.data.skillGroups)?t.data.skillGroups:[]).map(u=>{const m=Array.isArray(u.skills)?u.skills:[];return{dir:typeof u.dir=="string"?u.dir:"",exists:u.exists===!0,skills:m.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(u=>u.dir),p=e.cachedMcpCapabilities??e.lastMcpCapabilities,l=e.cachedMcpCapabilities!==void 0,c={kind:"combined",mcpServers:p?.mcpServers??[],mcpTools:p?.mcpTools??[],skills:s,skillsDir:a,skillGroups:n};this.emitProviderEvent(t,"runtime_capabilities",{capabilities:c,actionType:"runtime_capabilities",actionLabel:"\u8FD0\u884C\u65F6\u80FD\u529B",actionDetail:JSON.stringify(c)}),e.lastCombinedCapabilities=c,r(`[cap-diag] Combined capabilities emitted ${l?"(startup merge)":"(runtime refresh)"}: ${(p?.mcpTools??[]).length} MCP tools, ${s.length} skills`,{sessionId:t.sessionId,mcpServers:p?.mcpServers??[],skillsDir:a}),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=A(t.data.contextLimit)||void 0,s=A(t.data.maxOutput)||void 0,a=A(t.data.inputLimit)||void 0,i=A(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",p=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 u,m;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;u="\u4E0A\u4E0B\u6587\u538B\u7F29\u5F00\u59CB";const y=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,_=y?`, \u89E6\u53D1: ${y}`:"";h!==void 0?m=`\u538B\u7F29\u524D: ~${h} tokens, \u6D88\u606F: ${g}\u6761`+(S?`, \u5B9E\u9645 tokens: ${S} ${b}`:"")+_:m=`\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"?(u="\u5F00\u59CB\u89E6\u53D1\u54CD\u5E94\u5F0F\u538B\u7F29",m=h||"\u68C0\u6D4B\u5230\u4E0A\u4E0B\u6587\u8D85\u9650\uFF0C\u5373\u5C06\u5F00\u59CB\u538B\u7F29..."):(u=g,m=h)}else{const T=o.tokensBefore,g=o.tokensAfter,h=o.freedTokens,S=String(o.sizeBeforeKB??"?"),b=String(o.sizeAfterKB??"?"),C=String(o.freedKB??"?"),y=String(o.strategy??"?"),_=Number(o.prunedToolMessages??0),O=Number(o.summarizedMessages??0);u="\u538B\u7F29\u5B8C\u6210",T!==void 0&&g!==void 0?m=`\u91CA\u653E: ${h??T-g} tokens, ${T} tokens \u2192 ${g} tokens, \u7B56\u7565: ${y}`+(_?`, \u88C1\u526A\u5DE5\u5177: ${_}\u6761`:"")+(O?`, \u6458\u8981\u5316: ${O}\u6761`:""):m=`\u91CA\u653E: ${C}KB, ${S}KB \u2192 ${b}KB, \u7B56\u7565: ${y}`+(_?`, \u88C1\u526A\u5DE5\u5177: ${_}\u6761`:"")+(O?`, \u6458\u8981\u5316: ${O}\u6761`:"")}a&&(e.adapterSession.status="compacting");const f={actionType:"context_compaction",actionLabel:u,actionDetail:m};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`;if(n&&p&&!f.parentId&&(f.parentId=p),i){const T=A(o.contextTokensAfter)||A(o.tokensAfter);e.adapterSession.totalUsage.inputTokens=A(T),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,jt)}getIdlePollLoop(t){if(t.idlePollLoop)return t.idlePollLoop;const e=t.adapterSession.sessionId;return t.idlePollLoop=new vt({getStatus:()=>this.sessions.get(e)?.adapterSession.status,getCommand:()=>this.sessions.get(e)?.idleCommands?.idleInputCommand,isPollingCommand:o=>F(o),preDispatchHook:()=>null,dispatchPollingPrompt:(o,s)=>this.submitAutoPollPrompt(e,s?o:Jt,{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=>{const n=this.sessions.get(t);n&&(n.lastErrorText=i instanceof Error?i.message:String(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??Ht;e===void 0&&(o.autoPollDelayMs=Math.min(s*2,Kt)),o.autoPollTimer=setTimeout(()=>{const a=this.sessions.get(t);!a||a.autoPollActive||this.isTerminalStatus(a.adapterSession.status)||(a.autoPollTimer=void 0,this.submitAutoPollPrompt(t,qt,{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)||o.retryActive||o.retryTimer)return;if(!o.lastSubmittedPrompt){o.adapterSession.status="error",this.emit("status-change",t,"error");return}o.turnModelRequestSucceeded&&o.turnModelRequestSucceededEpoch===o.retryEpoch&&(o.turnModelRequestSucceeded=!1,o.retryAttempt=0),o.lastErrorText&&Gt(o.lastErrorText)&&Et({sessionId:t,agentId:o.config.agentId,model:o.config.model,attempt:Math.max(1,o.retryAttempt+1),errorText:o.lastErrorText,conversation:this.exportRawTranscript(t),extra:{reason:e,status:o.adapterSession.status}}),o.retryAttempt+=1,o.retryActive=!0,this.cancelScheduledAutoPoll(o),o.idlePollLoop?.stop();const s=Y[Math.min(o.retryAttempt-1,Y.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:Qt(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,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&&F(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.hasActiveBlockingToolCallEntry(s)&&i-s.autoPollLastActivityAt>=Wt){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>=Nt){const c=String(s.pendingToolEventData?.rawToolName??"");if((s.pendingToolAuthRequests?.size??0)>0){const u=s.pendingToolAuthRequests?.size??0;console.warn(`[ACode] tool_using elapsed ${Math.round(l/1e3)}s but ${u} tool permission request(s) awaiting user decision (session: ${t}), skipping recovery`),s.watchdogSubmitStartTime=i,s.watchdogLastDataFlowTime=i;return}if(c.endsWith("await_complete")){console.warn(`[ACode] tool_using elapsed ${Math.round(l/1e3)}s but await_complete is running (session: ${t}, tool: ${c}), 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 ${c} 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),p=i-(s.watchdogLastDataFlowTime||i);if(z>0&&p>=z){console.warn(`[ACode] CRITICAL: Data flow watchdog triggered after ${Math.round(p/1e3)}s (source: ${o}, session: ${t}, status: ${a}). No stream data received. Forcing recovery via recoverTurnFailure.`),this.executeWatchdogRecovery(t,s,o,"data_flow",p);return}if(X>0&&n>=X){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}},Bt)}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(),!(q<=0)&&(e.livenessTimer=setInterval(()=>{const o=this.sessions.get(t);if(!o){this.stopLivenessWatchdog(e);return}this.checkSessionLiveness(t,o)},J),k("liveness_watchdog_arm",{sessionId:t,stallTimeoutMs:q,pollIntervalMs:J}))}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.hasActiveBlockingToolCallEntry(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<q)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`)}hasActiveBlockingToolCallEntry(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:"",a=typeof t.requestMethod=="string"?t.requestMethod:"",i=typeof t.stream=="boolean"?t.stream:void 0,n=typeof t.messageCount=="number"?t.messageCount:void 0,
|
|
4
|
+
`,o=typeof t.model=="string"?t.model:"",s=typeof t.endpoint=="string"?t.endpoint:typeof t.requestUrl=="string"?t.requestUrl:"",a=typeof t.requestMethod=="string"?t.requestMethod:"",i=typeof t.stream=="boolean"?t.stream:void 0,n=typeof t.messageCount=="number"?t.messageCount:void 0,p=typeof t.toolCount=="number"?t.toolCount:void 0,l=typeof t.lastUserMessagePreview=="string"?t.lastUserMessagePreview:"",c=[o?`\u6A21\u578B: ${o}`:void 0,s?`\u63A5\u53E3: ${s}`:void 0,a?`\u65B9\u6CD5: ${a}`:void 0,i!==void 0?`\u6D41\u5F0F: ${i?"\u662F":"\u5426"}`:void 0,n!==void 0?`\u4E0A\u4E0B\u6587\u6D88\u606F: ${n}`:void 0,p!==void 0?`\u53EF\u7528\u5DE5\u5177: ${p}`:void 0,l?`\u6700\u540E\u8BF7\u6C42: ${l}`:void 0].filter(h=>!!h),u=/^(authorization|x-api-key|api-key|cookie|set-cookie|x-auth-token|token)$/i,m=t.requestHeaders,f=m?Object.entries(m).filter(([h])=>!u.test(h)).map(([h,S])=>`${h}: ${S}`).filter(h=>h.trim().length>0):[],T=c.join(`
|
|
5
5
|
`)||"ACode \u6B63\u5728\u53D1\u9001 AI \u8BF7\u6C42",g=f.length>0?`${e}${f.join(`
|
|
6
6
|
`)}`:"";return`${T}${g}`}}export{Ue as AcodeSdkAdapter,oe as isFailedAcodeTurnComplete,Vt as toAcodeEsmImportSpecifier};
|
|
7
7
|
|
package/dist/adapter/types.d.ts
CHANGED
|
@@ -74,6 +74,11 @@ export interface RuntimeTokenUsage {
|
|
|
74
74
|
cacheHitTokens?: number;
|
|
75
75
|
|
|
76
76
|
cacheMissTokens?: number;
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
totalInputTokens?: number;
|
|
80
|
+
|
|
81
|
+
totalOutputTokens?: number;
|
|
77
82
|
}
|
|
78
83
|
export type CommandOutputStream = "stdout" | "stderr" | "mixed";
|
|
79
84
|
export interface RuntimeStatusActionInfo {
|
|
@@ -320,6 +325,20 @@ export interface AdapterSessionConfig {
|
|
|
320
325
|
|
|
321
326
|
resumeTranscript?: unknown[];
|
|
322
327
|
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
resumeTokenUsage?: {
|
|
336
|
+
totalInputTokens?: number;
|
|
337
|
+
totalOutputTokens?: number;
|
|
338
|
+
cacheHitTokens?: number;
|
|
339
|
+
cacheMissTokens?: number;
|
|
340
|
+
};
|
|
341
|
+
|
|
323
342
|
model?: string;
|
|
324
343
|
|
|
325
344
|
maxTurns?: number;
|
|
@@ -65,6 +65,13 @@ export declare function renderSessionSnapshot(messages: Array<{
|
|
|
65
65
|
|
|
66
66
|
|
|
67
67
|
export declare function parseResumeTranscript(raw: unknown): unknown[] | undefined;
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
export declare function parseResumeTokenUsage(raw: unknown): AdapterSessionConfig["resumeTokenUsage"];
|
|
68
75
|
export interface RuntimeStopOptions {
|
|
69
76
|
statusNotified: boolean;
|
|
70
77
|
reason: string | undefined;
|
|
@@ -96,6 +103,8 @@ export declare function resolveStatusChangeUsage(actionInfo?: RuntimeStatusActio
|
|
|
96
103
|
compactionThreshold?: number;
|
|
97
104
|
cacheHitTokens?: number;
|
|
98
105
|
cacheMissTokens?: number;
|
|
106
|
+
totalInputTokens?: number;
|
|
107
|
+
totalOutputTokens?: number;
|
|
99
108
|
} | undefined;
|
|
100
109
|
export declare function resolveStatusChangeRuntimeState(status: string, actionInfo?: RuntimeStatusActionInfo): {
|
|
101
110
|
status: string;
|