aws-runtime-bridge 1.9.153 → 1.9.168

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. package/CHANGELOG.md +766 -0
  2. package/dist/adapter/AcodeSdkAdapter.d.ts +57 -6
  3. package/dist/adapter/AcodeSdkAdapter.js +4 -8
  4. package/dist/adapter/ClaudeSdkAdapter.d.ts +2 -0
  5. package/dist/adapter/ClaudeSdkAdapter.js +3 -3
  6. package/dist/adapter/CodexSdkAdapter.d.ts +2 -0
  7. package/dist/adapter/CodexSdkAdapter.js +3 -3
  8. package/dist/adapter/OpencodeSdkAdapter.d.ts +2 -0
  9. package/dist/adapter/OpencodeSdkAdapter.js +3 -3
  10. package/dist/adapter/prompts.d.ts +1 -1
  11. package/dist/adapter/prompts.js +1 -1
  12. package/dist/adapter/types.d.ts +41 -20
  13. package/dist/adapter/types.js +1 -1
  14. package/dist/browser/frame-encode.d.ts +25 -0
  15. package/dist/browser/frame-encode.js +2 -0
  16. package/dist/browser/screencast-differ.d.ts +2 -3
  17. package/dist/browser/screencast-differ.js +1 -1
  18. package/dist/browser/screencast-manager.js +1 -1
  19. package/dist/browser/types.d.ts +5 -1
  20. package/dist/browser/types.js +1 -1
  21. package/dist/desktop/desktop-mcp-client.js +2 -2
  22. package/dist/routes/acode-todos.js +1 -1
  23. package/dist/routes/background-tasks.js +3 -3
  24. package/dist/routes/capabilities.js +1 -1
  25. package/dist/routes/dashboard.d.ts +2 -0
  26. package/dist/routes/dashboard.js +4 -4
  27. package/dist/routes/git.js +22 -22
  28. package/dist/routes/instance.js +1 -1
  29. package/dist/routes/launch.js +10 -10
  30. package/dist/routes/ltr.js +1 -1
  31. package/dist/routes/mcp-extra.js +2 -2
  32. package/dist/routes/mcp.d.ts +4 -0
  33. package/dist/routes/mcp.js +1 -1
  34. package/dist/routes/plugins.js +1 -1
  35. package/dist/routes/pty.d.ts +11 -3
  36. package/dist/routes/pty.js +3 -3
  37. package/dist/routes/runtime-binding.js +1 -1
  38. package/dist/routes/sessions.d.ts +18 -74
  39. package/dist/routes/sessions.js +1 -1
  40. package/dist/routes/skills.js +1 -1
  41. package/dist/routes/sub-agents.js +8 -8
  42. package/dist/routes/terminal.d.ts +24 -2
  43. package/dist/routes/terminal.js +34 -36
  44. package/dist/services/agent-process-manager.js +1 -1
  45. package/dist/services/agent-pty-manager.js +4 -4
  46. package/dist/services/aws-client-agent-mcp.js +2 -2
  47. package/dist/services/capability-config.d.ts +8 -0
  48. package/dist/services/capability-config.js +2 -2
  49. package/dist/services/desktop-mcp-manager.d.ts +3 -1
  50. package/dist/services/desktop-mcp-manager.js +1 -1
  51. package/dist/services/instance-ai-config-service.js +1 -1
  52. package/dist/services/instance-features.d.ts +26 -2
  53. package/dist/services/instance-features.js +1 -1
  54. package/dist/services/instance-init-service.js +1 -1
  55. package/dist/services/launch-manager.d.ts +9 -1
  56. package/dist/services/launch-manager.js +6 -6
  57. package/dist/services/launch-metrics.d.ts +1 -1
  58. package/dist/services/launch-metrics.js +4 -3
  59. package/dist/services/mcp-deploy.d.ts +4 -0
  60. package/dist/services/mcp-env-injector.d.ts +12 -0
  61. package/dist/services/mcp-env-injector.js +2 -0
  62. package/dist/services/mcp-launch-binding-queue.d.ts +8 -0
  63. package/dist/services/mcp-launch-binding-queue.js +1 -1
  64. package/dist/services/orphan-monitor.js +1 -1
  65. package/dist/services/panel-env.d.ts +6 -2
  66. package/dist/services/panel-env.js +1 -1
  67. package/dist/services/plugin-manager.js +9 -9
  68. package/dist/services/process-detector.d.ts +23 -3
  69. package/dist/services/process-detector.js +13 -13
  70. package/dist/services/runtime-resources-snapshot.d.ts +3 -0
  71. package/dist/services/runtime-resources-snapshot.js +3 -0
  72. package/dist/services/session-output.d.ts +13 -0
  73. package/dist/services/session-output.js +4 -4
  74. package/dist/services/tunnel-client.js +1 -1
  75. package/dist/services/workspace-files.js +1 -1
  76. package/dist/services/workspace-watch.js +1 -1
  77. package/dist/types.d.ts +4 -0
  78. package/dist/utils/env-safety.d.ts +15 -0
  79. package/dist/utils/env-safety.js +2 -0
  80. package/dist/utils/lifecycle-log.d.ts +2 -0
  81. package/dist/utils/lifecycle-log.js +3 -0
  82. package/dist/utils/mcp-utils.js +1 -1
  83. package/package/acode/dist/ask-user-question-tool.js +1 -1
  84. package/package/acode/dist/await-complete-tool.js +1 -1
  85. package/package/acode/dist/background-command-manager.js +4 -4
  86. package/package/acode/dist/background-command-tools.js +1 -1
  87. package/package/acode/dist/built-in-file-tools.d.ts +31 -2
  88. package/package/acode/dist/built-in-file-tools.js +2 -2
  89. package/package/acode/dist/built-in-symbols-tool.js +1 -1
  90. package/package/acode/dist/builtins/shellCommandPreparation.d.ts +2 -0
  91. package/package/acode/dist/builtins/shellCommandPreparation.js +2 -2
  92. package/package/acode/dist/compaction.d.ts +10 -0
  93. package/package/acode/dist/compaction.js +6 -6
  94. package/package/acode/dist/context-overflow.d.ts +19 -0
  95. package/package/acode/dist/context-overflow.js +2 -0
  96. package/package/acode/dist/grammars/grammars/tree-sitter-lua.wasm +0 -0
  97. package/package/acode/dist/index.d.ts +4 -1
  98. package/package/acode/dist/index.js +1 -1
  99. package/package/acode/dist/mcpToolNames.d.ts +4 -0
  100. package/package/acode/dist/mcpToolNames.js +1 -1
  101. package/package/acode/dist/parsers/ast-cache.d.ts +12 -1
  102. package/package/acode/dist/parsers/ast-cache.js +1 -1
  103. package/package/acode/dist/parsers/language-queries.js +1 -1
  104. package/package/acode/dist/parsers/symbol-extractor.js +2 -2
  105. package/package/acode/dist/parsers/tree-sitter-loader.d.ts +1 -1
  106. package/package/acode/dist/parsers/tree-sitter-loader.js +1 -1
  107. package/package/acode/dist/plugin-types.d.ts +5 -0
  108. package/package/acode/dist/plugin-types.js +1 -0
  109. package/package/acode/dist/read-file-state.d.ts +48 -0
  110. package/package/acode/dist/read-file-state.js +2 -0
  111. package/package/acode/dist/runtime-environment.d.ts +2 -0
  112. package/package/acode/dist/runtime-environment.js +3 -2
  113. package/package/acode/dist/runtime.d.ts +124 -10
  114. package/package/acode/dist/runtime.js +27 -23
  115. package/package/acode/dist/skill-tool.js +3 -3
  116. package/package/acode/dist/sub-agent-manager.js +1 -1
  117. package/package/acode/dist/sub-agent-tools.js +5 -5
  118. package/package/acode/dist/todo-tool.js +3 -3
  119. package/package/acode/dist/tool-allocation.js +1 -1
  120. package/package/acode/dist/tool-concurrency/index.d.ts +5 -0
  121. package/package/acode/dist/tool-concurrency/index.js +2 -0
  122. package/package/acode/dist/tool-concurrency/observability.d.ts +46 -0
  123. package/package/acode/dist/tool-concurrency/observability.js +3 -0
  124. package/package/acode/dist/tool-concurrency/resource-lock.d.ts +25 -0
  125. package/package/acode/dist/tool-concurrency/resource-lock.js +2 -0
  126. package/package/acode/dist/tool-concurrency/scheduler.d.ts +30 -0
  127. package/package/acode/dist/tool-concurrency/scheduler.js +2 -0
  128. package/package/acode/dist/tool-concurrency/types.d.ts +80 -0
  129. package/package/acode/dist/tool-concurrency/types.js +2 -0
  130. package/package/acode/dist/tool-group-manager.d.ts +128 -0
  131. package/package/acode/dist/tool-group-manager.js +18 -0
  132. package/package/acode/dist/types.d.ts +20 -2
  133. package/package/acode/package.json +3 -3
  134. package/package/aws-client-agent-mcp/README.md +1 -0
  135. package/package/aws-client-agent-mcp/dist/agent-client.d.ts +20 -32
  136. package/package/aws-client-agent-mcp/dist/agent-client.js +1 -1
  137. package/package/aws-client-agent-mcp/dist/http-client.d.ts +10 -0
  138. package/package/aws-client-agent-mcp/dist/http-client.js +1 -1
  139. package/package/aws-client-agent-mcp/dist/logger.d.ts +2 -1
  140. package/package/aws-client-agent-mcp/dist/logger.js +2 -2
  141. package/package/aws-client-agent-mcp/dist/mcp-server.d.ts +65 -10
  142. package/package/aws-client-agent-mcp/dist/mcp-server.js +30 -30
  143. package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts +42 -7
  144. package/package/aws-client-agent-mcp/dist/mcp-tools.js +196 -21
  145. package/package/aws-client-agent-mcp/dist/memory-store.d.ts +2 -0
  146. package/package/aws-client-agent-mcp/dist/memory-store.js +3 -3
  147. package/package/aws-client-agent-mcp/dist/message-buffer.js +1 -1
  148. package/package/aws-client-agent-mcp/dist/office/office-equation.d.ts +5 -0
  149. package/package/aws-client-agent-mcp/dist/office/office-equation.js +2 -0
  150. package/package/aws-client-agent-mcp/dist/office/office-image.d.ts +12 -0
  151. package/package/aws-client-agent-mcp/dist/office/office-image.js +2 -0
  152. package/package/aws-client-agent-mcp/dist/office/office-workspace.d.ts +40 -0
  153. package/package/aws-client-agent-mcp/dist/office/office-workspace.js +2 -0
  154. package/package/aws-client-agent-mcp/dist/status-reporter.js +1 -1
  155. package/package/aws-client-agent-mcp/dist/tool-groups.d.ts +4 -0
  156. package/package/aws-client-agent-mcp/dist/tool-groups.js +2 -2
  157. package/package/aws-client-agent-mcp/dist/types.d.ts +56 -3
  158. package/package/aws-client-agent-mcp/dist/websocket-client.js +1 -1
  159. package/package/aws-client-agent-mcp/package.json +2 -1
  160. package/package.json +1 -1
  161. package/package/acode/dist/capability-prompt.d.ts +0 -16
  162. package/package/acode/dist/capability-prompt.js +0 -3
  163. package/package/acode/dist/plugin-tools.d.ts +0 -14
  164. package/package/acode/dist/plugin-tools.js +0 -9
@@ -12,15 +12,23 @@ type ACodeEvent = {
12
12
  type ACodeRuntimeInstance = {
13
13
  on(eventName: "event", listener: (event: ACodeEvent) => void): void;
14
14
  start(): Promise<void>;
15
- submit(message: string): Promise<void>;
15
+ submit(message: string, options?: {
16
+ resume?: boolean;
17
+ }): Promise<void>;
16
18
  abort(): Promise<void>;
17
19
  resetContext?(): Promise<void>;
18
20
  stop(): Promise<void>;
19
21
 
22
+ exportConversation?(): unknown[];
23
+
24
+ importTranscript?(transcript: unknown[]): Promise<number>;
25
+
20
26
  submitQuestionAnswer?(toolCallId: string, answers: Record<string, string>): boolean;
21
27
 
22
28
  detachCurrentToolExecution?(): boolean;
23
29
 
30
+ hasActiveBlockingToolCall?(): boolean;
31
+
24
32
  notifyForceMessage?(): void;
25
33
 
26
34
  addBuiltInTools?(tools: unknown[]): number;
@@ -48,6 +56,8 @@ type ACodeRuntimeConstructor = new (config: {
48
56
  globalPrompt?: string;
49
57
  rolePrompt?: string;
50
58
  memory?: string;
59
+
60
+ resumeContext?: string;
51
61
  env?: Record<string, string>;
52
62
  subAgentManager?: SubAgentManager;
53
63
 
@@ -72,6 +82,24 @@ type ACodeRuntimeConstructor = new (config: {
72
82
  subAgentSuiteToolProvider?: (patterns: string[]) => Promise<unknown[]>;
73
83
 
74
84
  capabilityState?: (featureKey: string) => FeatureState;
85
+
86
+ capabilityToolRelay?: {
87
+ handlesGroup(group: string): boolean;
88
+ handlesTool(toolName: string): boolean;
89
+ expand(group: string): Promise<Array<{
90
+ name: string;
91
+ description?: string;
92
+ inputSchema?: unknown;
93
+ }>>;
94
+ collapse(group: string): Promise<void>;
95
+ call(toolName: string, args: Record<string, unknown>): Promise<{
96
+ ok: boolean;
97
+ result?: unknown;
98
+ error?: string;
99
+ }>;
100
+ };
101
+
102
+ runtimeResourcesProvider?: () => Promise<string | null | undefined>;
75
103
  }) => ACodeRuntimeInstance;
76
104
  export declare function toAcodeEsmImportSpecifier(modulePath: string): string;
77
105
 
@@ -83,7 +111,7 @@ export declare class AcodeSdkAdapter extends EventEmitter implements BaseProvide
83
111
 
84
112
  private expandedBuiltInCapabilities;
85
113
 
86
- private dispatchableCapabilityTools;
114
+ private builtInCapabilityToolCache;
87
115
 
88
116
  private listenerWakeHooks;
89
117
  private runtimeConstructor?;
@@ -107,10 +135,19 @@ export declare class AcodeSdkAdapter extends EventEmitter implements BaseProvide
107
135
  resetContext(sessionId: string): Promise<void>;
108
136
  terminateSession(sessionId: string): Promise<void>;
109
137
  getConversation(sessionId: string): ConversationMessage[];
138
+
139
+ exportRawTranscript(sessionId: string): unknown[] | undefined;
140
+
141
+ importRawTranscript(sessionId: string, transcript: unknown[]): Promise<number>;
110
142
  hasSession(sessionId: string): boolean;
111
143
  getProviderSessionId(sessionId: string): string | undefined;
112
144
  getSessionStatus(sessionId: string): SessionStatus | undefined;
113
145
 
146
+ getTotalUsage(sessionId: string): {
147
+ inputTokens?: number;
148
+ outputTokens?: number;
149
+ } | undefined;
150
+
114
151
  notifyForceMessage(sessionId: string): boolean;
115
152
 
116
153
  getCapabilities(sessionId: string): RuntimeCapabilities | undefined;
@@ -123,6 +160,12 @@ export declare class AcodeSdkAdapter extends EventEmitter implements BaseProvide
123
160
 
124
161
  private syncMcpToolsForAgent;
125
162
 
163
+ private shouldInjectCapabilityTools;
164
+
165
+ private resolveCapabilityToolPrefix;
166
+
167
+ private loadCapabilityToolsForSession;
168
+
126
169
  setBuiltInCapabilityTools(agentId: string, capability: string, action: "expand" | "collapse"): Promise<{
127
170
  sessions: number;
128
171
  tools: number;
@@ -139,10 +182,6 @@ export declare class AcodeSdkAdapter extends EventEmitter implements BaseProvide
139
182
  error?: string;
140
183
  }>;
141
184
 
142
- private pruneDispatchableCapabilityTools;
143
-
144
- private shouldInjectCapabilityTools;
145
-
146
185
  getPendingQuestion(sessionId: string): {
147
186
  toolCallId: string;
148
187
  questions: unknown[];
@@ -170,6 +209,8 @@ export declare class AcodeSdkAdapter extends EventEmitter implements BaseProvide
170
209
  private emitProviderEvent;
171
210
 
172
211
  private armIdleLoopOrAutoPoll;
212
+
213
+ private scheduleDeferredIdleRearm;
173
214
  private getIdlePollLoop;
174
215
  private submitAutoPollPrompt;
175
216
 
@@ -201,6 +242,16 @@ export declare class AcodeSdkAdapter extends EventEmitter implements BaseProvide
201
242
 
202
243
  private cancelDataFlowWatchdog;
203
244
 
245
+ private startLivenessWatchdog;
246
+
247
+ private stopLivenessWatchdog;
248
+
249
+ private checkSessionLiveness;
250
+
251
+ private recoverIdleStall;
252
+
253
+ private hasActiveBlockingToolCall;
254
+
204
255
  private formatAiRequestActionDetail;
205
256
  }
206
257
  export {};
@@ -1,11 +1,7 @@
1
- import{EventEmitter as X}from"node:events";import V from"node:fs/promises";import U from"node:path";import{fileURLToPath as Z,pathToFileURL as tt}from"node:url";import{v4 as v}from"uuid";import{getBridgeInstancePluginsDir as et,getBridgeInstanceSkillsDir as st,getBridgeTemplateConfigFile as x,getBridgeTemplateSkillsDir as ot}from"../config.js";import{getReleasedAcodeEntryPath as it}from"../services/acode-package.js";import{syncAgentSkillFarm as F}from"../services/agent-capability-sync.js";import{agentPtyManager as at}from"../services/agent-pty-manager.js";import{getBrowserTools as L,closeBrowserSession as nt,registerListenerWakeHook as rt,unregisterListenerWakeHook as q}from"../services/browser-session-manager.js";import{getDesktopTools as P,getDesktopToolsIfReady as lt}from"../services/desktop-mcp-manager.js";import{redactForLog as B}from"../services/instance-ai-config-service.js";import{BROWSER_FEATURE_KEY as W,DESKTOP_FEATURE_KEY as D,getAgentToolPermissions as ut,getFeatureState as O,isFeatureEnabled as dt,resolveAgentToolPermissions as ct}from"../services/instance-features.js";import{pluginManager as $}from"../services/plugin-manager.js";import{subAgentManager as mt}from"../services/sub-agent-manager-instance.js";import{recordAgentFileChange as pt}from"../services/workspaceTaskChangeWatcher.js";import{getInstanceAiConfigDebugLogger as E}from"../utils/instance-ai-config-debug-logger.js";import{isMessagePollingIdleCommand as M,isPollMessageToolDescriptor as gt}from"./acode-tool-names.js";import{IdlePollLoop as ft}from"./idle-poll-loop.js";import{resolveAcodeProviderConfig as ht}from"./instance-ai-config-resolver.js";import{MESSAGE_POLLING_IDLE_PROMPT as Tt}from"./prompts.js";import{getCanonicalMcpDetail as N,getToolActionInfo as At}from"./types.js";const yt=process.env.ACODE_COMPACTION_DEBUG==="1";function l(...d){yt&&console.log(...d)}const bt=process.env.ACODE_TOKEN_DEBUG==="1";function k(...d){bt&&console.log("[TokenDebug][Adapter]",...d)}const St=["Continue the AgentsWork message loop now.","You MUST call the exact MCP tool named aws-mcp__poll_message as your next action and wait for the next assigned message or task.","Do not answer in plain text before calling aws-mcp__poll_message.","After handling any received work, reply through the appropriate aws-mcp messaging tool, then continue listening again."].join(" "),_t=5e3;function R(d,t){const e=process.env[d];if(e===void 0||e.trim()==="")return t;const s=Number(e.trim());return Number.isFinite(s)&&s>=0?Math.floor(s):t}const K=R("ACODE_DATA_FLOW_WATCHDOG_MS",12e4),Ct=5*6e4,kt=R("ACODE_STUCK_AUTOPOLL_TIMEOUT_MS",5*6e4),wt=250,H=[0,3e3,1e4,4e4],j=R("ACODE_SUBMIT_TIMEOUT_MS",12e4),Q=3e3,Pt=Tt;function $t(){return U.resolve(it())}function Lt(d){return tt(U.resolve(d)).href}const G=128e3,w={"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 G;const t=d.toLowerCase().trim(),e=w[t];if(e)return e.contextLimit;const s=Object.keys(w).filter(a=>t.startsWith(a)).sort((a,i)=>i.length-a.length),o=s[0]!==void 0?w[s[0]]:void 0;return o?o.contextLimit:G}const J=4096;function Dt(d){if(!d)return J;const t=d.toLowerCase().trim(),e=w[t];if(e)return e.maxOutput;const s=Object.keys(w).filter(a=>t.startsWith(a)).sort((a,i)=>i.length-a.length),o=s[0]!==void 0?w[s[0]]:void 0;return o?o.maxOutput:J}function Ot(d){if(!d||typeof d!="object")return;const t=d,e=h(t.inputTokens,t.input_tokens,t.promptTokens,t.prompt_tokens),s=h(t.outputTokens,t.output_tokens,t.completionTokens,t.completion_tokens);if(e===0&&s===0)return;let o=h(t.cacheHitTokens,t.promptCacheHitTokens,t.prompt_cache_hit_tokens),a=h(t.cacheMissTokens,t.promptCacheMissTokens,t.prompt_cache_miss_tokens),i=t.cacheHitTokens!==void 0||t.cacheMissTokens!==void 0||t.promptCacheHitTokens!==void 0||t.promptCacheMissTokens!==void 0||t.prompt_cache_hit_tokens!==void 0||t.prompt_cache_miss_tokens!==void 0;if(o===0&&a===0){const r=h(t.cache_read_input_tokens),n=h(t.cache_creation_input_tokens);r>0||n>0?(o=r,a=n+h(t.input_tokens),i=!0):(o=h(t.cache_hit_tokens),a=h(t.cache_miss_tokens),i=i||t.cache_hit_tokens!==void 0||t.cache_miss_tokens!==void 0)}if(o===0&&a===0){const r=h(t.prompt_tokens_details?.cached_tokens);r>0&&(o=r,a=e>r?e-r:0,i=!0)}return{inputTokens:e,outputTokens:s,...o>0||a>0?{cacheHitTokens:o,cacheMissTokens:a}:{},...i?{hasCache:!0}:{}}}function h(...d){for(const t of d){const e=Number(t);if(Number.isFinite(e)&&e>0)return e}return 0}function z(d){return h(d.estimatedContextTokens,d.contextTokens,d.context_tokens,d.contextUsedTokens,d.context_used_tokens)}function Et(d){return d==="stderr"||d==="mixed"?d:"stdout"}function Mt(d){if(!d||typeof d!="object"||Array.isArray(d))return;const t={};for(const[e,s]of Object.entries(d))typeof s=="string"&&(t[e]=s);return Object.keys(t).length>0?t:void 0}function Rt(d){return d.failed===!0}function Y(d,t,e){if(!d)return e?`${t}/${e}`:t;const s=`${t}__`;return d.startsWith(s)?N(`${t}__${d.slice(s.length)}`):N(d.replace("/","__"))}function It(d){return d==="read_file"||d==="edit_file"||d==="write_file"||d==="bash"}function Ut(d){const t=vt(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 vt(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 ne extends X{constructor(){super(),this.providerId="acode",this.displayName="ACode",this.sessions=new Map,this.expandedBuiltInCapabilities=new Map,this.dispatchableCapabilityTools=new Map,this.listenerWakeHooks=new Map,$.setOnPluginsChanged(t=>{this.syncPluginCommands(t)})}async syncPluginCommands(t){try{const e=await $.getPluginCommands(t);for(const s of this.sessions.values())s.config.agentId===t&&s.runtime.addPluginCommands?.(e)}catch(e){l(`[acode-adapter] syncPluginCommands failed for agent ${t}:`,e.message)}}async startSession(t,e){const s=e.mcpConfigPath||x(),{resolved:o,configContextLimit:a,supportsImage:i}=await this.resolveAcodeProvider(e,s),r=o.model,n=a??xt(r),c=Dt(r),u={sessionId:t,status:"starting",messages:[],createdAt:new Date().toISOString(),totalUsage:{inputTokens:0,outputTokens:0,contextLimit:n,maxOutput:c,cacheHitTokens:0,cacheMissTokens:0}};this.sessions.set(t,{adapterSession:u,config:e,runtime:await this.createRuntime(t,r,e,o,i),autoPollActive:!1,retryAttempt:0,retryActive:!1}),this.emit("status-change",t,"starting");const m=this.sessions.get(t);if(!m)throw new Error("ACode session was not initialized");const p=()=>{const g=this.sessions.get(t);g&&this.getIdlePollLoop(g).start()};this.listenerWakeHooks.set(t,p),rt(e.agentId,p);try{await m.runtime.start(),u.status="waiting_input",this.emit("status-change",t,"waiting_input",{usage:m.adapterSession.totalUsage}),e.initialPrompt?.trim()?this.startInitialPromptTurn(t,e.initialPrompt):this.armIdleLoopOrAutoPoll(t)}catch(g){u.status="error",this.emitRuntimeErrorEvent(t,g),this.emit("status-change",t,"error");const f=this.sessions.get(t);throw f?.capabilitiesFallbackTimer&&clearTimeout(f.capabilitiesFallbackTimer),this.sessions.delete(t),this.expandedBuiltInCapabilities.delete(t),this.pruneDispatchableCapabilityTools(e.agentId),q(e.agentId,this.listenerWakeHooks.get(t)),this.listenerWakeHooks.delete(t),g}}async sendMessage(t,e){const s=Date.now();l("[ACode] \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"),l("[ACode] \u25B6\uFE0F sendMessage STARTED"),l(`[ACode] Session: ${t}`),l(`[ACode] Message: ${e.slice(0,100)}${e.length>100?"...":""}`),l("[ACode] \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");const o=this.requireSession(t),a=o.adapterSession.status;l(`[ACode] Previous status: ${a}`),this.cancelScheduledAutoPoll(o),o.failedTurnRecoveryScheduled=!1,o.idlePollLoop?.stop(),this.cancelRequestRetry(o),o.retryAttempt=0;const i={id:v(),sessionId:t,role:"user",content:e,timestamp:new Date().toISOString()};o.adapterSession.messages.push(i),this.emit("conversation-message",t,i),l(`[ACode] Changing status: ${a} \u2192 thinking`),o.adapterSession.status="thinking",this.emit("status-change",t,"thinking"),o.lastSubmittedPrompt=e,this.startSubmitTimeoutDetection(t,o,"sendMessage");try{l("[ACode] \u25B6\uFE0F Calling runtime.submit()...");const r=Date.now();await o.runtime.submit(e);const n=Date.now()-r;this.cancelSubmitTimeoutDetection(o),l(`[ACode] \u2705 runtime.submit() completed in ${n}ms`),l(`[ACode] Current status after submit: ${o.adapterSession.status}`),l("[ACode] \u25B6\uFE0F Calling recoverResolvedTurnWithoutTerminalEvent()..."),this.recoverResolvedTurnWithoutTerminalEvent(t),l(`[ACode] Status after recovery: ${o.adapterSession.status}`);const c=Date.now()-s;l("[ACode] \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"),l(`[ACode] \u2705 sendMessage COMPLETED in ${c}ms`),l("[ACode] \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550")}catch(r){const n=Date.now()-s;console.error(`[ACode] \u274C sendMessage FAILED after ${n}ms:`,r instanceof Error?r.message:String(r)),this.cancelSubmitTimeoutDetection(o),l("[ACode] \u25B6\uFE0F sendMessage failed, scheduling request retry..."),this.emitRuntimeErrorEvent(t,r),this.scheduleRequestRetry(t,"sendMessage"),l(`[ACode] Status after failure: ${o.adapterSession.status}`)}}async sendConfirmation(t,e){}submitToolPermissionDecision(t,e,s){const o=this.sessions.get(t);if(!o)return!1;o.pendingToolAuthRequests?.delete(e);const a=o.runtime.submitToolPermissionDecision?.(e,s)??!1;return a&&this.startSubmitTimeoutDetection(t,o,"submitToolPermissionDecision"),a}getPendingToolAuthRequests(t){const e=this.sessions.get(t);return e?.pendingToolAuthRequests?Array.from(e.pendingToolAuthRequests.entries()).map(([s,o])=>({requestId:s,capability:o.capability,detail:o.detail,requestedAt:o.requestedAt})):[]}async sendQuestionAnswer(t,e){const s=this.sessions.get(t);if(!s)return;const o=s.pendingQuestionToolCallId;if(!o){l(`[AcodeSdkAdapter] sendQuestionAnswer: no pending question for session ${t}`);return}s.pendingQuestionToolCallId=void 0,s.pendingQuestions=void 0,s.runtime.submitQuestionAnswer&&s.runtime.submitQuestionAnswer(o,e),this.startSubmitTimeoutDetection(t,s,"sendQuestionAnswer")}async abortCurrentTurn(t){await this.requireSession(t).runtime.abort()}async resetContext(t){const e=this.requireSession(t);if(this.cancelScheduledAutoPoll(e),e.failedTurnRecoveryScheduled=!1,e.autoPollActive=!1,e.autoPollObservedPollingTool=!1,e.autoPollObservedAssistantText=!1,e.autoPollObservedAnyTool=!1,e.stopAutoPollAfterCurrentTurn=!1,e.idlePollLoop?.stop(),!e.runtime.resetContext)throw new Error("ACode runtime does not support context reset");await e.runtime.resetContext(),e.adapterSession.messages=[];const s=e.adapterSession.totalUsage;if(e.adapterSession.totalUsage={inputTokens:0,outputTokens:0,contextLimit:s.contextLimit,maxOutput:s.maxOutput,inputLimit:s.inputLimit,compactionThreshold:s.compactionThreshold,cacheHitTokens:s.cacheHitTokens,cacheMissTokens:s.cacheMissTokens},e.adapterSession.status="waiting_input",this.emit("status-change",t,"waiting_input",{usage:e.adapterSession.totalUsage}),e.config.initialPrompt?.trim()){this.startInitialPromptTurn(t,e.config.initialPrompt);return}this.armIdleLoopOrAutoPoll(t)}async terminateSession(t){const e=this.sessions.get(t);if(!e)return;this.cancelScheduledAutoPoll(e),e.failedTurnRecoveryScheduled=!1,e.idlePollLoop?.stop(),this.cancelRequestRetry(e),e.capabilitiesFallbackTimer&&(clearTimeout(e.capabilitiesFallbackTimer),e.capabilitiesFallbackTimer=void 0),await e.runtime.stop();const s=e.config.agentId;s&&(q(s,this.listenerWakeHooks.get(t)),nt(s)),this.listenerWakeHooks.delete(t),this.expandedBuiltInCapabilities.delete(t),this.pruneDispatchableCapabilityTools(s),e.adapterSession.status="terminated",this.sessions.delete(t),this.emit("status-change",t,"terminated")}getConversation(t){return this.sessions.get(t)?.adapterSession.messages??[]}hasSession(t){return this.sessions.has(t)}getProviderSessionId(t){return this.sessions.has(t)?t:void 0}getSessionStatus(t){return this.sessions.get(t)?.adapterSession.status}notifyForceMessage(t){const e=this.sessions.get(t);return e?.runtime?.notifyForceMessage?(e.runtime.notifyForceMessage(),!0):!1}getCapabilities(t){return this.sessions.get(t)?.lastCombinedCapabilities}async resolveAgentAiInfo(t){try{const e=[...this.sessions.values()].find(i=>i.config.agentId===t);if(!e)return;const s=e.config.mcpConfigPath||x(),{resolved:o,supportsImage:a}=await this.resolveAcodeProvider(e.config,s);return o?.model?{model:o.model,supportsImage:a===!0,...o.baseURL?{baseURL:o.baseURL}:{},...o.apiKey?{apiKey:o.apiKey}:{}}:void 0}catch{return}}resolveAgentSkillsDir(t){if(t){try{const e=F(t);if(e)return e}catch(e){l(`[acode-adapter] skill farm sync failed for agent ${t}:`,e.message)}return st(t)}return ot()}async applyAgentFeatures(t){if(!t)return;const e=this.shouldInjectCapabilityTools(t,D),s=this.shouldInjectCapabilityTools(t,W);for(const[a,i]of this.sessions){if(i.config.agentId!==t)continue;const r=i.runtime,n=e,c=s;try{if(n){const u=await P(t,await this.resolveAgentAiInfo(t)),m=r.addBuiltInTools?.(u)??0;m>0&&l(`[acode-adapter] session ${a}: ${m} desktop tools hot-added for agent ${t}`)}else{const u=r.removeBuiltInToolsByPrefix?.("desktop_")??0;u>0&&l(`[acode-adapter] session ${a}: ${u} desktop tools hot-removed for agent ${t}`)}}catch(u){l(`[acode-adapter] session ${a}: desktop feature hot-sync failed for agent ${t}:`,u.message)}if(c)try{const u=await L(t,i.config.scopeKey,typeof i.config.browserAllowPrivate=="boolean"?{allowPrivate:i.config.browserAllowPrivate}:void 0),m=r.addBuiltInTools?.(u)??0;m>0&&l(`[acode-adapter] session ${a}: ${m} browser tools hot-added for agent ${t}`)}catch(u){l(`[acode-adapter] session ${a}: browser feature hot-sync failed for agent ${t}:`,u.message)}else{const u=r.removeBuiltInToolsByPrefix?.("browser_")??0;u>0&&l(`[acode-adapter] session ${a}: ${u} browser tools hot-removed for agent ${t}`)}}this.syncMcpToolsForAgent(t);try{F(t)}catch(a){l(`[acode-adapter] skill farm hot-sync failed for agent ${t}:`,a.message)}try{await $.applyCapabilities(t)}catch(a){l(`[acode-adapter] plugin capability hot-sync failed for agent ${t}:`,a.message)}const o=ct(t);for(const[a,i]of this.sessions)if(i.config.agentId===t)try{i.runtime.setToolPermissionPolicy?.(o)}catch(r){l(`[acode-adapter] session ${a}: tool permission policy hot-sync failed for agent ${t}:`,r.message)}}syncMcpToolsForAgent(t){if(t){for(const[e,s]of this.sessions)if(s.config.agentId===t)try{s.runtime.requestMcpToolsRefresh?.()}catch(o){l(`[acode-adapter] session ${e}: mcp tools refresh failed for agent ${t}:`,o.message)}}}async setBuiltInCapabilityTools(t,e,s){if(!t)return{sessions:0,tools:0};const o=e==="browser"?"browser_":e==="desktop"?"desktop_":void 0;if(!o)return{sessions:0,tools:0};let a=0,i=0,r;const n=this.dispatchableCapabilityTools.get(t)?.get(e)?.length??0;let c=0;for(const[u,m]of this.sessions)if(m.config.agentId===t)try{if(s==="collapse"){const A=this.expandedBuiltInCapabilities.get(u)?.delete(e)??!1,y=m.runtime.removeBuiltInToolsByPrefix?.(o)??0;c+=y,(A||y>0)&&(a+=1,i+=y,l(`[acode-adapter] session ${u}: collapsed ${e} capability for agent ${t}`));continue}const p=e==="browser"?await L(t,m.config.scopeKey,typeof m.config.browserAllowPrivate=="boolean"?{allowPrivate:m.config.browserAllowPrivate}:void 0):await P(t,await this.resolveAgentAiInfo(t));if(!this.sessions.has(u))continue;let g=this.dispatchableCapabilityTools.get(t);g||(g=new Map,this.dispatchableCapabilityTools.set(t,g)),g.set(e,[...p]);let f=this.expandedBuiltInCapabilities.get(u);f||(f=new Set,this.expandedBuiltInCapabilities.set(u,f)),f.add(e),a+=1,i=p.length,r=p.map(A=>({name:A.toolName,description:A.description,inputSchema:A.inputSchema})),l(`[acode-adapter] session ${u}: ${p.length} ${e} tools dispatchable for agent ${t}`)}catch(p){l(`[acode-adapter] session ${u}: ${e} ${s} failed for agent ${t}:`,p.message)}return s==="collapse"?(this.dispatchableCapabilityTools.get(t)?.delete(e),{sessions:a,tools:n>0?n:c,manifests:r}):{sessions:a,tools:i,manifests:r}}async callBuiltInCapabilityTool(t,e,s,o){if(!t)return{ok:!1,error:"\u7F3A\u5C11 agentId"};if(e!=="browser"&&e!=="desktop")return{ok:!1,error:`\u672A\u77E5\u6865\u63A5\u80FD\u529B\u300C${e}\u300D`};if(!s.startsWith(`${e}_`))return{ok:!1,error:`\u5DE5\u5177\u300C${s}\u300D\u4E0D\u5C5E\u4E8E\u80FD\u529B\u300C${e}\u300D`};if(O(t,e)==="disabled")return{ok:!1,error:`\u80FD\u529B\u300C${e}\u300D\u672A\u5F00\u542F\uFF08\u5DF2\u7981\u7528\uFF0C\u8BF7\u5148\u5728\u80FD\u529B\u914D\u7F6E\u4E2D\u5F00\u542F\uFF09\u3002`};if(![...this.expandedBuiltInCapabilities.entries()].some(([n,c])=>c.has(e)&&this.sessions.get(n)?.config.agentId===t))return{ok:!1,error:`\u80FD\u529B\u300C${e}\u300D\u5C1A\u672A\u5C55\u5F00\uFF0C\u8BF7\u5148\u8C03\u7528 expand_tools({ group: "${e}" })\u3002`};let i=this.dispatchableCapabilityTools.get(t)?.get(e);if(!i||i.length===0)try{const n=[...this.sessions.values()].find(u=>u.config.agentId===t);i=e==="browser"?await L(t,n?.config.scopeKey,typeof n?.config.browserAllowPrivate=="boolean"?{allowPrivate:n.config.browserAllowPrivate}:void 0):await P(t,await this.resolveAgentAiInfo(t));let c=this.dispatchableCapabilityTools.get(t);c||(c=new Map,this.dispatchableCapabilityTools.set(t,c)),c.set(e,[...i])}catch(n){return{ok:!1,error:`\u6865\u63A5\u80FD\u529B\u5DE5\u5177\u6784\u5EFA\u5931\u8D25\uFF1A${n instanceof Error?n.message:String(n)}`}}const r=i.find(n=>n.toolName===s);if(!r)return{ok:!1,error:`\u80FD\u529B\u300C${e}\u300D\u4E0B\u4E0D\u5B58\u5728\u5DE5\u5177\u300C${s}\u300D`};try{return{ok:!0,result:await r.execute(o)}}catch(n){return{ok:!1,error:n instanceof Error?n.message:String(n)}}}pruneDispatchableCapabilityTools(t){if(!t)return;[...this.sessions.values()].some(s=>s.config.agentId===t)||this.dispatchableCapabilityTools.delete(t)}shouldInjectCapabilityTools(t,e){return t?O(t,e)==="expanded":!0}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 s=this.sessions.get(t);if(s){if(s.idleCommands=e,this.cancelScheduledAutoPoll(s),e.idleInputCommand&&M(e.idleInputCommand)){this.getIdlePollLoop(s).start();return}s.adapterSession.status==="waiting_input"&&(e.idleInputCommand||e.nonInputCommand)&&this.getIdlePollLoop(s).start()}}setRuntimeConstructorForTest(t){this.runtimeConstructor=t}async loadAcodeProviderSection(t){try{const e=await V.readFile(t,"utf-8"),s=JSON.parse(e),a=s.provider?.default,i=a?.options,r=h(s.contextLimit),n={},c={},u=a?.models;if(u&&typeof u=="object"){for(const[m,p]of Object.entries(u))if(p&&typeof p=="object"){const g=h(p.contextLimit);g>0&&(n[m.trim()]=g);const f=p.modalities?.input,A=Array.isArray(f)&&f.includes("image")||p.supportsImageInput===!0;c[m.trim()]=A===!0}}return{...a?.model?{model:a.model}:{},...i?.baseURL||i?.baseUrl?{baseURL:i?.baseURL||i?.baseUrl}:{},...i?.apiKey?{apiKey:i.apiKey}:{},...r>0?{contextLimit:r}:{},...Object.keys(n).length>0?{modelContextLimits:n}:{},...Object.keys(c).length>0?{modelImageSupport:c}:{}}}catch(e){const s=e instanceof Error?e.message:String(e);return E().log({level:"warn",category:"load",message:`loadAcodeProviderSection failed: ${t}: ${s}`,source:"bridge"}),{}}}async resolveAcodeProvider(t,e){const s=typeof t.model=="string"&&t.model.trim()?t.model.trim():void 0,o=E();o.log({level:"info",category:"resolve",message:"resolveAcodeProvider \u8F93\u5165",source:"bridge",details:{configModel:t.model??null,configInstanceAiConfig:t.instanceAiConfig?B(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}:{},...s?{model:s}:{}},i=await this.loadAcodeProviderSection(e);let r=i.contextLimit;if(!r&&i.modelContextLimits){const c=s||t.instanceAiConfig?.model||i.model;c&&i.modelContextLimits[c]&&(r=i.modelContextLimits[c])}const n=ht(a,i,"acode-default");return o.log({level:"info",category:"resolve",message:"resolveAcodeProvider \u89E3\u6790\u7ED3\u679C",source:"bridge",details:{instanceConfig:B(a),globalConfigModel:i?.model??null,resolvedModel:n.model,resolvedBaseURL:n.baseURL??null,resolvedApiKey:n.apiKey?"[set]":null,configContextLimit:r,resolvedSource:n.source}}),{resolved:n,configPath:e,perSessionModel:s,configContextLimit:r,supportsImage:i.modelImageSupport?.[n.model]===!0}}async createRuntime(t,e,s,o,a){const i=await this.loadRuntimeConstructor(),r=s.mcpConfigPath||x();let n=[];try{n=await L(s.agentId,s.scopeKey,typeof s.browserAllowPrivate=="boolean"?{allowPrivate:s.browserAllowPrivate}:void 0)}catch(p){l(`[acode-adapter] browser tools injection skipped for agent ${s.agentId}:`,p.message)}let c=[];if(this.shouldInjectCapabilityTools(s.agentId??"",W)&&(c=n),s.agentId&&this.shouldInjectCapabilityTools(s.agentId,D))try{const p=o?.model?{model:o.model,supportsImage:a===!0,...o.baseURL?{baseURL:o.baseURL}:{},...o.apiKey?{apiKey:o.apiKey}:{}}:void 0,g=await P(s.agentId,p);g.length>0&&(c=[...c,...g])}catch(p){l(`[acode-adapter] desktop tools injection skipped for agent ${s.agentId}:`,p.message)}const u=new i({sessionId:t,agentId:s.agentId,workingDirectory:s.workingDirectory,configPath:r,skillsDir:this.resolveAgentSkillsDir(s.agentId),pluginsDir:s.agentId?et(s.agentId):void 0,model:e,systemPrompt:typeof s.systemPrompt=="string"?s.systemPrompt:void 0,globalPrompt:typeof s.globalPrompt=="string"?s.globalPrompt:void 0,rolePrompt:typeof s.rolePrompt=="string"?s.rolePrompt:void 0,memory:typeof s.memory=="string"?s.memory:void 0,env:s.envOverrides,subAgentManager:mt,terminalManager:at,capabilityState:p=>O(s.agentId??"",p),pluginBridge:s.agentId?$.forAgent(s.agentId):void 0,commandDirs:[Z(new URL("../services/builtin-commands/",import.meta.url))],...s.subAgentModel?{subAgentModel:s.subAgentModel}:{},...s.subAgentEffort?{subAgentEffort:s.subAgentEffort}:{},...s.instanceAiConfig?.effort?{effort:s.instanceAiConfig.effort}:{},onFileChange:p=>pt({...p,agentId:s.agentId,workspacePath:s.workingDirectory}),extraBuiltInTools:c,...s.agentId?{toolPermissionPolicy:ut(s.agentId)??void 0}:{},subAgentSuiteTools:n,subAgentSuiteToolProvider:this.buildSubAgentSuiteToolProvider(s.agentId)});return E().log({level:"info",category:"resolve",message:"ACode provider resolved",source:"bridge",sessionId:t,details:{resolvedModel:e,perInstanceModel:s.instanceAiConfig?.model||null,perInstanceBaseURL:s.instanceAiConfig?.baseURL?"[set]":null,perInstanceApiKey:s.instanceAiConfig?.apiKey?"[set]":null,configPath:r}}),u.on("event",p=>this.forwardAcodeEvent(p)),u}buildSubAgentSuiteToolProvider(t){return async e=>{if(!t)return[];if(!dt(t,D))return[];if(e.length===0)return lt();if(!e.some(a=>{const i=a.trim().replace(/[.*]+$/,"");return i==="desktop"||i.startsWith("desktop.")}))return[];const o=await this.resolveAgentAiInfo(t);return P(t,o)}}async loadRuntimeConstructor(){if(this.runtimeConstructor)return this.runtimeConstructor;const t=$t(),e=await import(Lt(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 s=this.sessions.get(t);s&&(s.adapterSession.status="thinking",this.emit("status-change",t,"thinking"),s.lastSubmittedPrompt=e,this.startSubmitTimeoutDetection(t,s,"startInitialPromptTurn"),s.runtime.submit(e).then(()=>{this.cancelSubmitTimeoutDetection(s),this.recoverResolvedTurnWithoutTerminalEvent(t)}).catch(o=>{const a=this.sessions.get(t);a&&(this.cancelSubmitTimeoutDetection(a),this.emitRuntimeErrorEvent(t,o),this.scheduleRequestRetry(t,"startInitialPromptTurn"))}))}forwardAcodeEvent(t){const e=this.sessions.get(t.sessionId);if(e){if(e.autoPollActive&&(e.autoPollLastActivityAt=Date.now()),t.type==="assistant_delta"){const s=typeof t.data.text=="string"?t.data.text:"";e.autoPollActive&&(e.autoPollObservedAssistantText=!0),e.adapterSession.messages.push({id:v(),sessionId:t.sessionId,role:"assistant",content:s,timestamp:t.timestamp}),this.resetDataFlowWatchdog(t.sessionId,e),this.emitProviderEvent(t,"text_delta",{text:s});return}if(t.type==="thinking_delta"){const s=typeof t.data.text=="string"?t.data.text:"";this.resetDataFlowWatchdog(t.sessionId,e),this.emitProviderEvent(t,"thinking",{text:s});return}if(t.type==="command_output"){this.emitProviderEvent(t,"command_output",{text:typeof t.data.text=="string"?t.data.text:"",stream:Et(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 s=z(t.data),o=t.data.lastUsage,a=h(o?.inputTokens),i=h(o?.outputTokens),r=h(o?.cacheHitTokens),n=h(o?.cacheMissTokens),c=!!(o&&(a>0||i>0));let u;if(c&&(a>0&&(e.adapterSession.totalUsage.inputTokens=a),i>0&&(e.adapterSession.totalUsage.outputTokens=i),(o?.cacheHitTokens!==void 0||o?.cacheMissTokens!==void 0)&&(e.adapterSession.totalUsage.cacheHitTokens=r,e.adapterSession.totalUsage.cacheMissTokens=n),u={...e.adapterSession.totalUsage},k(`ai_request lastUsage applied: ${JSON.stringify(o)} -> totalUsage=${JSON.stringify(e.adapterSession.totalUsage)}`)),!c&&s>0){const g=e.adapterSession.totalUsage.inputTokens;g>0?e.adapterSession.totalUsage.inputTokens=Math.min(s,Math.floor(g*1.5)):e.adapterSession.totalUsage.inputTokens=s,u={...e.adapterSession.totalUsage}}e.adapterSession.status==="compacting"&&(e.adapterSession.status="thinking"),e.adapterSession.status==="waiting_input"&&(e.adapterSession.status="thinking");const p={actionType:"ai_request",actionLabel:"AI\u8BF7\u6C42",actionDetail:this.formatAiRequestActionDetail(t.data)};u&&(p.usage=u),k(`ai_request handled: estimatedContextTokens=${t.data.estimatedContextTokens??"n/a"} totalUsage=${JSON.stringify(e.adapterSession.totalUsage)} displayUsage=${JSON.stringify(u??null)}`),this.emit("status-change",t.sessionId,e.adapterSession.status,p),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:Mt(t.data.requestHeaders),stream:typeof t.data.stream=="boolean"?t.data.stream:void 0,messageCount:typeof t.data.messageCount=="number"?t.data.messageCount:void 0,toolCount:typeof t.data.toolCount=="number"?t.data.toolCount:void 0,lastUserMessagePreview:typeof t.data.lastUserMessagePreview=="string"?t.data.lastUserMessagePreview:void 0,requestBody:typeof t.data.requestBody=="string"?t.data.requestBody:void 0});return}if(t.type==="turn_complete"){const s=Ot(t.data.usage);if(s){const a=e.adapterSession.totalUsage.inputTokens,i=a>0&&s.inputTokens<Math.floor(a*.2)&&!s.hasCache;k(`turn_complete usage: raw=${JSON.stringify(t.data.usage)} parsed=${JSON.stringify(s)} currentInput=${a} threshold20pct=${Math.floor(a*.2)} isFallbackUsage=${i}`),i?s.outputTokens>0&&(e.adapterSession.totalUsage.outputTokens=s.outputTokens):(e.adapterSession.totalUsage.inputTokens=s.inputTokens,e.adapterSession.totalUsage.outputTokens=s.outputTokens),(s.cacheHitTokens||s.cacheMissTokens)&&(e.adapterSession.totalUsage.cacheHitTokens=s.cacheHitTokens,e.adapterSession.totalUsage.cacheMissTokens=s.cacheMissTokens,l(`[ACode] \u{1F4B0} Cache usage (overwrite from runtime cumulative): hit=${e.adapterSession.totalUsage.cacheHitTokens}, miss=${e.adapterSession.totalUsage.cacheMissTokens} (turn delta: hit=${s.cacheHitTokens||0}, miss=${s.cacheMissTokens||0})`)),k(`totalUsage after turn_complete: ${JSON.stringify(e.adapterSession.totalUsage)}`)}else k(`turn_complete has NO parseable usage: raw=${JSON.stringify(t.data.usage)} failed=${t.data.failed===!0} aborted=${t.data.aborted===!0}`);const o=e.adapterSession.status;if(l(`[ACode] turn_complete event received (session: ${t.sessionId}), previous status: ${o}, failed: ${t.data.failed===!0}, aborted: ${t.data.aborted===!0}`),Rt(t.data)){l(`[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)){l(`[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",this.emit("status-change",t.sessionId,"waiting_input",{usage:e.adapterSession.totalUsage}),k(`status-change emitted (waiting_input after turn_complete): usage=${JSON.stringify(e.adapterSession.totalUsage)}`),l(`[ACode] Status changed to waiting_input after turn_complete (session: ${t.sessionId})`),e.autoPollActive&&e.autoPollObservedAssistantText&&!e.autoPollObservedPollingTool&&!e.autoPollObservedAnyTool){e.stopAutoPollAfterCurrentTurn=!0,console.warn(`[${this.displayName}] Auto-poll turn produced assistant text without calling any tool; stopping auto-poll rearm for session ${t.sessionId}`);return}this.armIdleLoopOrAutoPoll(t.sessionId);return}if(t.type==="session_complete"){this.cancelDataFlowWatchdog(e),this.cancelScheduledAutoPoll(e),e.failedTurnRecoveryScheduled=!1,e.idlePollLoop?.stop(),e.adapterSession.status="completed",this.emitProviderEvent(t,"session_complete",{exitCode:Number(t.data.exitCode)||0}),this.emit("status-change",t.sessionId,"completed");return}if(t.type==="question_request"){this.cancelDataFlowWatchdog(e),this.cancelSubmitTimeoutDetection(e);const s=typeof t.data.toolCallId=="string"?t.data.toolCallId:"",o=Array.isArray(t.data.questions)?t.data.questions:[];s&&(e.pendingQuestionToolCallId=s,e.pendingQuestions=o),this.emit("ask-user-question",{sessionId:t.sessionId,toolCallId:s||void 0,questions:o});return}if(t.type==="tool_permission_request"){this.cancelDataFlowWatchdog(e),this.cancelSubmitTimeoutDetection(e);const s=typeof t.data.requestId=="string"?t.data.requestId:"";s&&(e.pendingToolAuthRequests||(e.pendingToolAuthRequests=new Map),e.pendingToolAuthRequests.set(s,{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:s,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",this.emitProviderEvent(t,"error",{text:String(t.data.message||"ACode runtime error")}),this.emit("status-change",t.sessionId,"error"),e.autoPollActive||this.recoverTurnFailure(t.sessionId,e);return}if(t.type==="mcp_status"){if(!t.data.action&&Array.isArray(t.data.tools)){const f=t.data.tools;f.some(T=>gt(T))||console.warn(`[${this.displayName}] ACode runtime is not exposing a poll_message tool. The LLM cannot call poll_message. Please configure an MCP server that provides poll_message (e.g. aws-mcp) in the dashboard panel for this runtime.`);const y=Array.isArray(t.data.servers)?t.data.servers:[],S=f.map(T=>({name:String(T.name??""),source:String(T.source??""),description:String(T.description??"")})).filter(T=>T.name),_={kind:"mcp",mcpServers:y,mcpTools:S};e.cachedMcpCapabilities=_,e.lastMcpCapabilities=_,e.lastCombinedCapabilities={kind:"combined",mcpServers:y,mcpTools:S,skills:e.lastCombinedCapabilities?.skills??[],skillsDir:e.lastCombinedCapabilities?.skillsDir,skillGroups:e.lastCombinedCapabilities?.skillGroups??[]},l(`[cap-diag] MCP capabilities cached: ${y.length} servers, ${S.length} tools`,{sessionId:t.sessionId,servers:y,toolNames:S.map(T=>T.name)}),e.capabilitiesFallbackTimer&&clearTimeout(e.capabilitiesFallbackTimer),e.capabilitiesFallbackTimer=setTimeout(()=>{const T=e.cachedMcpCapabilities;if(!T)return;const C={...T,skills:[],skillGroups:[]};this.emitProviderEvent(t,"runtime_capabilities",{capabilities:C,actionType:"runtime_capabilities",actionLabel:"\u8FD0\u884C\u65F6\u80FD\u529B",actionDetail:JSON.stringify(C)}),l(`[cap-diag] MCP capabilities emitted via fallback (skill_status not received within ${Q}ms)`,{sessionId:t.sessionId,mcpServers:T.mcpServers,mcpToolsCount:T.mcpTools?.length??0}),e.cachedMcpCapabilities=void 0,e.capabilitiesFallbackTimer=void 0},Q);return}const s=String(t.data.action??"");l(`[ACode] \u{1F4E1} mcp_status event: action=${s}, 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 o=typeof t.data.server=="string"?t.data.server:"mcp",a=typeof t.data.tool=="string"?t.data.tool:"",i=o&&a?`${o}__${a}`:a||o,r=t.data.arguments&&typeof t.data.arguments=="object"&&!Array.isArray(t.data.arguments)?t.data.arguments:void 0,n=At(i,r);e.autoPollActive&&(e.autoPollObservedAnyTool=!0,n.actionType==="idle"&&(e.autoPollObservedPollingTool=!0));const c=It(n.actionType)?n.actionDetail||Y(void 0,o,a):Y(n.actionDetail,o,a),u=typeof t.data.toolUseId=="string"?t.data.toolUseId:void 0,m=r?JSON.stringify(r,null,2):void 0,p={toolName:c,rawToolName:i,actionType:n.actionType,actionLabel:n.actionLabel,actionDetail:c,...m?{actionInput:m}:{},...r?{toolInput:r}:{},...u?{toolUseId:u,actionId:u}:{},metadata:{mcpServer:o}};if(t.data.action==="tool_result"){this.emitProviderEvent(t,"tool_use_end",{...p,toolResult:typeof t.data.result=="string"?t.data.result:JSON.stringify(t.data.result??"")});const f=n.actionType==="idle"&&!Ut(t.data.result)?"waiting_input":"thinking";e.adapterSession.status=f,n.actionType==="idle"&&(e.idleToolActiveAt=void 0),this.cancelDataFlowWatchdog(e),e.pendingToolEventData=void 0;const A=n.actionType==="idle";this.emit("status-change",t.sessionId,f,A||f==="thinking"?void 0:p);return}const g=n.actionType==="idle"?"waiting_input":"tool_using";e.adapterSession.status=g,n.actionType==="idle"&&(e.idleToolActiveAt=Date.now()),g==="tool_using"&&(this.resetDataFlowWatchdog(t.sessionId,e),e.pendingToolEventData={...p}),this.emitProviderEvent(t,"tool_use_start",p),this.emit("status-change",t.sessionId,g,p);return}if(t.type==="skill_status"){const o=(Array.isArray(t.data.skills)?t.data.skills:[]).map(m=>({name:String(m.name??""),description:typeof m.description=="string"?m.description:void 0,directory:typeof m.directory=="string"?m.directory:void 0})).filter(m=>m.name),a=typeof t.data.skillsDir=="string"?t.data.skillsDir:void 0,r=(Array.isArray(t.data.skillGroups)?t.data.skillGroups:[]).map(m=>{const p=Array.isArray(m.skills)?m.skills:[];return{dir:typeof m.dir=="string"?m.dir:"",exists:m.exists===!0,skills:p.map(g=>({name:String(g.name??""),description:typeof g.description=="string"?g.description:void 0,directory:typeof g.directory=="string"?g.directory:void 0})).filter(g=>g.name)}}).filter(m=>m.dir),n=e.cachedMcpCapabilities??e.lastMcpCapabilities,c=e.cachedMcpCapabilities!==void 0,u={kind:"combined",mcpServers:n?.mcpServers??[],mcpTools:n?.mcpTools??[],skills:o,skillsDir:a,skillGroups:r};this.emitProviderEvent(t,"runtime_capabilities",{capabilities:u,actionType:"runtime_capabilities",actionLabel:"\u8FD0\u884C\u65F6\u80FD\u529B",actionDetail:JSON.stringify(u)}),e.lastCombinedCapabilities=u,l(`[cap-diag] Combined capabilities emitted ${c?"(startup merge)":"(runtime refresh)"}: ${(n?.mcpTools??[]).length} MCP tools, ${o.length} skills`,{sessionId:t.sessionId,mcpServers:n?.mcpServers??[],skillsDir:a}),e.capabilitiesFallbackTimer&&(clearTimeout(e.capabilitiesFallbackTimer),e.capabilitiesFallbackTimer=void 0),e.cachedMcpCapabilities=void 0;return}if(t.type==="startup_phase"){l(`[ACode] \u{1F680} startup_phase swallowed: ${String(t.data.phase??"unknown")}`,{sessionId:t.sessionId});return}if(t.type==="command_status"){if(t.data.action==="commands_loaded"){l(`[ACode] \u{1F4CB} command_status commands_loaded swallowed: ${typeof t.data.installedCommandCount=="number"?t.data.installedCommandCount:"?"} commands`,{sessionId:t.sessionId});return}this.emitProviderEvent(t,"thinking",{text:JSON.stringify(t.data)});return}if(t.type==="session_started"){const s=z(t.data),o=h(t.data.contextLimit)||void 0,a=h(t.data.maxOutput)||void 0,i=h(t.data.inputLimit)||void 0,r=h(t.data.compactionThreshold)||void 0;let n=!1;s>0&&(e.adapterSession.totalUsage.inputTokens=s,e.adapterSession.totalUsage.outputTokens=0,n=!0),o!==void 0&&(e.adapterSession.totalUsage.contextLimit=o,n=!0),a!==void 0&&(e.adapterSession.totalUsage.maxOutput=a,n=!0),i!==void 0&&(e.adapterSession.totalUsage.inputLimit=i,n=!0),r!==void 0&&(e.adapterSession.totalUsage.compactionThreshold=r,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 s=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:s||"\u9000\u51FA\u8BA1\u5212\u6A21\u5F0F"}),this.emit("status-change",t.sessionId,"waiting_input",{actionLabel:"\u5BA1\u6279\u8BA1\u5212",actionDetail:s||"\u7B49\u5F85\u7528\u6237\u5BA1\u6279\u9000\u51FA\u8BA1\u5212\u6A21\u5F0F"});return}if(t.type==="context_compaction"){const s=t.data,o=s.action,a=o==="start",i=o==="end",r=o==="phase",n=s.parentId,c=s.compactionId;let u,m;if(a){const g=String(s.sizeKB??s.sizeBeforeKB??"?"),f=String(s.messageCount??s.messageCountBefore??"?"),A=s.estimatedTokens,y=s.actualInputTokens?`input=${s.actualInputTokens}`:"",S=s.actualOutputTokens?`output=${s.actualOutputTokens}`:"",_=s.trigger?`, \u89E6\u53D1: ${s.trigger}`:"";u="\u4E0A\u4E0B\u6587\u538B\u7F29\u5F00\u59CB",A!==void 0?m=`\u538B\u7F29\u524D: ~${A} tokens, \u6D88\u606F: ${f}\u6761`+(y?`, \u5B9E\u9645 tokens: ${y} ${S}`:"")+_:m=`\u538B\u7F29\u524D: ${g}KB, \u6D88\u606F: ${f}\u6761`+(y?`, \u5B9E\u9645 tokens: ${y} ${S}`:"")+_}else if(r)u=String(s.phaseLabel??"\u538B\u7F29\u9636\u6BB5"),m=String(s.phaseDetail??"");else{const g=s.tokensBefore,f=s.tokensAfter,A=s.freedTokens,y=String(s.sizeBeforeKB??"?"),S=String(s.sizeAfterKB??"?"),_=String(s.freedKB??"?"),T=String(s.strategy??"?"),C=Number(s.prunedToolMessages??0),b=Number(s.summarizedMessages??0);u="\u538B\u7F29\u5B8C\u6210",g!==void 0&&f!==void 0?m=`\u91CA\u653E: ${A??g-f} tokens, ${g} tokens \u2192 ${f} tokens, \u7B56\u7565: ${T}`+(C?`, \u88C1\u526A\u5DE5\u5177: ${C}\u6761`:"")+(b?`, \u6458\u8981\u5316: ${b}\u6761`:""):m=`\u91CA\u653E: ${_}KB, ${y}KB \u2192 ${S}KB, \u7B56\u7565: ${T}`+(C?`, \u88C1\u526A\u5DE5\u5177: ${C}\u6761`:"")+(b?`, \u6458\u8981\u5316: ${b}\u6761`:"")}a&&(e.adapterSession.status="compacting");const p={actionType:"context_compaction",actionLabel:u,actionDetail:m};if(a&&c)p.actionId=c;else if((r||i)&&c)if(p.parentId=c,r){const g=String(s.phase??"unknown");p.actionId=`${c}-phase-${g}`}else p.actionId=`${c}-end`;r&&n&&!p.parentId&&(p.parentId=n),i&&(e.adapterSession.totalUsage.inputTokens=h(s.tokensAfter),e.adapterSession.totalUsage.outputTokens=0,e.config.agentId&&$.markAgentCompacted(e.config.agentId),p.usage={...e.adapterSession.totalUsage}),this.emitProviderEvent(t,"context_compaction",p),this.emit("status-change",t.sessionId,"compacting",p);return}this.emitProviderEvent(t,"thinking",{text:JSON.stringify(t.data)})}}emitProviderEvent(t,e,s){this.emit("event",{type:e,sessionId:t.sessionId,timestamp:t.timestamp,data:s})}armIdleLoopOrAutoPoll(t){const e=this.sessions.get(t);if(!(!e||this.isTerminalStatus(e.adapterSession.status))){if(this.cancelRequestRetry(e),e.retryAttempt=0,e.idleCommands?.idleInputCommand){this.getIdlePollLoop(e).start();return}this.scheduleAutoPoll(t)}}getIdlePollLoop(t){if(t.idlePollLoop)return t.idlePollLoop;const e=t.adapterSession.sessionId;return t.idlePollLoop=new ft({getStatus:()=>this.sessions.get(e)?.adapterSession.status,getCommand:()=>this.sessions.get(e)?.idleCommands?.idleInputCommand,isPollingCommand:s=>M(s),preDispatchHook:()=>null,dispatchPollingPrompt:(s,o)=>this.submitAutoPollPrompt(e,o?s:Pt,{keepWaitingStatus:!0}),dispatchRegularIdleCommand:s=>this.submitAutoPollPrompt(e,s)}),t.idlePollLoop}submitAutoPollPrompt(t,e,s){const o=this.sessions.get(t);if(!o||this.isTerminalStatus(o.adapterSession.status))return;const a=(o.autoPollToken??0)+1;o.autoPollToken=a,o.autoPollActive=!0,o.autoPollObservedPollingTool=!1,o.autoPollObservedAssistantText=!1,o.autoPollObservedAnyTool=!1,o.stopAutoPollAfterCurrentTurn=!1,o.autoPollQueuedAt=Date.now(),o.autoPollLastActivityAt=Date.now(),o.idleToolActiveAt=void 0,o.lastSubmittedPrompt=e,s?.keepWaitingStatus||(o.adapterSession.status="thinking",this.emit("status-change",t,"thinking")),this.startSubmitTimeoutDetection(t,o,"submitAutoPollPrompt"),o.runtime.submit(e).catch(i=>{this.emitRuntimeErrorEvent(t,i),this.scheduleRequestRetry(t,"submitAutoPollPrompt")}).finally(()=>{const i=this.sessions.get(t);if(i){if(i.autoPollToken!==a){l(`[ACode] submitAutoPollPrompt.finally: token mismatch (my=${a}, current=${i.autoPollToken}), skipping cleanup \u2014 newer turn has taken over`);return}if(this.cancelSubmitTimeoutDetection(i),i.autoPollActive=!1,i.failedTurnRecoveryScheduled||i.autoPollTimer){i.failedTurnRecoveryScheduled=!1;return}if(i.stopAutoPollAfterCurrentTurn){i.stopAutoPollAfterCurrentTurn=!1,i.autoPollObservedPollingTool=!1,i.autoPollObservedAssistantText=!1,i.autoPollObservedAnyTool=!1;return}if(i.adapterSession.status==="error"){this.recoverTurnFailure(t,i);return}if(i.adapterSession.status==="thinking"||i.adapterSession.status==="tool_using"){this.recoverResolvedTurnWithoutTerminalEvent(t);return}i.adapterSession.status==="waiting_input"&&this.armIdleLoopOrAutoPoll(t)}})}scheduleAutoPoll(t,e=wt){const s=this.sessions.get(t);!s||s.autoPollActive||s.autoPollTimer||this.isTerminalStatus(s.adapterSession.status)||(s.autoPollTimer=setTimeout(()=>{const o=this.sessions.get(t);!o||o.autoPollActive||this.isTerminalStatus(o.adapterSession.status)||(o.autoPollTimer=void 0,this.submitAutoPollPrompt(t,St,{keepWaitingStatus:!0}))},e))}cancelScheduledAutoPoll(t){t.autoPollTimer&&(clearTimeout(t.autoPollTimer),t.autoPollTimer=void 0)}scheduleRequestRetry(t,e){const s=this.sessions.get(t);if(!s||this.isTerminalStatus(s.adapterSession.status)||s.retryActive||s.retryTimer)return;if(!s.lastSubmittedPrompt){s.adapterSession.status="error",this.emit("status-change",t,"error");return}s.retryAttempt+=1,s.retryActive=!0,this.cancelScheduledAutoPoll(s),s.idlePollLoop?.stop();const o=H[Math.min(s.retryAttempt-1,H.length-1)];s.adapterSession.status="error",this.emit("status-change",t,"error",{actionType:"retry",actionLabel:"\u91CD\u8BD5\u4E2D",actionDetail:`\u7B2C${s.retryAttempt}\u6B21 \xB7 ${Math.round(o/1e3)}s\u540E`}),l(`[ACode] scheduleRequestRetry(${e}): attempt=${s.retryAttempt} delay=${o}ms`),s.retryTimer=setTimeout(()=>{s.retryTimer=void 0,this.retryFailedRequest(t,e)},o)}retryFailedRequest(t,e){const s=this.sessions.get(t);if(!s)return;if(s.retryTimer=void 0,this.isTerminalStatus(s.adapterSession.status)||!s.lastSubmittedPrompt){s.retryActive=!1;return}s.retryActive=!1;const o=s.lastSubmittedPrompt;l(`[ACode] retryFailedRequest(${e}): attempt=${s.retryAttempt} re-submitting...`),s.adapterSession.status="thinking",this.emit("status-change",t,"thinking",{usage:s.adapterSession.totalUsage}),this.startSubmitTimeoutDetection(t,s,"retryFailedRequest"),s.runtime.submit(o).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),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 s=new Date().toISOString();this.emit("event",{type:"error",sessionId:t,timestamp:s,data:{text:e instanceof Error?e.message:String(e)}})}estimateOutputTokensFromMessages(t){const e=t.filter(s=>s.role==="assistant").map(s=>s.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 o=e.pendingToolEventData;l(`[ACode] recoverTurnFailure: \u8865\u53D1 tool_use_end (tool: ${o.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:{...o,toolResult:"[aborted] \u5DE5\u5177\u6267\u884C\u88AB\u6570\u636E\u6D41\u770B\u95E8\u72D7\u4E2D\u65AD"}}),e.pendingToolEventData=void 0}const s=this.estimateOutputTokensFromMessages(e.adapterSession.messages);if(s>0){const o=e.adapterSession.totalUsage.outputTokens;e.adapterSession.totalUsage.outputTokens=s,l(`[ACode] recoverTurnFailure: \u4F30\u7B97\u8986\u76D6 output tokens ${o} -> ${s} (totalUsage now: input=${e.adapterSession.totalUsage.inputTokens}, output=${e.adapterSession.totalUsage.outputTokens})`)}this.cancelScheduledAutoPoll(e),this.scheduleRequestRetry(t,"recoverTurnFailure")}recoverResolvedTurnWithoutTerminalEvent(t){l(`[ACode] \u25B6\uFE0F recoverResolvedTurnWithoutTerminalEvent called for session ${t}`);const e=this.sessions.get(t);if(!e||this.isTerminalStatus(e.adapterSession.status)){l(`[ACode] Skipping recovery: entry=${!!e}, isTerminal=${e?this.isTerminalStatus(e.adapterSession.status):"N/A"}`);return}if(l(`[ACode] Current status: ${e.adapterSession.status}`),e.adapterSession.status!=="thinking"&&e.adapterSession.status!=="tool_using"){l(`[ACode] Skipping recovery: status is ${e.adapterSession.status} (not thinking/tool_using)`);return}console.warn(`[ACode] \u26A0\uFE0F Detected stuck state: ${e.adapterSession.status} after submit resolved! Recovering to waiting_input. If runtime.submit() is still pending (e.g., built-in tool execution not interruptible by abort()), the submitQueue is deadlocked and subsequent auto-poll/user submits will never execute.`),l("[ACode] Recovering to waiting_input..."),e.adapterSession.status="waiting_input";const s=e.idleCommands?.idleInputCommand,a=!!(s&&M(s))?{actionType:"idle",actionLabel:"\u76D1\u542C\u6D88\u606F",actionDetail:"aws-mcp/poll_message"}:void 0;this.emit("status-change",t,"waiting_input",a),l(`[ACode] \u2705 Recovery complete, status now: ${e.adapterSession.status}`),l("[ACode] \u25B6\uFE0F Arming idle loop or auto-poll..."),this.armIdleLoopOrAutoPoll(t),l("[ACode] \u2705 Idle loop armed, recovery process complete")}startSubmitTimeoutDetection(t,e,s){this.cancelSubmitTimeoutDetection(e),e.watchdogSubmitStartTime=Date.now(),e.watchdogLastDataFlowTime=Date.now(),e.watchdogTimer=setInterval(()=>{const o=this.sessions.get(t);if(!o){this.cancelSubmitTimeoutDetection(e);return}const a=o.adapterSession.status,i=Date.now();if(a==="waiting_input"){if(o.autoPollActive&&o.autoPollLastActivityAt&&o.idleToolActiveAt===void 0&&i-o.autoPollLastActivityAt>=kt){console.warn(`[ACode] CRITICAL: stuck auto-poll detected after ${Math.round((i-o.autoPollLastActivityAt)/1e3)}s (source: ${s}, 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,o,s,"stuck_autopoll",i-o.autoPollLastActivityAt);return}o.watchdogSubmitStartTime=i,o.watchdogLastDataFlowTime=i;return}if(a==="tool_using"){const c=i-(o.watchdogLastDataFlowTime||i);if(c>=Ct){const u=String(o.pendingToolEventData?.rawToolName??"");if((o.pendingToolAuthRequests?.size??0)>0){const m=o.pendingToolAuthRequests?.size??0;console.warn(`[ACode] tool_using elapsed ${Math.round(c/1e3)}s but ${m} tool permission request(s) awaiting user decision (session: ${t}), skipping recovery`),o.watchdogSubmitStartTime=i,o.watchdogLastDataFlowTime=i;return}if(u.endsWith("await_complete")){console.warn(`[ACode] tool_using elapsed ${Math.round(c/1e3)}s but await_complete is running (session: ${t}, tool: ${u}), skipping recovery (sub-agents have their own watchdogs, bg commands have timeout limits)`),o.watchdogSubmitStartTime=i,o.watchdogLastDataFlowTime=i;return}if(console.warn(`[ACode] CRITICAL: tool_using slow timeout triggered after ${Math.round(c/1e3)}s (source: ${s}, session: ${t}). Tool execution likely hung. Forcing recovery via recoverTurnFailure.`),o.runtime.detachCurrentToolExecution?.()){console.warn(`[ACode] tool_using slow (${Math.round(c/1e3)}s): detached tool ${u} to background (session: ${t}); waiting for the real tool_result to continue the turn`),o.watchdogSubmitStartTime=i,o.watchdogLastDataFlowTime=i;return}this.executeWatchdogRecovery(t,o,s,"tool_using_slow",c);return}o.watchdogSubmitStartTime=i;return}if(a!=="thinking")return;const r=i-(o.watchdogSubmitStartTime||i),n=i-(o.watchdogLastDataFlowTime||i);if(K>0&&n>=K){console.warn(`[ACode] CRITICAL: Data flow watchdog triggered after ${Math.round(n/1e3)}s (source: ${s}, session: ${t}, status: ${a}). No stream data received. Forcing recovery via recoverTurnFailure.`),this.executeWatchdogRecovery(t,o,s,"data_flow",n);return}if(j>0&&r>=j){console.warn(`[ACode] CRITICAL: submit timeout detected after ${Math.round(r/1e3)}s (source: ${s}, session: ${t}, status: ${a}). Forcing recovery to prevent permanent state stuck.`),this.executeWatchdogRecovery(t,o,s,"submit_timeout",r);return}},_t)}executeWatchdogRecovery(t,e,s,o,a){l(`[ACode] Watchdog (${o}): calling runtime.abort() after ${Math.round(a/1e3)}s...`);try{e.runtime.abort(),l(`[ACode] Watchdog (${o}): runtime.abort() called`)}catch(i){console.warn(`[ACode] \u26A0\uFE0F Watchdog (${o}): runtime.abort() threw: ${i instanceof Error?i.message:String(i)}`)}this.cancelSubmitTimeoutDetection(e),this.recoverTurnFailure(t,e),console.warn(`[ACode] \u26A0\uFE0F Watchdog (${o}) recovery complete. If abort() could not cancel the underlying operation, submitQueue may still be deadlocked.`)}cancelSubmitTimeoutDetection(t){t.watchdogTimer&&(clearInterval(t.watchdogTimer),t.watchdogTimer=void 0),t.watchdogSubmitStartTime=void 0,t.watchdogLastDataFlowTime=void 0}resetDataFlowWatchdog(t,e){e.watchdogLastDataFlowTime=Date.now(),e.watchdogSubmitStartTime=Date.now()}startDataFlowWatchdog(t,e){e.watchdogLastDataFlowTime=Date.now()}cancelDataFlowWatchdog(t){t.watchdogLastDataFlowTime=Date.now()}formatAiRequestActionDetail(t){const e=`
1
+ import{EventEmitter as nt}from"node:events";import rt from"node:fs/promises";import H from"node:path";import{fileURLToPath as lt,pathToFileURL as ut}from"node:url";import{isMcpGroupKey as dt}from"@agentswork/acode";import{v4 as L}from"uuid";import{getBridgeInstancePluginsDir as ct,getBridgeInstanceSkillsDir as pt,getBridgeTemplateConfigFile as M,getBridgeTemplateSkillsDir as mt}from"../config.js";import{getReleasedAcodeEntryPath as ft}from"../services/acode-package.js";import{syncAgentSkillFarm as K}from"../services/agent-capability-sync.js";import{agentPtyManager as gt}from"../services/agent-pty-manager.js";import{getBrowserTools as v,closeBrowserSession as ht,registerListenerWakeHook as Tt,unregisterListenerWakeHook as j}from"../services/browser-session-manager.js";import{getDesktopTools as R,getDesktopToolsIfReady as At}from"../services/desktop-mcp-manager.js";import{redactForLog as G}from"../services/instance-ai-config-service.js";import{BROWSER_FEATURE_KEY as x,DESKTOP_FEATURE_KEY as w,getAgentToolPermissions as yt,getFeatureState as U,isFeatureEnabled as St,resolveAgentToolPermissions as bt,resolveGroupFeatureKey as _t}from"../services/instance-features.js";import{pluginManager as I}from"../services/plugin-manager.js";import{buildRuntimeResourcesSnapshot as Ct}from"../services/runtime-resources-snapshot.js";import{subAgentManager as kt}from"../services/sub-agent-manager-instance.js";import{recordAgentFileChange as Pt}from"../services/workspaceTaskChangeWatcher.js";import{getInstanceAiConfigDebugLogger as F}from"../utils/instance-ai-config-debug-logger.js";import{recordLifecycleEvent as k}from"../utils/lifecycle-log.js";import{isMessagePollingIdleCommand as q,isPollMessageToolDescriptor as wt}from"./acode-tool-names.js";import{IdlePollLoop as $t}from"./idle-poll-loop.js";import{resolveAcodeProviderConfig as Et}from"./instance-ai-config-resolver.js";import{MESSAGE_POLLING_IDLE_PROMPT as z}from"./prompts.js";import{getCanonicalMcpDetail as J,getToolActionInfo as Lt}from"./types.js";const xt=process.env.ACODE_COMPACTION_DEBUG==="1";function r(...l){xt&&console.log(...l)}const It=process.env.ACODE_TOKEN_DEBUG==="1";function P(...l){It&&console.log("[TokenDebug][Adapter]",...l)}const Dt=z,Ot=5e3;function $(l,t){const e=process.env[l];if(e===void 0||e.trim()==="")return t;const o=Number(e.trim());return Number.isFinite(o)&&o>=0?Math.floor(o):t}const Q=$("ACODE_DATA_FLOW_WATCHDOG_MS",12e4),Rt=5*6e4,Mt=$("ACODE_STUCK_AUTOPOLL_TIMEOUT_MS",5*6e4),Y=$("ACODE_LIVENESS_POLL_INTERVAL_MS",15e3),B=$("ACODE_LIVENESS_STALL_TIMEOUT_MS",10*6e4),vt=250,Ut=1e3,Ft=$("ACODE_DEFERRED_IDLE_REARM_MS",3e3),V=[2e3,3e3,1e4,4e4],X=4e3;function Z(l){const t=String(l||"").trim();if(t)return t.length>X?`${t.slice(0,X)}\u2026(truncated)`:t}function qt(l){const t=l.toLowerCase();return/tool[_ ]?call/.test(t)||t.includes("invalid_request")?!0:/(?:failed:\s*|http[\s/]*|status[\s:="']*|code[\s:="']*)(400|401|403|404|422)(?!\d)/.test(t)}const N={[x]:"browser_",[w]:"desktop_"};function Bt(l){if(!l||typeof l!="object")return;const t=l,e=typeof t.exposedName=="string"&&t.exposedName||typeof t.toolName=="string"&&t.toolName||typeof t.name=="string"&&t.name||"";if(!e)return;const o=typeof t.execute=="function"?t.execute:void 0;return{name:e,...typeof t.description=="string"?{description:t.description}:{},...t.inputSchema!==void 0?{inputSchema:t.inputSchema}:{},definition:t,...o?{execute:o}:{}}}const tt=$("ACODE_SUBMIT_TIMEOUT_MS",12e4),et=3e3,Nt=z;function Wt(){return H.resolve(ft())}function Ht(l){return ut(H.resolve(l)).href}const ot=128e3,E={"claude-4":{contextLimit:2e5,maxOutput:8192},"claude-sonnet-4":{contextLimit:2e5,maxOutput:8192},"claude-3-5-sonnet":{contextLimit:2e5,maxOutput:8192},"claude-3-opus":{contextLimit:2e5,maxOutput:8192},"claude-3-haiku":{contextLimit:2e5,maxOutput:8192},"claude-2":{contextLimit:1e5,maxOutput:4096},"gpt-4o":{contextLimit:128e3,maxOutput:16384},"gpt-4-turbo":{contextLimit:128e3,maxOutput:4096},"gpt-4":{contextLimit:8192,maxOutput:4096},"gpt-3.5-turbo":{contextLimit:16384,maxOutput:4096},o1:{contextLimit:2e5,maxOutput:1e5},"o3-mini":{contextLimit:2e5,maxOutput:1e5},"gemini-2.0-flash":{contextLimit:1048576,maxOutput:8192},"gemini-2.5-pro":{contextLimit:1048576,maxOutput:8192},"gemini-1.5-pro":{contextLimit:2097152,maxOutput:8192},"gemini-1.5-flash":{contextLimit:1048576,maxOutput:8192},deepseek:{contextLimit:64e3,maxOutput:8192},"deepseek-chat":{contextLimit:64e3,maxOutput:8192},"deepseek-reasoner":{contextLimit:64e3,maxOutput:8192},"qwen-max":{contextLimit:32e3,maxOutput:8192},"qwen-plus":{contextLimit:128e3,maxOutput:8192},"qwen-turbo":{contextLimit:1e6,maxOutput:8192},"glm-4":{contextLimit:128e3,maxOutput:4096},"yi-":{contextLimit:2e5,maxOutput:4096},"llama-3":{contextLimit:8192,maxOutput:4096},"llama-2":{contextLimit:4096,maxOutput:4096},mistral:{contextLimit:32e3,maxOutput:4096},mixtral:{contextLimit:32e3,maxOutput:4096},codestral:{contextLimit:256e3,maxOutput:8192},grok:{contextLimit:131072,maxOutput:4096},"nova-":{contextLimit:2e5,maxOutput:8192}};function Kt(l){if(!l)return ot;const t=l.toLowerCase().trim(),e=E[t];if(e)return e.contextLimit;const o=Object.keys(E).filter(a=>t.startsWith(a)).sort((a,i)=>i.length-a.length),s=o[0]!==void 0?E[o[0]]:void 0;return s?s.contextLimit:ot}const st=4096;function jt(l){if(!l)return st;const t=l.toLowerCase().trim(),e=E[t];if(e)return e.maxOutput;const o=Object.keys(E).filter(a=>t.startsWith(a)).sort((a,i)=>i.length-a.length),s=o[0]!==void 0?E[o[0]]:void 0;return s?s.maxOutput:st}function it(l){if(!l||typeof l!="object")return;const t=l,e=y(t.inputTokens,t.input_tokens,t.promptTokens,t.prompt_tokens),o=y(t.outputTokens,t.output_tokens,t.completionTokens,t.completion_tokens);if(e===0&&o===0)return;let s=y(t.cacheHitTokens,t.promptCacheHitTokens,t.prompt_cache_hit_tokens),a=y(t.cacheMissTokens,t.promptCacheMissTokens,t.prompt_cache_miss_tokens),i=t.cacheHitTokens!==void 0||t.cacheMissTokens!==void 0||t.promptCacheHitTokens!==void 0||t.promptCacheMissTokens!==void 0||t.prompt_cache_hit_tokens!==void 0||t.prompt_cache_miss_tokens!==void 0;if(s===0&&a===0){const n=y(t.cache_read_input_tokens),c=y(t.cache_creation_input_tokens);if(n>0||c>0){const f=t.input_tokens!==void 0&&Number.isFinite(Number(t.input_tokens))&&Number(t.input_tokens)>=0?y(t.input_tokens):Math.max(0,e-n-c);s=n,a=c+f,i=!0}else s=y(t.cache_hit_tokens),a=y(t.cache_miss_tokens),i=i||t.cache_hit_tokens!==void 0||t.cache_miss_tokens!==void 0}if(s===0&&a===0){const n=y(t.prompt_tokens_details?.cached_tokens);n>0&&(s=n,a=e>n?e-n:0,i=!0)}return{inputTokens:e,outputTokens:o,...i?{cacheHitTokens:s,cacheMissTokens:a}:{},...i?{hasCache:!0}:{}}}function y(...l){for(const t of l){const e=Number(t);if(Number.isFinite(e)&&e>0)return e}return 0}function Gt(l){return l==="stderr"||l==="mixed"?l:"stdout"}function D(l){const t=Number(l);return Number.isFinite(t)?t:0}function W(l){if(l==null)return;const t=Number(l);return Number.isFinite(t)?t:void 0}function zt(l){if(!l||typeof l!="object"||Array.isArray(l))return;const t={};for(const[e,o]of Object.entries(l))typeof o=="string"&&(t[e]=o);return Object.keys(t).length>0?t:void 0}function Jt(l){return l.failed===!0}function at(l,t,e){if(!l)return e?`${t}/${e}`:t;const o=`${t}__`;return l.startsWith(o)?J(`${t}__${l.slice(o.length)}`):J(l.replace("/","__"))}function Qt(l){return l==="read_file"||l==="edit_file"||l==="write_file"||l==="bash"}function Yt(l){const t=Vt(l);return t?[t.directMessages,t.groupMessages,t.messages].some(e=>Array.isArray(e)&&e.length>0):typeof l=="string"&&l.trim().length>0}function Vt(l){if(l&&typeof l=="object"&&!Array.isArray(l))return l;if(!(typeof l!="string"||!l.trim()))try{const t=JSON.parse(l);return t&&typeof t=="object"&&!Array.isArray(t)?t:void 0}catch{return}}class ke extends nt{constructor(){super(),this.providerId="acode",this.displayName="ACode",this.sessions=new Map,this.expandedBuiltInCapabilities=new Map,this.builtInCapabilityToolCache=new Map,this.listenerWakeHooks=new Map,I.setOnPluginsChanged(t=>{this.syncPluginCommands(t)})}async syncPluginCommands(t){try{const e=await I.getPluginCommands(t);for(const o of this.sessions.values())o.config.agentId===t&&o.runtime.addPluginCommands?.(e)}catch(e){r(`[acode-adapter] syncPluginCommands failed for agent ${t}:`,e.message)}}async startSession(t,e){const o=e.mcpConfigPath||M(),{resolved:s,configContextLimit:a,supportsImage:i}=await this.resolveAcodeProvider(e,o),n=s.model,c=a??Kt(n),u=jt(n),f={sessionId:t,status:"starting",messages:[],createdAt:new Date().toISOString(),totalUsage:{inputTokens:0,outputTokens:0,contextLimit:c,maxOutput:u,cacheHitTokens:0,cacheMissTokens:0}};this.sessions.set(t,{adapterSession:f,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 d=this.sessions.get(t);if(!d)throw new Error("ACode session was not initialized");this.startLivenessWatchdog(t,d);const p=()=>{const m=this.sessions.get(t);m&&(m.autoPollDelayMs=void 0,this.getIdlePollLoop(m).start())};this.listenerWakeHooks.set(t,p),Tt(e.agentId,p);try{if(await d.runtime.start(),console.log(`[HIBERNATE-REPLAY] startSession: agentId=${e.agentId??"?"} resumeTranscript=${Array.isArray(d.config.resumeTranscript)?`${d.config.resumeTranscript.length}\u6761`:"\u65E0"} importTranscript\u652F\u6301=${typeof d.runtime.importTranscript=="function"}`),f.status="waiting_input",this.emit("status-change",t,"waiting_input",{usage:d.adapterSession.totalUsage}),d.config.resumeTranscript&&d.runtime.importTranscript)try{const m=await d.runtime.importTranscript(d.config.resumeTranscript);console.log(`[HIBERNATE-REPLAY] importTranscript \u5B8C\u6210: agentId=${e.agentId??"?"} \u91CD\u653E=${m}\u6761 conversation=${d.runtime.exportConversation?.().length??"?"}\u6761`),m>0&&d.adapterSession.messages.push({id:L(),sessionId:t,role:"assistant",content:`[\u4F11\u7720\u6062\u590D] \u5DF2\u91CD\u653E\u4F11\u7720\u524D\u7684 ${m} \u6761\u5BF9\u8BDD\u8BB0\u5F55\uFF0C\u4E0A\u4E0B\u6587\u5DF2\u63A5\u7EED\u3002`,timestamp:new Date().toISOString()})}catch(m){console.error(`[HIBERNATE-REPLAY] importTranscript \u5931\u8D25\uFF08\u964D\u7EA7\u4E3A\u6458\u8981\u901A\u9053\uFF09: agentId=${e.agentId??"?"}`,m instanceof Error?m.stack:m)}e.initialPrompt?.trim()?this.startInitialPromptTurn(t,e.initialPrompt):this.armIdleLoopOrAutoPoll(t)}catch(m){f.status="error",this.emitRuntimeErrorEvent(t,m),this.emit("status-change",t,"error");const T=this.sessions.get(t);throw T?.capabilitiesFallbackTimer&&clearTimeout(T.capabilitiesFallbackTimer),T&&this.stopLivenessWatchdog(T),this.sessions.delete(t),j(e.agentId,this.listenerWakeHooks.get(t)),this.listenerWakeHooks.delete(t),m}}async sendMessage(t,e){const o=Date.now();r("[ACode] \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"),r("[ACode] \u25B6\uFE0F sendMessage STARTED"),r(`[ACode] Session: ${t}`),r(`[ACode] Message: ${e.slice(0,100)}${e.length>100?"...":""}`),r("[ACode] \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");const s=this.requireSession(t),a=s.adapterSession.status;r(`[ACode] Previous status: ${a}`),this.cancelScheduledAutoPoll(s),s.failedTurnRecoveryScheduled=!1,s.idlePollLoop?.stop(),s.idleListeningIntentionallyStopped=!1,this.cancelRequestRetry(s),s.retryAttempt=0,s.retryCircuitBroken=!1,s.retryEpoch+=1,s.turnModelRequestSucceeded=!1;const i={id:L(),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 c=Date.now()-n;this.cancelSubmitTimeoutDetection(s),r(`[ACode] \u2705 runtime.submit() completed in ${c}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 u=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 ${u}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 c=Date.now()-o;console.error(`[ACode] \u274C sendMessage FAILED after ${c}ms:`,n instanceof Error?n.message:String(n)),this.cancelSubmitTimeoutDetection(s),r("[ACode] \u25B6\uFE0F sendMessage failed, scheduling request retry..."),this.emitRuntimeErrorEvent(t,n),this.scheduleRequestRetry(t,"sendMessage"),r(`[ACode] Status after failure: ${s.adapterSession.status}`)}}async sendConfirmation(t,e){}submitToolPermissionDecision(t,e,o){const s=this.sessions.get(t);if(!s)return!1;s.pendingToolAuthRequests?.delete(e);const a=s.runtime.submitToolPermissionDecision?.(e,o)??!1;return a&&this.startSubmitTimeoutDetection(t,s,"submitToolPermissionDecision"),a}getPendingToolAuthRequests(t){const e=this.sessions.get(t);return e?.pendingToolAuthRequests?Array.from(e.pendingToolAuthRequests.entries()).map(([o,s])=>({requestId:o,capability:s.capability,detail:s.detail,requestedAt:s.requestedAt})):[]}async sendQuestionAnswer(t,e){const o=this.sessions.get(t);if(!o)return;const s=o.pendingQuestionToolCallId;if(!s){r(`[AcodeSdkAdapter] sendQuestionAnswer: no pending question for session ${t}`);return}o.pendingQuestionToolCallId=void 0,o.pendingQuestions=void 0,o.runtime.submitQuestionAnswer&&o.runtime.submitQuestionAnswer(s,e),this.startSubmitTimeoutDetection(t,o,"sendQuestionAnswer")}async abortCurrentTurn(t){await this.requireSession(t).runtime.abort()}async resetContext(t){const e=this.requireSession(t);if(this.cancelScheduledAutoPoll(e),e.failedTurnRecoveryScheduled=!1,e.autoPollActive=!1,e.autoPollObservedPollingTool=!1,e.autoPollObservedAssistantText=!1,e.autoPollObservedAnyTool=!1,e.stopAutoPollAfterCurrentTurn=!1,e.idleListeningIntentionallyStopped=!1,e.idlePollLoop?.stop(),!e.runtime.resetContext)throw new Error("ACode runtime does not support context reset");await e.runtime.resetContext(),e.adapterSession.messages=[];const o=e.adapterSession.totalUsage;if(e.adapterSession.totalUsage={inputTokens:0,outputTokens:0,contextLimit:o.contextLimit,maxOutput:o.maxOutput,inputLimit:o.inputLimit,compactionThreshold:o.compactionThreshold,cacheHitTokens:o.cacheHitTokens,cacheMissTokens:o.cacheMissTokens},e.adapterSession.status="waiting_input",this.emit("status-change",t,"waiting_input",{usage:e.adapterSession.totalUsage}),e.config.initialPrompt?.trim()){this.startInitialPromptTurn(t,e.config.initialPrompt);return}this.armIdleLoopOrAutoPoll(t)}async terminateSession(t){const e=this.sessions.get(t);if(!e)return;this.cancelScheduledAutoPoll(e),e.failedTurnRecoveryScheduled=!1,e.idlePollLoop?.stop(),this.stopLivenessWatchdog(e),this.cancelRequestRetry(e),e.capabilitiesFallbackTimer&&(clearTimeout(e.capabilitiesFallbackTimer),e.capabilitiesFallbackTimer=void 0),await e.runtime.stop();const o=e.config.agentId;o&&(j(o,this.listenerWakeHooks.get(t)),ht(o)),this.listenerWakeHooks.delete(t),e.adapterSession.status="terminated",this.sessions.delete(t),o&&![...this.sessions.values()].some(s=>s.config.agentId===o)&&(this.expandedBuiltInCapabilities.delete(o),this.builtInCapabilityToolCache.delete(o)),this.emit("status-change",t,"terminated")}getConversation(t){return this.sessions.get(t)?.adapterSession.messages??[]}exportRawTranscript(t){const e=this.sessions.get(t);if(e?.runtime.exportConversation)try{const o=e.runtime.exportConversation();return Array.isArray(o)?o:void 0}catch{return}}async importRawTranscript(t,e){const o=this.sessions.get(t);return!o?.runtime.importTranscript||!Array.isArray(e)?0:o.runtime.importTranscript(e)}hasSession(t){return this.sessions.has(t)}getProviderSessionId(t){return this.sessions.has(t)?t:void 0}getSessionStatus(t){return this.sessions.get(t)?.adapterSession.status}getTotalUsage(t){const e=this.sessions.get(t)?.adapterSession.totalUsage;if(e)return{inputTokens:e.inputTokens,outputTokens:e.outputTokens}}notifyForceMessage(t){const e=this.sessions.get(t);return e?.runtime?.notifyForceMessage?(e.autoPollDelayMs=void 0,e.runtime.notifyForceMessage(),!0):!1}getCapabilities(t){return this.sessions.get(t)?.lastCombinedCapabilities}async resolveAgentAiInfo(t){try{const e=[...this.sessions.values()].find(i=>i.config.agentId===t);if(!e)return;const o=e.config.mcpConfigPath||M(),{resolved:s,supportsImage:a}=await this.resolveAcodeProvider(e.config,o);return s?.model?{model:s.model,supportsImage:a===!0,...s.baseURL?{baseURL:s.baseURL}:{},...s.apiKey?{apiKey:s.apiKey}:{}}:void 0}catch{return}}resolveAgentSkillsDir(t){if(t){try{const e=K(t);if(e)return e}catch(e){r(`[acode-adapter] skill farm sync failed for agent ${t}:`,e.message)}return pt(t)}return mt()}async applyAgentFeatures(t){if(!t)return;const e=this.shouldInjectCapabilityTools(t,w),o=this.shouldInjectCapabilityTools(t,x);for(const[a,i]of this.sessions){if(i.config.agentId!==t)continue;const n=i.runtime,c=e,u=o;try{if(c){const f=await R(t,await this.resolveAgentAiInfo(t)),d=n.addBuiltInTools?.(f)??0;d>0&&r(`[acode-adapter] session ${a}: ${d} desktop tools hot-added for agent ${t}`)}else{const f=n.removeBuiltInToolsByPrefix?.("desktop_")??0;f>0&&r(`[acode-adapter] session ${a}: ${f} desktop tools hot-removed for agent ${t}`)}}catch(f){r(`[acode-adapter] session ${a}: desktop feature hot-sync failed for agent ${t}:`,f.message)}if(u)try{const f=await v(t,i.config.scopeKey,typeof i.config.browserAllowPrivate=="boolean"?{allowPrivate:i.config.browserAllowPrivate}:void 0),d=n.addBuiltInTools?.(f)??0;d>0&&r(`[acode-adapter] session ${a}: ${d} browser tools hot-added for agent ${t}`)}catch(f){r(`[acode-adapter] session ${a}: browser feature hot-sync failed for agent ${t}:`,f.message)}else{const f=n.removeBuiltInToolsByPrefix?.("browser_")??0;f>0&&r(`[acode-adapter] session ${a}: ${f} browser tools hot-removed for agent ${t}`)}}this.syncMcpToolsForAgent(t);try{K(t)}catch(a){r(`[acode-adapter] skill farm hot-sync failed for agent ${t}:`,a.message)}try{await I.applyCapabilities(t)}catch(a){r(`[acode-adapter] plugin capability hot-sync failed for agent ${t}:`,a.message)}const s=bt(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)}}}shouldInjectCapabilityTools(t,e){return t?U(t,e)==="expanded":!0}resolveCapabilityToolPrefix(t){return N[String(t??"").trim()]}async loadCapabilityToolsForSession(t,e,o){const s=t===x?await v(e,o.config.scopeKey,typeof o.config.browserAllowPrivate=="boolean"?{allowPrivate:o.config.browserAllowPrivate}:void 0):await R(e,await this.resolveAgentAiInfo(e)),a=[];for(const i of s){const n=Bt(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(([,u])=>u.config.agentId===s);if(i.length===0)return{sessions:0,tools:0};if(o==="collapse"){let u=0;for(const[f,d]of i){const p=d.runtime.removeBuiltInToolsByPrefix?.(a)??0;u+=p,p>0&&r(`[acode-adapter] session ${f}: ${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=${u}`),{sessions:i.length,tools:u}}const n=new Map;for(const[u,f]of i){let d;try{d=await this.loadCapabilityToolsForSession(e,s,f)}catch(p){throw r(`[acode-adapter] session ${u}: capability ${e} tool load failed for agent ${s}:`,p.message),p}for(const p of d)n.has(p.name)||n.set(p.name,p)}const c=this.expandedBuiltInCapabilities.get(s)??new Set;return c.add(e),this.expandedBuiltInCapabilities.set(s,c),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(u=>({name:u.name,...u.description!==void 0?{description:u.description}:{},...u.inputSchema!==void 0?{inputSchema:u.inputSchema}:{}}))}}async callBuiltInCapabilityTool(t,e,o,s){const a=String(t??"").trim(),i=this.resolveCapabilityToolPrefix(e);if(!i)return{ok:!1,error:`\u672A\u77E5\u80FD\u529B\u300C${String(e)}\u300D\uFF1A\u4EC5\u652F\u6301 browser / desktop`};const n=String(o??"").trim();if(!n)return{ok:!1,error:"\u5DE5\u5177\u540D\u7F3A\u5931"};if(!n.startsWith(i))return{ok:!1,error:`\u5DE5\u5177\u300C${n}\u300D\u4E0D\u5C5E\u4E8E\u80FD\u529B\u300C${e}\u300D`};if(a&&U(a,e)==="disabled")return{ok:!1,error:`\u80FD\u529B\u300C${e}\u300D\u5DF2\u7981\u7528\uFF0C\u65E0\u6CD5\u8C03\u5EA6\u8BE5\u5DE5\u5177`};if(!(this.expandedBuiltInCapabilities.get(a)?.has(e)??!1))return{ok:!1,error:`\u80FD\u529B\u300C${e}\u300D\u5C1A\u672A\u5C55\u5F00\uFF0C\u8BF7\u5148\u8C03\u7528 expand_tools \u5C55\u5F00\u540E\u518D\u8C03\u5EA6\u8BE5\u5DE5\u5177`};const u=this.builtInCapabilityToolCache.get(a)?.get(n);return u?typeof u.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 u.execute.call(u.definition,s??{})}:{ok:!1,error:`\u5DE5\u5177\u300C${n}\u300D\u65E0\u7F13\u5B58\u5B9A\u4E49\uFF0C\u8BF7\u91CD\u65B0\u8C03\u7528 expand_tools \u5237\u65B0`}}getPendingQuestion(t){const e=this.sessions.get(t);if(e?.pendingQuestionToolCallId)return{toolCallId:e.pendingQuestionToolCallId,questions:e.pendingQuestions??[]}}cleanup(){for(const t of this.sessions.keys())this.terminateSession(t)}setIdleCommands(t,e){const o=this.sessions.get(t);if(o){if(o.idleCommands=e,this.cancelScheduledAutoPoll(o),e.idleInputCommand&&q(e.idleInputCommand)){this.getIdlePollLoop(o).start();return}o.adapterSession.status==="waiting_input"&&(e.idleInputCommand||e.nonInputCommand)&&this.getIdlePollLoop(o).start()}}setRuntimeConstructorForTest(t){this.runtimeConstructor=t}async loadAcodeProviderSection(t){try{const e=await rt.readFile(t,"utf-8"),o=JSON.parse(e),a=o.provider?.default,i=a?.options,n=y(o.contextLimit),c={},u={},f=a?.models;if(f&&typeof f=="object"){for(const[d,p]of Object.entries(f))if(p&&typeof p=="object"){const m=y(p.contextLimit);m>0&&(c[d.trim()]=m);const T=p.modalities?.input,g=Array.isArray(T)&&T.includes("image")||p.supportsImageInput===!0;u[d.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(c).length>0?{modelContextLimits:c}:{},...Object.keys(u).length>0?{modelImageSupport:u}:{}}}catch(e){const o=e instanceof Error?e.message:String(e);return F().log({level:"warn",category:"load",message:`loadAcodeProviderSection failed: ${t}: ${o}`,source:"bridge"}),{}}}async resolveAcodeProvider(t,e){const o=typeof t.model=="string"&&t.model.trim()?t.model.trim():void 0,s=F();s.log({level:"info",category:"resolve",message:"resolveAcodeProvider \u8F93\u5165",source:"bridge",details:{configModel:t.model??null,configInstanceAiConfig:t.instanceAiConfig?G(t.instanceAiConfig):null,configPath:e}});const a={...t.instanceAiConfig?.model?{model:t.instanceAiConfig.model}:{},...t.instanceAiConfig?.baseURL?{baseURL:t.instanceAiConfig.baseURL}:{},...t.instanceAiConfig?.apiKey?{apiKey:t.instanceAiConfig.apiKey}:{},...t.instanceAiConfig?.effort?{effort:t.instanceAiConfig.effort}:{},...o?{model:o}:{}},i=await this.loadAcodeProviderSection(e);let n=i.contextLimit;if(!n&&i.modelContextLimits){const u=o||t.instanceAiConfig?.model||i.model;u&&i.modelContextLimits[u]&&(n=i.modelContextLimits[u])}const c=Et(a,i,"acode-default");return s.log({level:"info",category:"resolve",message:"resolveAcodeProvider \u89E3\u6790\u7ED3\u679C",source:"bridge",details:{instanceConfig:G(a),globalConfigModel:i?.model??null,resolvedModel:c.model,resolvedBaseURL:c.baseURL??null,resolvedApiKey:c.apiKey?"[set]":null,configContextLimit:n,resolvedSource:c.source}}),{resolved:c,configPath:e,perSessionModel:o,configContextLimit:n,supportsImage:i.modelImageSupport?.[c.model]===!0}}async createRuntime(t,e,o,s,a){const i=await this.loadRuntimeConstructor(),n=o.mcpConfigPath||M();let c=[];try{c=await v(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 u=[];if(this.shouldInjectCapabilityTools(o.agentId??"",x)&&(u=c),o.agentId&&this.shouldInjectCapabilityTools(o.agentId,w))try{const p=s?.model?{model:s.model,supportsImage:a===!0,...s.baseURL?{baseURL:s.baseURL}:{},...s.apiKey?{apiKey:s.apiKey}:{}}:void 0,m=await R(o.agentId,p);m.length>0&&(u=[...u,...m])}catch(p){r(`[acode-adapter] desktop tools injection skipped for agent ${o.agentId}:`,p.message)}const f=new i({sessionId:t,agentId:o.agentId,workingDirectory:o.workingDirectory,configPath:n,skillsDir:this.resolveAgentSkillsDir(o.agentId),pluginsDir:o.agentId?ct(o.agentId):void 0,model:e,systemPrompt:typeof o.systemPrompt=="string"?o.systemPrompt:void 0,globalPrompt:typeof o.globalPrompt=="string"?o.globalPrompt:void 0,rolePrompt:typeof o.rolePrompt=="string"?o.rolePrompt:void 0,memory:typeof o.memory=="string"?o.memory:void 0,resumeContext:typeof o.resumeContext=="string"?o.resumeContext:void 0,env:o.envOverrides,subAgentManager:kt,terminalManager:gt,capabilityState:p=>dt(p)?"collapsed":U(o.agentId??"",_t(p)),capabilityToolRelay:o.agentId?{handlesGroup:p=>this.resolveCapabilityToolPrefix(p)!==void 0,handlesTool:p=>Object.values(N).some(m=>p.startsWith(m)),expand:async p=>(await this.setBuiltInCapabilityTools(o.agentId??"",p,"expand")).manifests??[],collapse:async p=>{await this.setBuiltInCapabilityTools(o.agentId??"",p,"collapse")},call:async(p,m)=>{const T=p.startsWith(N[w]??"desktop_")?w:x;return this.callBuiltInCapabilityTool(o.agentId??"",T,p,m)}}:void 0,pluginBridge:o.agentId?I.forAgent(o.agentId):void 0,runtimeResourcesProvider:o.agentId?()=>Ct(o.agentId):void 0,commandDirs:[lt(new URL("../services/builtin-commands/",import.meta.url))],...o.subAgentModel?{subAgentModel:o.subAgentModel}:{},...o.subAgentEffort?{subAgentEffort:o.subAgentEffort}:{},...o.instanceAiConfig?.effort?{effort:o.instanceAiConfig.effort}:{},onFileChange:p=>Pt({...p,agentId:o.agentId,workspacePath:o.workingDirectory}),extraBuiltInTools:u,...o.agentId?{toolPermissionPolicy:yt(o.agentId)??void 0}:{},subAgentSuiteTools:c,subAgentSuiteToolProvider:this.buildSubAgentSuiteToolProvider(o.agentId)});return F().log({level:"info",category:"resolve",message:"ACode provider resolved",source:"bridge",sessionId:t,details:{resolvedModel:e,perInstanceModel:o.instanceAiConfig?.model||null,perInstanceBaseURL:o.instanceAiConfig?.baseURL?"[set]":null,perInstanceApiKey:o.instanceAiConfig?.apiKey?"[set]":null,configPath:n}}),f.on("event",p=>this.forwardAcodeEvent(p)),f}buildSubAgentSuiteToolProvider(t){return async e=>{if(!t)return[];if(!St(t,w))return[];if(e.length===0)return At();if(!e.some(a=>{const i=a.trim().replace(/[.*]+$/,"");return i==="desktop"||i.startsWith("desktop.")}))return[];const s=await this.resolveAgentAiInfo(t);return R(t,s)}}async loadRuntimeConstructor(){if(this.runtimeConstructor)return this.runtimeConstructor;const t=Wt(),e=await import(Ht(t));if(!e.ACodeRuntime)throw new Error(`ACode runtime export not found: ${t}`);return this.runtimeConstructor=e.ACodeRuntime,this.runtimeConstructor}requireSession(t){const e=this.sessions.get(t);if(!e)throw new Error("ACode session not found");return e}startInitialPromptTurn(t,e){const o=this.sessions.get(t);o&&(o.adapterSession.status="thinking",this.emit("status-change",t,"thinking"),o.autoPollObservedAssistantText=!1,o.autoPollObservedAnyTool=!1,o.autoPollObservedPollingTool=!1,o.lastSubmittedPrompt=e,o.retryEpoch+=1,o.turnModelRequestSucceeded=!1,this.startSubmitTimeoutDetection(t,o,"startInitialPromptTurn"),o.runtime.submit(e).then(()=>{this.cancelSubmitTimeoutDetection(o),this.recoverResolvedTurnWithoutTerminalEvent(t)}).catch(s=>{const 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:L(),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:Gt(t.data.stream),sequence:typeof t.data.sequence=="number"?t.data.sequence:void 0,cwd:typeof t.data.cwd=="string"?t.data.cwd:void 0,commandLineCount:typeof t.data.commandLineCount=="number"?t.data.commandLineCount:void 0,commandFilePath:typeof t.data.commandFilePath=="string"?t.data.commandFilePath:void 0});return}if(t.type==="background_command_completed"){this.emitProviderEvent(t,"background_command_completed",t.data);return}if(t.type==="ai_request"){const o=t.data.lastUsage,s=y(o?.inputTokens),a=y(o?.outputTokens),i=y(o?.cacheHitTokens),n=y(o?.cacheMissTokens),c=!!(o&&(s>0||a>0));let u;c&&(s>0&&(e.adapterSession.totalUsage.inputTokens=s),a>0&&(e.adapterSession.totalUsage.outputTokens=a),(o?.cacheHitTokens!==void 0||o?.cacheMissTokens!==void 0)&&(e.adapterSession.totalUsage.cacheHitTokens=i,e.adapterSession.totalUsage.cacheMissTokens=n),u={...e.adapterSession.totalUsage},P(`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 d={actionType:"ai_request",actionLabel:"AI\u8BF7\u6C42",actionDetail:this.formatAiRequestActionDetail(t.data)};u&&(d.usage=u),P(`ai_request handled: estimatedContextTokens=${t.data.estimatedContextTokens??"n/a"} totalUsage=${JSON.stringify(e.adapterSession.totalUsage)} displayUsage=${JSON.stringify(u??null)}`),this.emit("status-change",t.sessionId,e.adapterSession.status,d),this.startDataFlowWatchdog(t.sessionId,e),e.adapterSession.status==="thinking"&&e.watchdogSubmitStartTime&&(e.watchdogSubmitStartTime=Date.now()),this.emitProviderEvent(t,"ai_request",{model:typeof t.data.model=="string"?t.data.model:void 0,endpoint:typeof t.data.endpoint=="string"?t.data.endpoint:void 0,requestMethod:typeof t.data.requestMethod=="string"?t.data.requestMethod:void 0,requestUrl:typeof t.data.requestUrl=="string"?t.data.requestUrl:void 0,requestHeaders:zt(t.data.requestHeaders),stream:typeof t.data.stream=="boolean"?t.data.stream:void 0,messageCount:typeof t.data.messageCount=="number"?t.data.messageCount:void 0,toolCount:typeof t.data.toolCount=="number"?t.data.toolCount:void 0,lastUserMessagePreview:typeof t.data.lastUserMessagePreview=="string"?t.data.lastUserMessagePreview:void 0});return}if(t.type==="iteration_usage"){const o=it(t.data);o&&(e.adapterSession.totalUsage.inputTokens=o.inputTokens,e.adapterSession.totalUsage.outputTokens=o.outputTokens,o.hasCache&&(e.adapterSession.totalUsage.cacheHitTokens=o.cacheHitTokens,e.adapterSession.totalUsage.cacheMissTokens=o.cacheMissTokens),P(`iteration_usage applied: raw=${JSON.stringify(t.data)} -> totalUsage=${JSON.stringify(e.adapterSession.totalUsage)}`),this.emit("status-change",t.sessionId,e.adapterSession.status,{usage:{...e.adapterSession.totalUsage}}));return}if(t.type==="turn_complete"){const o=it(t.data.usage);if(o){const a=e.adapterSession.totalUsage.inputTokens,i=a>0&&o.inputTokens<Math.floor(a*.2)&&!o.hasCache;P(`turn_complete usage: raw=${JSON.stringify(t.data.usage)} parsed=${JSON.stringify(o)} currentInput=${a} threshold20pct=${Math.floor(a*.2)} isFallbackUsage=${i}`),i?o.outputTokens>0&&(e.adapterSession.totalUsage.outputTokens=o.outputTokens):(e.adapterSession.totalUsage.inputTokens=o.inputTokens,e.adapterSession.totalUsage.outputTokens=o.outputTokens),o.hasCache&&(e.adapterSession.totalUsage.cacheHitTokens=o.cacheHitTokens,e.adapterSession.totalUsage.cacheMissTokens=o.cacheMissTokens,r(`[ACode] \u{1F4B0} Cache usage (overwrite from runtime cumulative): hit=${e.adapterSession.totalUsage.cacheHitTokens}, miss=${e.adapterSession.totalUsage.cacheMissTokens} (turn delta: hit=${o.cacheHitTokens??0}, miss=${o.cacheMissTokens??0})`)),P(`totalUsage after turn_complete: ${JSON.stringify(e.adapterSession.totalUsage)}`)}else P(`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}`),Jt(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}),P(`status-change emitted (waiting_input after turn_complete): usage=${JSON.stringify(e.adapterSession.totalUsage)}`),r(`[ACode] Status changed to waiting_input after turn_complete (session: ${t.sessionId})`),e.autoPollActive&&e.autoPollObservedAssistantText&&!e.autoPollObservedPollingTool&&!e.autoPollObservedAnyTool){e.stopAutoPollAfterCurrentTurn=!0,e.idleListeningIntentionallyStopped=!0,console.warn(`[${this.displayName}] Auto-poll turn produced assistant text without calling any tool; stopping auto-poll rearm for session ${t.sessionId}`);return}if(!e.autoPollActive&&e.autoPollObservedAnyTool&&!e.autoPollObservedPollingTool){r(`[ACode] User-message turn called work tools; deferring idle rearm (no immediate dispatch) for this turn (session: ${t.sessionId})`),this.scheduleDeferredIdleRearm(t.sessionId);return}this.armIdleLoopOrAutoPoll(t.sessionId);return}if(t.type==="session_complete"){this.cancelDataFlowWatchdog(e),this.cancelScheduledAutoPoll(e),e.failedTurnRecoveryScheduled=!1,e.idlePollLoop?.stop(),e.adapterSession.status="completed",this.emitProviderEvent(t,"session_complete",{exitCode:Number(t.data.exitCode)||0}),this.emit("status-change",t.sessionId,"completed");return}if(t.type==="question_request"){this.cancelDataFlowWatchdog(e),this.cancelSubmitTimeoutDetection(e);const o=typeof t.data.toolCallId=="string"?t.data.toolCallId:"",s=Array.isArray(t.data.questions)?t.data.questions:[];o&&(e.pendingQuestionToolCallId=o,e.pendingQuestions=s),this.emit("ask-user-question",{sessionId:t.sessionId,toolCallId:o||void 0,questions:s});return}if(t.type==="tool_permission_request"){this.cancelDataFlowWatchdog(e),this.cancelSubmitTimeoutDetection(e);const o=typeof t.data.requestId=="string"?t.data.requestId:"";o&&(e.pendingToolAuthRequests||(e.pendingToolAuthRequests=new Map),e.pendingToolAuthRequests.set(o,{capability:String(t.data.capability||""),detail:{path:t.data.path,command:t.data.command,cwd:t.data.cwd,operation:t.data.operation},requestedAt:Date.now()})),this.emit("tool-permission-request",{sessionId:t.sessionId,requestId:o,capability:String(t.data.capability||""),agentId:e.config.agentId,detail:{path:t.data.path,command:t.data.command,cwd:t.data.cwd,operation:t.data.operation}});return}if(t.type==="error"){if(t.data.nonFatal){this.resetDataFlowWatchdog(t.sessionId,e),this.emitProviderEvent(t,"error",{text:String(t.data.message||"ACode runtime error")});return}this.cancelDataFlowWatchdog(e),e.adapterSession.status="error",e.lastErrorText=String(t.data.message||""),this.emitProviderEvent(t,"error",{text:String(t.data.message||"ACode runtime error")}),this.emit("status-change",t.sessionId,"error"),e.autoPollActive||this.recoverTurnFailure(t.sessionId,e);return}if(t.type==="mcp_status"){if(!t.data.action&&Array.isArray(t.data.tools)){const g=t.data.tools;g.some(A=>wt(A))||console.warn(`[${this.displayName}] ACode runtime is not exposing a poll_message tool. The LLM cannot call poll_message. Please configure an MCP server that provides poll_message (e.g. aws-mcp) in the dashboard panel for this runtime.`);const S=Array.isArray(t.data.servers)?t.data.servers:[],b=g.map(A=>({name:String(A.name??""),source:String(A.source??""),description:String(A.description??"")})).filter(A=>A.name),C={kind:"mcp",mcpServers:S,mcpTools:b};e.cachedMcpCapabilities=C,e.lastMcpCapabilities=C,e.lastCombinedCapabilities={kind:"combined",mcpServers:S,mcpTools:b,skills:e.lastCombinedCapabilities?.skills??[],skillsDir:e.lastCombinedCapabilities?.skillsDir,skillGroups:e.lastCombinedCapabilities?.skillGroups??[]},r(`[cap-diag] MCP capabilities cached: ${S.length} servers, ${b.length} tools`,{sessionId:t.sessionId,servers:S,toolNames:b.map(A=>A.name)}),e.capabilitiesFallbackTimer&&clearTimeout(e.capabilitiesFallbackTimer),e.capabilitiesFallbackTimer=setTimeout(()=>{const A=e.cachedMcpCapabilities;if(!A)return;const _={...A,skills:[],skillGroups:[]};this.emitProviderEvent(t,"runtime_capabilities",{capabilities:_,actionType:"runtime_capabilities",actionLabel:"\u8FD0\u884C\u65F6\u80FD\u529B",actionDetail:JSON.stringify(_)}),r(`[cap-diag] MCP capabilities emitted via fallback (skill_status not received within ${et}ms)`,{sessionId:t.sessionId,mcpServers:A.mcpServers,mcpToolsCount:A.mcpTools?.length??0}),e.cachedMcpCapabilities=void 0,e.capabilitiesFallbackTimer=void 0},et);return}const o=String(t.data.action??"");if(o==="tool_batch_start"){const g=typeof t.data.batchId=="string"?t.data.batchId:void 0;if(!g){r(`[ACode] \u{1F9E9} tool_batch_start without batchId, ignored (session=${t.sessionId})`);return}const h=typeof t.data.toolCount=="number"?t.data.toolCount:0,S=Array.isArray(t.data.toolNames)?t.data.toolNames.map(b=>String(b??"")).filter(Boolean):[];r(`[ACode] \u{1F9E9} tool_batch_start: batch=${g.slice(0,20)}\u2026, tools=${h}`),this.emitProviderEvent(t,"tool_batch_start",{batchId:g,batchToolCount:h,batchToolNames:S,actionType:"tool_batch",actionLabel:"\u5E76\u884C\u6267\u884C\u5DE5\u5177",actionDetail:S.length>0?S.join(", "):void 0,actionId:g});return}if(o==="tool_batch_metrics"){const g=typeof t.data.batchId=="string"?t.data.batchId:void 0;if(!g){r(`[ACode] \u26A1 tool_batch_metrics without batchId, ignored (session=${t.sessionId})`);return}const h={toolCount:D(t.data.toolCount),parallelism:D(t.data.parallelism),speedup:D(t.data.speedup),wallClockMs:D(t.data.wallClockMs),totalWaitMs:W(t.data.totalWaitMs),contentionCount:D(t.data.contentionCount),failureCount:W(t.data.failureCount),maxConcurrentObserved:W(t.data.maxConcurrentObserved)};r(`[ACode] \u26A1 tool_batch_metrics: batch=${g.slice(0,20)}\u2026, speedup=${h.speedup}x parallelism=${h.parallelism}x wall=${h.wallClockMs}ms contentions=${h.contentionCount} failures=${h.failureCount??"-"}`),this.emitProviderEvent(t,"tool_batch_metrics",{batchId:g,batchMetrics:h,actionType:"tool_batch",actionLabel:"\u5E76\u884C\u6267\u884C\u5DE5\u5177",actionId:g});return}if(o!=="call_tool"&&o!=="tool_result"){r(`[ACode] \u{1F4AC} mcp_status status report ignored (action=${o||"none"}, server=${typeof t.data.server=="string"?t.data.server:"?"}, session=${t.sessionId})`);return}r(`[ACode] \u{1F4E1} mcp_status event: action=${o}, server=${typeof t.data.server=="string"?t.data.server:"?"}, tool=${typeof t.data.tool=="string"?t.data.tool:"?"}, toolUseId=${typeof t.data.toolUseId=="string"?t.data.toolUseId.slice(0,16)+"\u2026":"none"}, failed=${t.data.failed===!0}, session=${t.sessionId}, status=${e.adapterSession.status}`);const s=typeof t.data.server=="string"?t.data.server:"mcp",a=typeof t.data.tool=="string"?t.data.tool:"",i=s&&a?`${s}__${a}`:a||s,n=t.data.arguments&&typeof t.data.arguments=="object"&&!Array.isArray(t.data.arguments)?t.data.arguments:void 0,c=Lt(i,n);e.autoPollObservedAnyTool=!0,c.actionType==="idle"&&(e.autoPollObservedPollingTool=!0);const u=Qt(c.actionType)?c.actionDetail||at(void 0,s,a):at(c.actionDetail,s,a),f=typeof t.data.toolUseId=="string"?t.data.toolUseId:void 0,d=n?JSON.stringify(n,null,2):void 0,p=typeof t.data.batchId=="string"?t.data.batchId:void 0,m={toolName:u,rawToolName:i,actionType:c.actionType,actionLabel:c.actionLabel,actionDetail:u,...d?{actionInput:d}:{},...n?{toolInput:n}:{},...f?{toolUseId:f,actionId:f}:{},...p?{batchId:p,parentId:p}:{},metadata:{mcpServer:s}};if(t.data.action==="tool_result"){this.emitProviderEvent(t,"tool_use_end",{...m,toolResult:typeof t.data.result=="string"?t.data.result:JSON.stringify(t.data.result??"")}),e.adapterSession.messages.push({id:L(),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:f,isError:t.data.failed===!0});const g=c.actionType==="idle"&&!Yt(t.data.result)?"waiting_input":"thinking";e.adapterSession.status=g,c.actionType==="idle"&&(e.idleToolActiveAt=void 0),k("tool_use_end",{sessionId:t.sessionId,actionType:c.actionType,tool:i,nextStatus:g,idleToolActiveAtAfter:e.idleToolActiveAt??null}),this.cancelDataFlowWatchdog(e),e.pendingToolEventData=void 0;const h=c.actionType==="idle";this.emit("status-change",t.sessionId,g,h||g==="thinking"?void 0:m);return}const T=c.actionType==="idle"?"waiting_input":"tool_using";e.adapterSession.status=T,c.actionType==="idle"&&(e.idleToolActiveAt=Date.now()),T==="tool_using"&&(this.resetDataFlowWatchdog(t.sessionId,e),e.pendingToolEventData={...m}),e.adapterSession.messages.push({id:L(),sessionId:t.sessionId,role:"tool_use",content:d??"",timestamp:t.timestamp,toolName:i,toolInput:n,toolUseId:f}),this.emitProviderEvent(t,"tool_use_start",m),this.emit("status-change",t.sessionId,T,m);return}if(t.type==="skill_status"){const s=(Array.isArray(t.data.skills)?t.data.skills:[]).map(d=>({name:String(d.name??""),description:typeof d.description=="string"?d.description:void 0,directory:typeof d.directory=="string"?d.directory:void 0})).filter(d=>d.name),a=typeof t.data.skillsDir=="string"?t.data.skillsDir:void 0,n=(Array.isArray(t.data.skillGroups)?t.data.skillGroups:[]).map(d=>{const p=Array.isArray(d.skills)?d.skills:[];return{dir:typeof d.dir=="string"?d.dir:"",exists:d.exists===!0,skills:p.map(m=>({name:String(m.name??""),description:typeof m.description=="string"?m.description:void 0,directory:typeof m.directory=="string"?m.directory:void 0})).filter(m=>m.name)}}).filter(d=>d.dir),c=e.cachedMcpCapabilities??e.lastMcpCapabilities,u=e.cachedMcpCapabilities!==void 0,f={kind:"combined",mcpServers:c?.mcpServers??[],mcpTools:c?.mcpTools??[],skills:s,skillsDir:a,skillGroups:n};this.emitProviderEvent(t,"runtime_capabilities",{capabilities:f,actionType:"runtime_capabilities",actionLabel:"\u8FD0\u884C\u65F6\u80FD\u529B",actionDetail:JSON.stringify(f)}),e.lastCombinedCapabilities=f,r(`[cap-diag] Combined capabilities emitted ${u?"(startup merge)":"(runtime refresh)"}: ${(c?.mcpTools??[]).length} MCP tools, ${s.length} skills`,{sessionId:t.sessionId,mcpServers:c?.mcpServers??[],skillsDir:a}),e.capabilitiesFallbackTimer&&(clearTimeout(e.capabilitiesFallbackTimer),e.capabilitiesFallbackTimer=void 0),e.cachedMcpCapabilities=void 0;return}if(t.type==="startup_phase"){r(`[ACode] \u{1F680} startup_phase swallowed: ${String(t.data.phase??"unknown")}`,{sessionId:t.sessionId});return}if(t.type==="command_status"){if(t.data.action==="commands_loaded"){r(`[ACode] \u{1F4CB} command_status commands_loaded swallowed: ${typeof t.data.installedCommandCount=="number"?t.data.installedCommandCount:"?"} commands`,{sessionId:t.sessionId});return}this.emitProviderEvent(t,"thinking",{text:JSON.stringify(t.data)});return}if(t.type==="session_started"){const o=y(t.data.contextLimit)||void 0,s=y(t.data.maxOutput)||void 0,a=y(t.data.inputLimit)||void 0,i=y(t.data.compactionThreshold)||void 0;let n=!1;o!==void 0&&(e.adapterSession.totalUsage.contextLimit=o,n=!0),s!==void 0&&(e.adapterSession.totalUsage.maxOutput=s,n=!0),a!==void 0&&(e.adapterSession.totalUsage.inputLimit=a,n=!0),i!==void 0&&(e.adapterSession.totalUsage.compactionThreshold=i,n=!0),n&&this.emit("status-change",t.sessionId,e.adapterSession.status,{usage:e.adapterSession.totalUsage});return}if(t.type==="exit_plan_mode"){e.adapterSession.status="waiting_input";const o=typeof t.data.plan=="string"?t.data.plan:void 0;this.emitProviderEvent(t,"exit_plan_mode",{toolInput:t.data.toolInput&&typeof t.data.toolInput=="object"?t.data.toolInput:void 0,text:o||"\u9000\u51FA\u8BA1\u5212\u6A21\u5F0F"}),this.emit("status-change",t.sessionId,"waiting_input",{actionLabel:"\u5BA1\u6279\u8BA1\u5212",actionDetail:o||"\u7B49\u5F85\u7528\u6237\u5BA1\u6279\u9000\u51FA\u8BA1\u5212\u6A21\u5F0F"});return}if(t.type==="context_compaction"){const o=t.data,s=o.action,a=s==="start",i=s==="end",n=s==="phase",c=o.parentId,u=o.compactionId;if(o.trigger==="hibernation_replay"){const T=typeof o.replayedMessageCount=="number"?o.replayedMessageCount:void 0,g=o.estimatedTokens;typeof g=="number"&&g>0&&(e.adapterSession.totalUsage.inputTokens=g);const h={actionType:"context_compaction",actionLabel:"\u4F11\u7720\u6062\u590D",actionDetail:T?`\u5DF2\u91CD\u653E\u4F11\u7720\u524D\u7684 ${T} \u6761\u5BF9\u8BDD\u8BB0\u5F55\uFF0C\u4E0A\u4E0B\u6587\u5DF2\u63A5\u7EED`:"\u5DF2\u91CD\u653E\u4F11\u7720\u524D\u7684\u5BF9\u8BDD\u8BB0\u5F55\uFF0C\u4E0A\u4E0B\u6587\u5DF2\u63A5\u7EED",...u?{actionId:u}:{},...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 d,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;d="\u4E0A\u4E0B\u6587\u538B\u7F29\u5F00\u59CB";const A=C==="provider_overflow_error"?"\u6A21\u578B\u8FD4\u56DE\u4E0A\u4E0B\u6587\u8D85\u9650\u4FE1\u53F7":C==="finish_reason_context_overflow"?"\u54CD\u5E94\u4E2D\u7684\u8D85\u9650\u6807\u8BB0":C==="request_body_byte_limit"?"\u8BF7\u6C42\u4F53\u5B57\u8282\u4E0A\u9650":C,_=A?`, \u89E6\u53D1: ${A}`:"";h!==void 0?p=`\u538B\u7F29\u524D: ~${h} tokens, \u6D88\u606F: ${g}\u6761`+(S?`, \u5B9E\u9645 tokens: ${S} ${b}`:"")+_:p=`\u538B\u7F29\u524D: ${T}KB, \u6D88\u606F: ${g}\u6761`+(S?`, \u5B9E\u9645 tokens: ${S} ${b}`:"")+_}else if(n){const T=String(o.phase??""),g=String(o.phaseLabel??"\u538B\u7F29\u9636\u6BB5"),h=String(o.phaseDetail??"");T==="detect"?(d="\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..."):(d=g,p=h)}else{const T=o.tokensBefore,g=o.tokensAfter,h=o.freedTokens,S=String(o.sizeBeforeKB??"?"),b=String(o.sizeAfterKB??"?"),C=String(o.freedKB??"?"),A=String(o.strategy??"?"),_=Number(o.prunedToolMessages??0),O=Number(o.summarizedMessages??0);d="\u538B\u7F29\u5B8C\u6210",T!==void 0&&g!==void 0?p=`\u91CA\u653E: ${h??T-g} tokens, ${T} tokens \u2192 ${g} tokens, \u7B56\u7565: ${A}`+(_?`, \u88C1\u526A\u5DE5\u5177: ${_}\u6761`:"")+(O?`, \u6458\u8981\u5316: ${O}\u6761`:""):p=`\u91CA\u653E: ${C}KB, ${S}KB \u2192 ${b}KB, \u7B56\u7565: ${A}`+(_?`, \u88C1\u526A\u5DE5\u5177: ${_}\u6761`:"")+(O?`, \u6458\u8981\u5316: ${O}\u6761`:"")}a&&(e.adapterSession.status="compacting");const m={actionType:"context_compaction",actionLabel:d,actionDetail:p};if(a&&u)m.actionId=u;else if((n||i)&&u)if(m.parentId=u,n){const T=String(o.phase??"unknown");m.actionId=`${u}-phase-${T}`}else m.actionId=`${u}-end`;n&&c&&!m.parentId&&(m.parentId=c),i&&(e.adapterSession.totalUsage.inputTokens=y(o.tokensAfter),e.adapterSession.totalUsage.outputTokens=0,e.config.agentId&&I.markAgentCompacted(e.config.agentId),m.usage={...e.adapterSession.totalUsage}),this.emitProviderEvent(t,"context_compaction",m),this.emit("status-change",t.sessionId,"compacting",m);return}this.emitProviderEvent(t,"thinking",{text:JSON.stringify(t.data)})}}emitProviderEvent(t,e,o){this.emit("event",{type:e,sessionId:t.sessionId,timestamp:t.timestamp,data:o})}armIdleLoopOrAutoPoll(t){const e=this.sessions.get(t);if(!(!e||this.isTerminalStatus(e.adapterSession.status))){if(e.autoPollTimer&&(clearTimeout(e.autoPollTimer),e.autoPollTimer=void 0),this.cancelRequestRetry(e),e.retryAttempt=0,e.idleCommands?.idleInputCommand){this.getIdlePollLoop(e).start();return}this.scheduleAutoPoll(t)}}scheduleDeferredIdleRearm(t){const e=this.sessions.get(t);!e||e.autoPollActive||e.autoPollTimer||this.isTerminalStatus(e.adapterSession.status)||this.scheduleAutoPoll(t,Ft)}getIdlePollLoop(t){if(t.idlePollLoop)return t.idlePollLoop;const e=t.adapterSession.sessionId;return t.idlePollLoop=new $t({getStatus:()=>this.sessions.get(e)?.adapterSession.status,getCommand:()=>this.sessions.get(e)?.idleCommands?.idleInputCommand,isPollingCommand:o=>q(o),preDispatchHook:()=>null,dispatchPollingPrompt:(o,s)=>this.submitAutoPollPrompt(e,s?o:Nt,{keepWaitingStatus:!0}),dispatchRegularIdleCommand:o=>this.submitAutoPollPrompt(e,o)}),t.idlePollLoop}submitAutoPollPrompt(t,e,o){const s=this.sessions.get(t);if(!s||this.isTerminalStatus(s.adapterSession.status))return;const a=(s.autoPollToken??0)+1;s.autoPollToken=a,s.autoPollActive=!0,s.autoPollObservedPollingTool=!1,s.autoPollObservedAssistantText=!1,s.autoPollObservedAnyTool=!1,s.stopAutoPollAfterCurrentTurn=!1,s.idleListeningIntentionallyStopped=!1,s.autoPollQueuedAt=Date.now(),s.autoPollLastActivityAt=Date.now(),s.idleToolActiveAt=void 0,s.lastSubmittedPrompt=e,s.retryEpoch+=1,s.turnModelRequestSucceeded=!1,o?.keepWaitingStatus||(s.adapterSession.status="thinking",this.emit("status-change",t,"thinking")),this.startSubmitTimeoutDetection(t,s,"submitAutoPollPrompt"),s.runtime.submit(e).catch(i=>{this.emitRuntimeErrorEvent(t,i),this.scheduleRequestRetry(t,"submitAutoPollPrompt")}).finally(()=>{const i=this.sessions.get(t);if(i){if(i.autoPollToken!==a){r(`[ACode] submitAutoPollPrompt.finally: token mismatch (my=${a}, current=${i.autoPollToken}), skipping cleanup \u2014 newer turn has taken over`);return}if(this.cancelSubmitTimeoutDetection(i),i.autoPollActive=!1,i.failedTurnRecoveryScheduled||i.autoPollTimer){i.failedTurnRecoveryScheduled=!1;return}if(i.stopAutoPollAfterCurrentTurn){i.stopAutoPollAfterCurrentTurn=!1,i.autoPollObservedPollingTool=!1,i.autoPollObservedAssistantText=!1,i.autoPollObservedAnyTool=!1;return}if(i.adapterSession.status==="error"){this.recoverTurnFailure(t,i);return}if(i.adapterSession.status==="thinking"||i.adapterSession.status==="tool_using"){this.recoverResolvedTurnWithoutTerminalEvent(t);return}i.adapterSession.status==="waiting_input"&&this.armIdleLoopOrAutoPoll(t)}})}scheduleAutoPoll(t,e){const o=this.sessions.get(t);if(!o||o.autoPollActive||o.autoPollTimer||this.isTerminalStatus(o.adapterSession.status))return;const s=e??o.autoPollDelayMs??vt;e===void 0&&(o.autoPollDelayMs=Math.min(s*2,Ut)),o.autoPollTimer=setTimeout(()=>{const a=this.sessions.get(t);!a||a.autoPollActive||this.isTerminalStatus(a.adapterSession.status)||(a.autoPollTimer=void 0,this.submitAutoPollPrompt(t,Dt,{keepWaitingStatus:!0}))},s)}cancelScheduledAutoPoll(t){t.autoPollDelayMs=void 0,t.autoPollTimer&&(clearTimeout(t.autoPollTimer),t.autoPollTimer=void 0)}scheduleRequestRetry(t,e){const o=this.sessions.get(t);if(!o||this.isTerminalStatus(o.adapterSession.status))return;if(o.retryCircuitBroken){r(`[ACode] scheduleRequestRetry(${e}): retry terminated by non-retryable error, suppress further auto-retry`);return}if(o.retryActive||o.retryTimer)return;if(!o.lastSubmittedPrompt){o.adapterSession.status="error",this.emit("status-change",t,"error");return}if(o.turnModelRequestSucceeded&&o.turnModelRequestSucceededEpoch===o.retryEpoch&&(o.turnModelRequestSucceeded=!1,o.retryAttempt=0),o.lastErrorText&&qt(o.lastErrorText)){r(`[ACode] scheduleRequestRetry(${e}): non-retryable provider error, giving up retry: ${o.lastErrorText.slice(0,200)}`),this.cancelRequestRetry(o),o.retryAttempt=0,o.retryCircuitBroken=!0,o.adapterSession.status="error",this.emit("status-change",t,"error",{actionType:"retry_aborted",actionLabel:"\u8BF7\u6C42\u65E0\u6548",actionDetail:"Provider \u8FD4\u56DE 4xx \u8BF7\u6C42\u9519\u8BEF\uFF08\u539F\u6837\u91CD\u8BD5\u5FC5\u7136\u5931\u8D25\uFF09\uFF0C\u5DF2\u505C\u6B62\u81EA\u52A8\u91CD\u8BD5\uFF0C\u8BF7\u68C0\u67E5\u6E20\u9053\u914D\u7F6E\u6216\u91CD\u542F\u4F1A\u8BDD\u3002",actionError:Z(o.lastErrorText)});return}o.retryAttempt+=1,o.retryActive=!0,this.cancelScheduledAutoPoll(o),o.idlePollLoop?.stop();const s=V[Math.min(o.retryAttempt-1,V.length-1)];o.adapterSession.status="error",this.emit("status-change",t,"error",{actionType:"retry",actionLabel:"\u91CD\u8BD5\u4E2D",actionDetail:`\u7B2C${o.retryAttempt}\u6B21 \xB7 ${Math.round(s/1e3)}s\u540E`,actionError:Z(o.lastErrorText)}),r(`[ACode] scheduleRequestRetry(${e}): attempt=${o.retryAttempt} delay=${s}ms`),o.retryTimer=setTimeout(()=>{o.retryTimer=void 0,this.retryFailedRequest(t,e)},s)}retryFailedRequest(t,e){const o=this.sessions.get(t);if(!o)return;if(o.retryTimer=void 0,this.isTerminalStatus(o.adapterSession.status)||!o.lastSubmittedPrompt){o.retryActive=!1;return}o.retryActive=!1;const s=o.lastSubmittedPrompt;r(`[ACode] retryFailedRequest(${e}): attempt=${o.retryAttempt} re-submitting...`),o.retryEpoch+=1,o.turnModelRequestSucceeded=!1,o.autoPollObservedAssistantText=!1,o.autoPollObservedAnyTool=!1,o.autoPollObservedPollingTool=!1,o.adapterSession.status="thinking",this.emit("status-change",t,"thinking",{usage:o.adapterSession.totalUsage}),this.startSubmitTimeoutDetection(t,o,"retryFailedRequest"),o.runtime.submit(s,{resume:!0}).then(()=>{const a=this.sessions.get(t);!a||a.retryTimer||(this.cancelSubmitTimeoutDetection(a),a.retryAttempt=0,a.retryActive=!1,a.retryCircuitBroken=!1,this.recoverResolvedTurnWithoutTerminalEvent(t))}).catch(a=>{const i=this.sessions.get(t);i&&(this.cancelSubmitTimeoutDetection(i),i.lastErrorText=a instanceof Error?a.message:String(a),this.emitRuntimeErrorEvent(t,a),this.scheduleRequestRetry(t,`retry#${i.retryAttempt+1}`))})}cancelRequestRetry(t){t.retryTimer&&(clearTimeout(t.retryTimer),t.retryTimer=void 0),t.retryActive=!1}isTerminalStatus(t){return t==="completed"||t==="terminated"}emitRuntimeErrorEvent(t,e){const o=new Date().toISOString();this.emit("event",{type:"error",sessionId:t,timestamp:o,data:{text:e instanceof Error?e.message:String(e)}})}estimateOutputTokensFromMessages(t){const e=t.filter(o=>o.role==="assistant").map(o=>o.content).join("");return Math.max(0,Math.round(e.length/4))}recoverTurnFailure(t,e){if(this.isTerminalStatus(e.adapterSession.status))return;if(e.idleToolActiveAt=void 0,e.pendingToolAuthRequests?.size&&e.pendingToolAuthRequests.clear(),e.adapterSession.status==="tool_using"&&e.pendingToolEventData){const s=e.pendingToolEventData;r(`[ACode] recoverTurnFailure: \u8865\u53D1 tool_use_end (tool: ${s.toolName??"unknown"}) \u5173\u95ED\u65F6\u95F4\u7EBF\u6761\u76EE\uFF0C\u907F\u514D\u6C38\u4E45\u5361\u5728\u5DE5\u5177\u6267\u884C\u72B6\u6001`),this.emit("event",{type:"tool_use_end",sessionId:t,timestamp:new Date().toISOString(),data:{...s,toolResult:"[aborted] \u5DE5\u5177\u6267\u884C\u88AB\u6570\u636E\u6D41\u770B\u95E8\u72D7\u4E2D\u65AD"}}),e.pendingToolEventData=void 0}const o=this.estimateOutputTokensFromMessages(e.adapterSession.messages);if(o>0){const s=e.adapterSession.totalUsage.outputTokens;e.adapterSession.totalUsage.outputTokens=o,r(`[ACode] recoverTurnFailure: \u4F30\u7B97\u8986\u76D6 output tokens ${s} -> ${o} (totalUsage now: input=${e.adapterSession.totalUsage.inputTokens}, output=${e.adapterSession.totalUsage.outputTokens})`)}this.cancelScheduledAutoPoll(e),this.scheduleRequestRetry(t,"recoverTurnFailure")}recoverResolvedTurnWithoutTerminalEvent(t){r(`[ACode] \u25B6\uFE0F recoverResolvedTurnWithoutTerminalEvent called for session ${t}`);const e=this.sessions.get(t);if(!e||this.isTerminalStatus(e.adapterSession.status)){r(`[ACode] Skipping recovery: entry=${!!e}, isTerminal=${e?this.isTerminalStatus(e.adapterSession.status):"N/A"}`);return}if(r(`[ACode] Current status: ${e.adapterSession.status}`),e.adapterSession.status!=="thinking"&&e.adapterSession.status!=="tool_using"){r(`[ACode] Skipping recovery: status is ${e.adapterSession.status} (not thinking/tool_using)`);return}console.warn(`[ACode] \u26A0\uFE0F Detected stuck state: ${e.adapterSession.status} after submit resolved! Recovering to waiting_input. If runtime.submit() is still pending (e.g., built-in tool execution not interruptible by abort()), the submitQueue is deadlocked and subsequent auto-poll/user submits will never execute.`),r("[ACode] Recovering to waiting_input..."),e.adapterSession.status="waiting_input";const o=e.idleCommands?.idleInputCommand,a=!!(o&&q(o))?{actionType:"idle",actionLabel:"\u76D1\u542C\u6D88\u606F",actionDetail:"aws-mcp/poll_message"}:void 0;if(this.emit("status-change",t,"waiting_input",a),r(`[ACode] \u2705 Recovery complete, status now: ${e.adapterSession.status}`),r("[ACode] \u25B6\uFE0F Arming idle loop or auto-poll..."),!e.autoPollActive&&e.autoPollObservedAnyTool&&!e.autoPollObservedPollingTool){r(`[ACode] User-message turn called work tools; deferring idle rearm in recoverResolvedTurnWithoutTerminalEvent (session: ${t})`),this.scheduleDeferredIdleRearm(t);return}this.armIdleLoopOrAutoPoll(t),r("[ACode] \u2705 Idle loop armed, recovery process complete")}startSubmitTimeoutDetection(t,e,o){this.cancelSubmitTimeoutDetection(e),e.watchdogSubmitStartTime=Date.now(),e.watchdogLastDataFlowTime=Date.now(),k("turn_watchdog_arm",{sessionId:t,source:o,status:e.adapterSession.status,autoPollActive:!!e.autoPollActive,idleToolActiveAt:e.idleToolActiveAt??null}),e.watchdogTimer=setInterval(()=>{const s=this.sessions.get(t);if(!s){this.cancelSubmitTimeoutDetection(e);return}const a=s.adapterSession.status,i=Date.now();if(a==="waiting_input"){if(s.autoPollActive&&s.autoPollLastActivityAt&&!this.hasActiveBlockingToolCall(s)&&i-s.autoPollLastActivityAt>=Mt){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 u=i-(s.watchdogLastDataFlowTime||i);if(u>=Rt){const f=String(s.pendingToolEventData?.rawToolName??"");if((s.pendingToolAuthRequests?.size??0)>0){const d=s.pendingToolAuthRequests?.size??0;console.warn(`[ACode] tool_using elapsed ${Math.round(u/1e3)}s but ${d} tool permission request(s) awaiting user decision (session: ${t}), skipping recovery`),s.watchdogSubmitStartTime=i,s.watchdogLastDataFlowTime=i;return}if(f.endsWith("await_complete")){console.warn(`[ACode] tool_using elapsed ${Math.round(u/1e3)}s but await_complete is running (session: ${t}, tool: ${f}), 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(u/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(u/1e3)}s): detached tool ${f} 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",u);return}s.watchdogSubmitStartTime=i;return}if(a!=="thinking")return;const n=i-(s.watchdogSubmitStartTime||i),c=i-(s.watchdogLastDataFlowTime||i);if(Q>0&&c>=Q){console.warn(`[ACode] CRITICAL: Data flow watchdog triggered after ${Math.round(c/1e3)}s (source: ${o}, session: ${t}, status: ${a}). No stream data received. Forcing recovery via recoverTurnFailure.`),this.executeWatchdogRecovery(t,s,o,"data_flow",c);return}if(tt>0&&n>=tt){console.warn(`[ACode] CRITICAL: submit timeout detected after ${Math.round(n/1e3)}s (source: ${o}, session: ${t}, status: ${a}). Forcing recovery to prevent permanent state stuck.`),this.executeWatchdogRecovery(t,s,o,"submit_timeout",n);return}},Ot)}executeWatchdogRecovery(t,e,o,s,a){k("turn_watchdog_trigger",{sessionId:t,source:o,reason:s,elapsedMs:a,status:e.adapterSession.status,autoPollActive:!!e.autoPollActive,idleToolActiveAt:e.idleToolActiveAt??null,pendingTool:e.pendingToolEventData?.rawToolName??null}),r(`[ACode] Watchdog (${s}): calling runtime.abort() after ${Math.round(a/1e3)}s...`);try{e.runtime.abort(),r(`[ACode] Watchdog (${s}): runtime.abort() called`)}catch(i){console.warn(`[ACode] \u26A0\uFE0F Watchdog (${s}): runtime.abort() threw: ${i instanceof Error?i.message:String(i)}`)}this.cancelSubmitTimeoutDetection(e),this.recoverTurnFailure(t,e),console.warn(`[ACode] \u26A0\uFE0F Watchdog (${s}) recovery complete. If abort() could not cancel the underlying operation, submitQueue may still be deadlocked.`)}cancelSubmitTimeoutDetection(t){t.watchdogTimer&&(clearInterval(t.watchdogTimer),t.watchdogTimer=void 0,k("turn_watchdog_cancel",{sessionId:t.adapterSession.sessionId,status:t.adapterSession.status,autoPollActive:!!t.autoPollActive,idleToolActiveAt:t.idleToolActiveAt??null})),t.watchdogSubmitStartTime=void 0,t.watchdogLastDataFlowTime=void 0}resetDataFlowWatchdog(t,e){e.watchdogLastDataFlowTime=Date.now(),e.watchdogSubmitStartTime=Date.now()}startDataFlowWatchdog(t,e){e.watchdogLastDataFlowTime=Date.now()}cancelDataFlowWatchdog(t){t.watchdogLastDataFlowTime=Date.now()}startLivenessWatchdog(t,e){this.stopLivenessWatchdog(e),e.lastAcodeEventAt=Date.now(),!(B<=0)&&(e.livenessTimer=setInterval(()=>{const o=this.sessions.get(t);if(!o){this.stopLivenessWatchdog(e);return}this.checkSessionLiveness(t,o)},Y),k("liveness_watchdog_arm",{sessionId:t,stallTimeoutMs:B,pollIntervalMs:Y}))}stopLivenessWatchdog(t){t.livenessTimer&&(clearInterval(t.livenessTimer),t.livenessTimer=void 0)}checkSessionLiveness(t,e){if(this.isTerminalStatus(e.adapterSession.status)){this.stopLivenessWatchdog(e);return}if(e.adapterSession.status!=="waiting_input"||e.autoPollActive||e.idleListeningIntentionallyStopped||e.pendingQuestionToolCallId||(e.pendingToolAuthRequests?.size??0)>0||this.hasActiveBlockingToolCall(e))return;e.idleToolActiveAt!==void 0&&(r(`[ACode] liveness: runtime \u672A\u62A5\u544A\u963B\u585E\u578B\u5DE5\u5177\u5728\u98DE\uFF0C\u6E05\u9664\u6B8B\u7559 idleToolActiveAt \u6807\u8BB0 (session: ${t})`),e.idleToolActiveAt=void 0);const o=e.lastAcodeEventAt??Date.now(),s=Date.now()-o;if(s<B)return;console.warn(`[ACode] CRITICAL: session liveness stall detected \u2014 no runtime event for ${Math.round(s/1e3)}s (session: ${t}, status: waiting_input). Forcing recovery (abort + re-arm listening loop).`),k("liveness_stall_detected",{sessionId:t,stalledForMs:s,status:e.adapterSession.status,idleToolActiveAt:e.idleToolActiveAt??null}),this.recoverIdleStall(t,e,s);const a=this.sessions.get(t);a&&(a.lastAcodeEventAt=Date.now())}recoverIdleStall(t,e,o){try{e.runtime.abort()}catch(s){console.warn(`[ACode] liveness recovery: runtime.abort() threw: ${s instanceof Error?s.message:String(s)}`)}this.cancelScheduledAutoPoll(e),e.autoPollActive=!1,e.idleToolActiveAt=void 0,this.isTerminalStatus(e.adapterSession.status)||(e.adapterSession.status="waiting_input",this.armIdleLoopOrAutoPoll(t)),k("liveness_recovery",{sessionId:t,stalledForMs:o,rearmedStatus:e.adapterSession.status}),console.warn(`[ACode] liveness recovery complete: session ${t} re-armed listening loop after ${Math.round(o/1e3)}s stall`)}hasActiveBlockingToolCall(t){const e=t.runtime.hasActiveBlockingToolCall;if(typeof e=="function")try{return e.call(t.runtime)===!0}catch(o){r(`[ACode] hasActiveBlockingToolCall probe threw, falling back to idle marker: ${o instanceof Error?o.message:String(o)}`)}return t.idleToolActiveAt!==void 0}formatAiRequestActionDetail(t){const e=`
2
2
 
3
3
  \u8BF7\u6C42\u5934:
4
- `,s=`
5
-
6
- \u8BF7\u6C42\u4F53:
7
- `,a=typeof t.model=="string"?t.model:"",i=typeof t.endpoint=="string"?t.endpoint:typeof t.requestUrl=="string"?t.requestUrl:"",r=typeof t.requestMethod=="string"?t.requestMethod:"",n=typeof t.stream=="boolean"?t.stream:void 0,c=typeof t.messageCount=="number"?t.messageCount:void 0,u=typeof t.toolCount=="number"?t.toolCount:void 0,m=typeof t.lastUserMessagePreview=="string"?t.lastUserMessagePreview:"",p=[a?`\u6A21\u578B: ${a}`:void 0,i?`\u63A5\u53E3: ${i}`:void 0,r?`\u65B9\u6CD5: ${r}`:void 0,n!==void 0?`\u6D41\u5F0F: ${n?"\u662F":"\u5426"}`:void 0,c!==void 0?`\u4E0A\u4E0B\u6587\u6D88\u606F: ${c}`:void 0,u!==void 0?`\u53EF\u7528\u5DE5\u5177: ${u}`:void 0,m?`\u6700\u540E\u8BF7\u6C42: ${m}`:void 0].filter(b=>!!b),g=/^(authorization|x-api-key|api-key|cookie|set-cookie|x-auth-token|token)$/i,f=t.requestHeaders,A=f?Object.entries(f).filter(([b])=>!g.test(b)).map(([b,I])=>`${b}: ${I}`).filter(b=>b.trim().length>0):[],y=p.join(`
8
- `)||"ACode \u6B63\u5728\u53D1\u9001 AI \u8BF7\u6C42",S=A.length>0?`${e}${A.join(`
9
- `)}`:"",_=typeof t.requestBody=="string"?t.requestBody:"",T=_.length>6e4?`${_.slice(0,6e4)}
10
- ...(\u8BF7\u6C42\u4F53\u8FC7\u957F\uFF0C\u5DF2\u622A\u65AD)`:_,C=T?`${s}${T}`:"";return`${y}${S}${C}`}}export{ne as AcodeSdkAdapter,Rt as isFailedAcodeTurnComplete,Lt as toAcodeEsmImportSpecifier};
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,c=typeof t.toolCount=="number"?t.toolCount:void 0,u=typeof t.lastUserMessagePreview=="string"?t.lastUserMessagePreview:"",f=[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,c!==void 0?`\u53EF\u7528\u5DE5\u5177: ${c}`:void 0,u?`\u6700\u540E\u8BF7\u6C42: ${u}`:void 0].filter(h=>!!h),d=/^(authorization|x-api-key|api-key|cookie|set-cookie|x-auth-token|token)$/i,p=t.requestHeaders,m=p?Object.entries(p).filter(([h])=>!d.test(h)).map(([h,S])=>`${h}: ${S}`).filter(h=>h.trim().length>0):[],T=f.join(`
5
+ `)||"ACode \u6B63\u5728\u53D1\u9001 AI \u8BF7\u6C42",g=m.length>0?`${e}${m.join(`
6
+ `)}`:"";return`${T}${g}`}}export{ke as AcodeSdkAdapter,Jt as isFailedAcodeTurnComplete,Ht as toAcodeEsmImportSpecifier};
11
7
 
@@ -47,6 +47,8 @@ export declare class ClaudeSdkAdapter extends EventEmitter implements BaseProvid
47
47
 
48
48
  private stopIdleDetection;
49
49
 
50
+ private armIdleCheck;
51
+
50
52
  private checkIdleState;
51
53
 
52
54
  private sendIdlePrompt;
@@ -1,4 +1,4 @@
1
- import{execSync as y}from"child_process";import{EventEmitter as k}from"events";import*as p from"fs";import*as c from"path";import{v4 as h}from"uuid";import{registerListenerWakeHook as v,unregisterListenerWakeHook as g}from"../services/browser-session-manager.js";import{importBridgeSdkPackage as x}from"../utils/sdk-package-loader.js";import{IdlePollLoop as _}from"./idle-poll-loop.js";import{MESSAGE_POLLING_IDLE_PROMPT as w}from"./prompts.js";import{getToolActionInfo as f}from"./types.js";class C{constructor(){this.queue=[],this.resolve=null,this.done=!1}enqueue(t){if(!this.done)if(this.resolve){const e=this.resolve;this.resolve=null,e({value:t,done:!1})}else this.queue.push(t)}close(){if(this.done=!0,this.resolve){const t=this.resolve;this.resolve=null,t({value:void 0,done:!0})}}[Symbol.asyncIterator](){return{next:()=>{if(this.queue.length>0){const t=this.queue.shift();if(t!==void 0)return Promise.resolve({value:t,done:!1})}return this.done?Promise.resolve({value:void 0,done:!0}):new Promise(t=>{this.resolve=t})}}}}class L extends k{constructor(){super(...arguments),this.providerId="claude-code",this.displayName="Claude Code",this.sessions=new Map,this.sdkQueries=new Map,this.inputStreams=new Map,this.abortControllers=new Map,this.sdkModule=null,this.pendingPermissions=new Map,this.pendingQuestions=new Map,this.activeToolUseIds=new Map,this.recentToolNames=new Map,this.toolInputBuffers=new Map,this.idleCommands=new Map,this.idleTimers=new Map,this.idlePollLoops=new Map,this.lastActivityAt=new Map,this.sessionAgentIds=new Map,this.listenerWakeHooks=new Map}async startSession(t,e){const i={sessionId:t,status:"starting",messages:[],createdAt:new Date().toISOString(),totalUsage:{inputTokens:0,outputTokens:0}};if(this.sessions.set(t,i),e.agentId&&this.sessionAgentIds.set(t,e.agentId),e.agentId){const o=()=>{this.getIdlePollLoop(t).start()};this.listenerWakeHooks.set(t,o),v(e.agentId,o)}try{const o=await this.loadSdk(),n=new AbortController;this.abortControllers.set(t,n);const s=new C;this.inputStreams.set(t,s);const a=this.buildQueryOptions(t,e,n),r=o.query({prompt:s,options:a});if(this.sdkQueries.set(t,r),this.consumeStream(t,r).catch(l=>{console.error(`[ClaudeSdkAdapter] Stream error for ${t}:`,l)}),await new Promise(l=>setTimeout(l,100)),e.initialPrompt){i.status="starting",this.emit("status-change",t,"starting");const l={id:h(),sessionId:t,role:"user",content:e.initialPrompt,timestamp:new Date().toISOString()};i.messages.push(l),this.emit("conversation-message",t,l);const d=this.parseMessageContent(e.initialPrompt);s.enqueue({type:"user",message:{role:"user",content:d}})}else i.status="waiting_input",this.emit("status-change",t,"waiting_input",{usage:i.totalUsage}),this.idleCommands.has(t)&&this.startIdleDetection(t)}catch(o){e.agentId&&g(e.agentId,this.listenerWakeHooks.get(t)),this.listenerWakeHooks.delete(t);const n=o instanceof Error?o.message:String(o);throw i.status="error",this.emit("status-change",t,"error"),this.emitEvent(t,{type:"error",sessionId:t,timestamp:new Date().toISOString(),data:{text:`Failed to start session: ${n}`}}),o}}async sendMessage(t,e){const i=this.sessions.get(t),o=this.inputStreams.get(t);if(!i||!o)throw new Error(`Session ${t} not found`);if(i.status==="error")throw new Error(`Session ${t} is in error state`);const n={id:h(),sessionId:t,role:"user",content:e,timestamp:new Date().toISOString()};i.messages.push(n),this.emit("conversation-message",t,n),i.status="thinking",this.emit("status-change",t,"thinking");const s=this.parseMessageContent(e);o.enqueue({type:"user",message:{role:"user",content:s}})}parseMessageContent(t){const e=[],i=/\[图片\s*:\s*([^\]\n]+?)\s*\]/gi;let o=0,n=i.exec(t);for(;n!==null;){if(n.index>o){const a=t.slice(o,n.index).trim();a&&e.push({type:"text",text:a})}const s=n[1].trim();s&&e.push({type:"image",source:{type:"url",url:s}}),o=n.index+n[0].length,n=i.exec(t)}if(o<t.length){const s=t.slice(o).trim();s&&e.push({type:"text",text:s})}return e.length===0&&e.push({type:"text",text:t}),e}async sendConfirmation(t,e){const i=this.pendingPermissions.get(t);i&&(e?i.resolve({behavior:"allow",updatedInput:i.toolInput}):i.resolve({behavior:"deny",message:"User denied"}),this.pendingPermissions.delete(t))}async sendQuestionAnswer(t,e){const i=this.pendingQuestions.get(t);if(!i)return;const o=i.toolInput.questions;let n=`\u7528\u6237\u5DF2\u56DE\u7B54\u4E86\u60A8\u7684\u95EE\u9898\uFF1A
2
- `;Array.isArray(o)?o.forEach((s,a)=>{const r=String(a),l=e[r]||e[s.header||""]||e[s.question]||"\uFF08\u672A\u586B\u5199\uFF09";n+=`\u2022 ${s.header||s.question}\uFF1A${l}
3
- `}):n+=JSON.stringify(e),i.resolve({behavior:"deny",message:n}),this.pendingQuestions.delete(t)}async abortCurrentTurn(t){const e=this.abortControllers.get(t);e&&e.abort()}async terminateSession(t){const e=this.sessions.get(t),i=this.sdkQueries.get(t),o=this.inputStreams.get(t);if(o&&o.close(),i)try{i.close()}catch{}e&&(e.status="terminated",this.emit("status-change",t,"terminated"),this.emitEvent(t,{type:"session_complete",sessionId:t,timestamp:new Date().toISOString(),data:{exitCode:0}}));const n=this.sessionAgentIds.get(t);n&&g(n,this.listenerWakeHooks.get(t)),this.listenerWakeHooks.delete(t),this.cleanupSession(t)}getConversation(t){return this.sessions.get(t)?.messages??[]}hasSession(t){return this.sessions.has(t)}getProviderSessionId(t){return this.sessions.get(t)?.providerSessionId}getSessionStatus(t){return this.sessions.get(t)?.status}getSessionPid(t){return this.sessions.get(t)?.pid}cleanup(){for(const t of this.sessions.keys())try{this.terminateSession(t)}catch{}this.sessions.clear(),this.sdkQueries.clear(),this.inputStreams.clear(),this.abortControllers.clear(),this.pendingPermissions.clear(),this.pendingQuestions.clear(),this.idleCommands.clear(),this.idleTimers.clear()}setIdleCommands(t,e){this.idleCommands.set(t,e);const i=this.sessions.get(t);i&&i.status==="waiting_input"&&(e.idleInputCommand||e.nonInputCommand)&&this.startIdleDetection(t)}startIdleDetection(t){this.stopIdleDetection(t);const e=this.idleCommands.get(t);if(!e?.idleInputCommand)return;if(this.isMessagePollingIdleCommand(e.idleInputCommand)){this.getIdlePollLoop(t).start();return}this.lastActivityAt.set(t,Date.now());const i=setInterval(()=>{this.checkIdleState(t)},500);this.idleTimers.set(t,i)}stopIdleDetection(t){this.idlePollLoops.get(t)?.stop();const e=this.idleTimers.get(t);e&&(clearInterval(e),this.idleTimers.delete(t))}checkIdleState(t){const e=this.sessions.get(t);if(!e||e.status!=="waiting_input")return;const i=this.idleCommands.get(t);if(!i||!i.idleInputCommand&&!i.nonInputCommand)return;const o=this.lastActivityAt.get(t)||0;if(!(Date.now()-o<1500)&&(this.lastActivityAt.set(t,Date.now()),i.idleInputCommand)){const a=i.idleInputCommand;this.isMessagePollingIdleCommand(a)?this.sendIdlePrompt(t,this.buildMessagePollingIdlePrompt()):this.sendIdlePrompt(t,a)}}sendIdlePrompt(t,e,i){const o=this.inputStreams.get(t);if(!o)return;const n=this.sessions.get(t);n&&!i?.keepWaitingStatus&&(n.status="thinking",this.emit("status-change",t,"thinking")),o.enqueue({type:"user",message:{role:"user",content:[{type:"text",text:e}]}})}isMessagePollingIdleCommand(t){const e=t.trim();if(!e)return!1;const i=e.toLowerCase();return i.includes("poll_message")||i.includes("get_message")||e.includes("\u53D6\u6D88\u606F")}buildMessagePollingIdlePrompt(){return w}getIdlePollLoop(t){const e=this.idlePollLoops.get(t);if(e)return e;const i=new _({getStatus:()=>this.sessions.get(t)?.status,getCommand:()=>this.idleCommands.get(t)?.idleInputCommand,isPollingCommand:o=>this.isMessagePollingIdleCommand(o),preDispatchHook:()=>null,dispatchPollingPrompt:(o,n)=>this.sendIdlePrompt(t,n?o:this.buildMessagePollingIdlePrompt(),{keepWaitingStatus:!0}),dispatchRegularIdleCommand:o=>this.sendIdlePrompt(t,o)});return this.idlePollLoops.set(t,i),i}async sendShortcutInput(t,e){await this.executeIdleCommand(t,e)}async executeIdleCommand(t,e){const i=this.inputStreams.get(t);if(!i)return;const o=/\[(.+?)\]/g;let n=0;const s=[];let a=o.exec(e);for(;a!==null;){a.index>n&&s.push({type:"text",value:e.slice(n,a.index)});const r=a[1];if(r.startsWith("wait:")){const l=parseFloat(r.slice(5));isNaN(l)||s.push({type:"wait",value:l*1e3})}else{const l={enter:"\r",up:"\x1B[A",down:"\x1B[B",left:"\x1B[D",right:"\x1B[C",tab:" ",esc:"\x1B",escape:"\x1B",space:" ","ctrl+c":""};s.push({type:"key",value:l[r.toLowerCase()]||r})}n=a.index+a[0].length,a=o.exec(e)}n<e.length&&s.push({type:"text",value:e.slice(n)});for(const r of s)if(r.type==="wait")await new Promise(l=>setTimeout(l,r.value));else{const l=String(r.value);i.enqueue({type:"user",message:{role:"user",content:[{type:"text",text:l}]}})}}updateActivity(t){this.lastActivityAt.set(t,Date.now())}async resumeSession(t,e,i){const o={sessionId:t,providerSessionId:e,status:"starting",messages:[],createdAt:new Date().toISOString(),totalUsage:{inputTokens:0,outputTokens:0}};this.sessions.set(t,o);try{await this.startSession(t,i),o.providerSessionId=e}catch(n){throw o.status="error",this.emit("status-change",t,"error"),n}}async loadSdk(){if(!this.sdkModule)try{this.sdkModule=await x("@anthropic-ai/claude-agent-sdk")}catch(t){throw new Error(`Failed to load @anthropic-ai/claude-agent-sdk. Please install: npm install @anthropic-ai/claude-agent-sdk. Original error: ${t}`)}return this.sdkModule}findClaudeExecutable(t){const e=this.extractExecutableCommand(t);if(c.isAbsolute(e)&&p.existsSync(e)){const s=this.resolveWindowsWrapper(e);if(s)return s;if(this.isWindowsWrapperPath(e)){console.warn(`[ClaudeSdkAdapter] Skipping wrapper script for Claude Code executable: ${e}`);return}return e}const i=this.resolveExecutableFromPath(e);if(i)return i;if(process.platform==="win32"&&this.shouldUseDefaultClaudeFallbacks(e)){const s=process.env.USERPROFILE||"",a=process.env.LOCALAPPDATA||"",r=process.env.APPDATA||"",l=[c.join(a,"Volta","tools","shared","@anthropic-ai","claude-code","cli.js"),c.join(a,"Volta","tools","image","packages","@anthropic-ai","claude-code","cli.js")];for(const u of l)if(p.existsSync(u))return u;const d=[c.join(r,"npm","node_modules","@anthropic-ai","claude-code","cli.js"),c.join(a,"Programs","claude-code","claude.exe"),c.join(s,".local","bin","claude.exe")];for(const u of d)if(u&&p.existsSync(u))return u}const o=process.env.HOME||"",n=[c.join(o,".local","bin","claude"),c.join(o,".npm-global","bin","claude"),c.join(o,".local","share","mise","shims","claude"),c.join(o,".asdf","shims","claude"),"/opt/homebrew/bin/claude","/usr/local/bin/claude","/usr/bin/claude","/usr/local/lib/node_modules/@anthropic-ai/claude-code/cli.js","/usr/lib/node_modules/@anthropic-ai/claude-code/cli.js",c.join(o,".local","share","volta","tools","shared","@anthropic-ai","claude-code","cli.js"),c.join(o,".volta","tools","shared","@anthropic-ai","claude-code","cli.js")];if(this.shouldUseDefaultClaudeFallbacks(e)){for(const s of n)if(s&&p.existsSync(s))return s}if(this.shouldUseDefaultClaudeFallbacks(e))try{const s=y("npm root -g",{encoding:"utf8",timeout:5e3}).trim(),a=c.join(s,"@anthropic-ai","claude-code","cli.js");if(p.existsSync(a))return a}catch{}console.warn(`[ClaudeSdkAdapter] Claude Code executable not found for command: ${e}`)}extractExecutableCommand(t){const i=((t||"claude").trim()||"claude").match(/^\s*(?:"([^"]+)"|'([^']+)'|(\S+))/);return i?.[1]||i?.[2]||i?.[3]||"claude"}resolveExecutableFromPath(t){const e=process.env.PATH||"";if(!e)return;const i=c.extname(t).length>0,o=process.platform==="win32"?this.getWindowsPathExtensions(i):[""];for(const n of e.split(c.delimiter))if(n)for(const s of o){const a=c.join(n,`${t}${s}`);if(p.existsSync(a)){if(this.isWindowsWrapperPath(a)){const r=this.resolveWindowsWrapper(a);if(r)return r;continue}return a}}}getWindowsPathExtensions(t){return t?[""]:(process.env.PATHEXT||".EXE;.CMD;.BAT;.COM;.PS1").split(";").map(i=>i.trim()).filter(i=>i.length>0)}shouldUseDefaultClaudeFallbacks(t){return["claude","claude-code","claudecode"].includes(t.toLowerCase())}isWindowsWrapperPath(t){const e=c.extname(t).toLowerCase();return[".cmd",".bat",".ps1"].includes(e)}resolveWindowsWrapper(t){if(this.isWindowsWrapperPath(t))return this.resolveCliJsFromWrapper(t)}resolveCliJsFromWrapper(t){try{if(p.readFileSync(t,"utf8").includes("volta run")){const n=c.join(process.env.LOCALAPPDATA||"","Volta","tools","shared","@anthropic-ai","claude-code","cli.js");if(p.existsSync(n))return n}const i=c.dirname(t),o=c.join(i,"node_modules","@anthropic-ai","claude-code","cli.js");if(p.existsSync(o))return o}catch{}}buildQueryOptions(t,e,i){const o={cwd:e.workingDirectory,abortController:i,settingSources:["user","project","local"],includePartialMessages:!0},n=this.findClaudeExecutable(e.command);if(n?o.pathToClaudeCodeExecutable=n:console.warn(`[ClaudeSdkAdapter] \u2605\u2605\u2605 \u8B66\u544A\uFF1A\u672A\u627E\u5230 Claude Code \u53EF\u6267\u884C\u6587\u4EF6 \u2605\u2605\u2605 command="${e.command}"`),e.model&&(o.model=e.model),e.maxTurns&&e.maxTurns>0&&(o.maxTurns=e.maxTurns),e.mcpConfigPath)try{const s=p.readFileSync(e.mcpConfigPath,"utf-8"),a=JSON.parse(s);o.mcpServers={...e.extraMcpServers,...a.mcpServers}}catch{o.mcpServers=e.extraMcpServers||{}}else o.mcpServers=e.extraMcpServers||{};return e.allowedTools&&e.allowedTools.length>0?o.allowedTools=e.allowedTools:o.allowedTools=["Read","Write","Edit","Bash","Glob","Grep","WebSearch","WebFetch","Task","NotebookEdit","LSP","Skill","mcp__*"],o.env={...process.env,...e.envOverrides},o.canUseTool=this.createPermissionHandler(t,e.autoAccept),o}createPermissionHandler(t,e){return async(i,o,n)=>i==="AskUserQuestion"||i==="ask_user_question"?new Promise(s=>{this.pendingQuestions.set(t,{resolve:s,toolInput:o}),this.emit("ask-user-question",{sessionId:t,toolCallId:this.activeToolUseIds.get(t)||void 0,questions:o.questions})}):e?{behavior:"allow",updatedInput:o}:new Promise(s=>{this.pendingPermissions.set(t,{resolve:s,toolInput:o}),this.emit("permission-request",{sessionId:t,toolName:i,toolInput:o,permissionPrompt:`Allow ${i}?`})})}async consumeStream(t,e){const i=this.sessions.get(t);if(i)try{for await(const o of e){const n=o;this.handleSdkMessage(t,i,n)}}catch(o){if(this.abortControllers.get(t)?.signal.aborted)return;const n=o instanceof Error?o.message:String(o);this.emitEvent(t,{type:"error",sessionId:t,timestamp:new Date().toISOString(),data:{text:`Stream error: ${n}`}})}}applyUsage(t,e){e&&(Number.isFinite(e.input_tokens)&&(t.totalUsage.inputTokens=Math.max(t.totalUsage.inputTokens,e.input_tokens??0)),Number.isFinite(e.output_tokens)&&(t.totalUsage.outputTokens=Math.max(t.totalUsage.outputTokens,e.output_tokens??0)))}handleSdkMessage(t,e,i){const o=new Date().toISOString();switch(i.type){case"text":i.delta&&(e.status!=="thinking"&&(e.status="thinking",this.emit("status-change",t,"thinking"),this.stopIdleDetection(t)),this.emitEvent(t,{type:"text_delta",sessionId:t,timestamp:o,data:{text:i.delta}}));break;case"thinking":e.status!=="thinking"&&(e.status="thinking",this.emit("status-change",t,"thinking"),this.stopIdleDetection(t)),(i.content||i.delta)&&this.emitEvent(t,{type:"thinking",sessionId:t,timestamp:o,data:{text:i.delta||i.content}});break;case"tool_use":case"tool_use_start":{const n={...f(i.tool_name,i.tool_input),actionId:i.tool_use_id},s=n.actionType==="idle"?"waiting_input":"tool_using";e.status=s;const a=this.extractMcpServerName(i.tool_name||"");this.emit("status-change",t,s,{actionType:n.actionType,actionLabel:n.actionLabel,actionDetail:n.actionDetail,actionId:n.actionId,usage:e.totalUsage,...a?{metadata:{mcpServer:a}}:{}}),n.actionType!=="idle"&&this.stopIdleDetection(t),this.handleToolUse(t,e,i,o)}break;case"tool_result":case"tool_use_end":this.emitEvent(t,{type:"tool_use_end",sessionId:t,timestamp:o,data:{toolName:i.tool_name,toolResult:i.tool_result,isError:i.is_error,toolUseId:i.tool_use_id}});break;case"result":{const n=i.subtype==="success";this.applyUsage(e,i.usage),this.emitEvent(t,{type:"turn_complete",sessionId:t,timestamp:o,data:{usage:e.totalUsage,text:n?i.result:void 0}}),e.status="waiting_input",(()=>{const a=this.idleCommands.get(t);return!!(a?.idleInputCommand&&this.isMessagePollingIdleCommand(a.idleInputCommand))})()?this.emit("status-change",t,"waiting_input",{actionType:"idle",actionLabel:"\u76D1\u542C\u6D88\u606F",actionDetail:"aws-mcp/poll_message",usage:e.totalUsage}):this.emit("status-change",t,"waiting_input",{usage:e.totalUsage}),this.idleCommands.has(t)&&this.startIdleDetection(t)}break;case"system":break;case"assistant":if(this.applyUsage(e,i.message?.usage),i.message?.content){const n=i.message.content.filter(s=>s.type==="text"&&s.text).map(s=>s.text||"").join("");n&&e.messages.push({id:h(),sessionId:t,role:"assistant",content:n,timestamp:o})}break;case"user":i.tool_use_result;break;case"error":e.status="error",this.emit("status-change",t,"error"),this.emitEvent(t,{type:"error",sessionId:t,timestamp:o,data:{text:i.content||"Unknown error"}});break;case"stream_event":this.handleStreamEvent(t,e,i,o);break;default:break}}handleToolUse(t,e,i,o){const n=this.recentToolNames.get(t),s=this.extractToolNameSuffix(i.tool_name||"");if(n&&Date.now()-n.time<3e4&&n.name===s){this.recentToolNames.delete(t),this.activeToolUseIds.delete(t),e.messages.push({id:h(),sessionId:t,role:"tool_use",content:`${i.tool_name}: ${JSON.stringify(i.tool_input).slice(0,100)}`,timestamp:o,toolName:i.tool_name,toolInput:i.tool_input,toolUseId:i.tool_use_id});return}this.recentToolNames.delete(t),this.activeToolUseIds.delete(t);const a=f(i.tool_name,i.tool_input),r=this.extractMcpServerName(i.tool_name||"");this.emitEvent(t,{type:"tool_use_start",sessionId:t,timestamp:o,data:{toolName:i.tool_name,toolInput:i.tool_input,toolUseId:i.tool_use_id,actionType:a.actionType,actionLabel:a.actionLabel,actionDetail:a.actionDetail,...r?{metadata:{mcpServer:r}}:{}}}),e.messages.push({id:h(),sessionId:t,role:"tool_use",content:`${i.tool_name}: ${JSON.stringify(i.tool_input).slice(0,100)}`,timestamp:o,toolName:i.tool_name,toolInput:i.tool_input,toolUseId:i.tool_use_id})}handleStreamEvent(t,e,i,o){const n=i.event;if(n){if(n.type==="content_block_start"){const s=n.content_block;if(s?.type==="tool_use"&&s.name){const a=s.name,r=s.id||`stream_${Date.now()}`;this.activeToolUseIds.set(t,r);const l=this.extractToolNameSuffix(a);this.recentToolNames.set(t,{name:l,time:Date.now()});const d=`${t}:${r}`;this.toolInputBuffers.set(d,"")}}if(n.type==="content_block_delta"&&n.delta?.type==="input_json_delta"&&n.delta.partial_json){const s=this.activeToolUseIds.get(t);if(s){const a=`${t}:${s}`,r=this.toolInputBuffers.get(a)||"";this.toolInputBuffers.set(a,r+n.delta.partial_json)}}if(n.type==="content_block_stop"){const s=this.activeToolUseIds.get(t),a=this.recentToolNames.get(t);if(s&&a){const r=`${t}:${s}`,l=this.toolInputBuffers.get(r)||"";let d;if(l)try{d=JSON.parse(l)}catch{console.warn("[ClaudeSdkAdapter] Failed to parse tool input JSON:",l.slice(0,100))}const u={...f(a.name,d),actionId:s},m=this.extractMcpServerName(a.name);e.status="tool_using",this.emit("status-change",t,"tool_using",{actionType:u.actionType,actionLabel:u.actionLabel,actionDetail:u.actionDetail,actionId:u.actionId,usage:e.totalUsage,...m?{metadata:{mcpServer:m}}:{}}),this.stopIdleDetection(t),this.emitEvent(t,{type:"tool_use_start",sessionId:t,timestamp:o,data:{toolName:a.name,toolInput:d,toolUseId:s,actionType:u.actionType,actionLabel:u.actionLabel,actionDetail:u.actionDetail,actionId:u.actionId,...m?{metadata:{mcpServer:m}}:{}}}),e.messages.push({id:h(),sessionId:t,role:"tool_use",content:`${a.name}: ${l.slice(0,100)}`,timestamp:o,toolName:a.name,toolInput:d,toolUseId:s}),this.toolInputBuffers.delete(r),this.activeToolUseIds.delete(t)}}}}extractMcpServerName(t){if(t.startsWith("mcp__")){const e=t.split("__");if(e.length>=3)return e[1]}}extractToolNameSuffix(t){if(t.includes("__"))return t.split("__").pop()||t;if(t.includes("-mcp__")){const e=t.indexOf("-mcp__");return t.substring(e+6)}return t}emitEvent(t,e){this.emit("event",e)}cleanupSession(t){this.stopIdleDetection(t),this.sessions.delete(t),this.sdkQueries.delete(t),this.inputStreams.delete(t),this.abortControllers.delete(t),this.pendingPermissions.delete(t),this.pendingQuestions.delete(t),this.idleCommands.delete(t),this.idlePollLoops.delete(t),this.sessionAgentIds.delete(t),this.lastActivityAt.delete(t)}}export{L as ClaudeSdkAdapter};
1
+ import{execSync as k}from"child_process";import{EventEmitter as y}from"events";import*as p from"fs";import*as c from"path";import{v4 as h}from"uuid";import{registerListenerWakeHook as v,unregisterListenerWakeHook as g}from"../services/browser-session-manager.js";import{injectEffectiveEnvIntoMcpServers as x}from"../services/mcp-env-injector.js";import{getPanelEnvVars as _}from"../services/panel-env.js";import{importBridgeSdkPackage as w}from"../utils/sdk-package-loader.js";import{IdlePollLoop as C}from"./idle-poll-loop.js";import{MESSAGE_POLLING_IDLE_PROMPT as b}from"./prompts.js";import{getToolActionInfo as f}from"./types.js";class P{constructor(){this.queue=[],this.resolve=null,this.done=!1}enqueue(t){if(!this.done)if(this.resolve){const e=this.resolve;this.resolve=null,e({value:t,done:!1})}else this.queue.push(t)}close(){if(this.done=!0,this.resolve){const t=this.resolve;this.resolve=null,t({value:void 0,done:!0})}}[Symbol.asyncIterator](){return{next:()=>{if(this.queue.length>0){const t=this.queue.shift();if(t!==void 0)return Promise.resolve({value:t,done:!1})}return this.done?Promise.resolve({value:void 0,done:!0}):new Promise(t=>{this.resolve=t})}}}}class $ extends y{constructor(){super(...arguments),this.providerId="claude-code",this.displayName="Claude Code",this.sessions=new Map,this.sdkQueries=new Map,this.inputStreams=new Map,this.abortControllers=new Map,this.sdkModule=null,this.pendingPermissions=new Map,this.pendingQuestions=new Map,this.activeToolUseIds=new Map,this.recentToolNames=new Map,this.toolInputBuffers=new Map,this.idleCommands=new Map,this.idleTimers=new Map,this.idlePollLoops=new Map,this.lastActivityAt=new Map,this.sessionAgentIds=new Map,this.listenerWakeHooks=new Map}async startSession(t,e){const i={sessionId:t,status:"starting",messages:[],createdAt:new Date().toISOString(),totalUsage:{inputTokens:0,outputTokens:0}};if(this.sessions.set(t,i),e.agentId&&this.sessionAgentIds.set(t,e.agentId),e.agentId){const o=()=>{this.getIdlePollLoop(t).start()};this.listenerWakeHooks.set(t,o),v(e.agentId,o)}try{const o=await this.loadSdk(),n=new AbortController;this.abortControllers.set(t,n);const a=new P;this.inputStreams.set(t,a);const s=this.buildQueryOptions(t,e,n),r=o.query({prompt:a,options:s});if(this.sdkQueries.set(t,r),this.consumeStream(t,r).catch(l=>{console.error(`[ClaudeSdkAdapter] Stream error for ${t}:`,l)}),await new Promise(l=>setTimeout(l,100)),e.initialPrompt){i.status="starting",this.emit("status-change",t,"starting");const l={id:h(),sessionId:t,role:"user",content:e.initialPrompt,timestamp:new Date().toISOString()};i.messages.push(l),this.emit("conversation-message",t,l);const d=this.parseMessageContent(e.initialPrompt);a.enqueue({type:"user",message:{role:"user",content:d}})}else i.status="waiting_input",this.emit("status-change",t,"waiting_input",{usage:i.totalUsage}),this.idleCommands.has(t)&&this.startIdleDetection(t)}catch(o){e.agentId&&g(e.agentId,this.listenerWakeHooks.get(t)),this.listenerWakeHooks.delete(t);const n=o instanceof Error?o.message:String(o);throw i.status="error",this.emit("status-change",t,"error"),this.emitEvent(t,{type:"error",sessionId:t,timestamp:new Date().toISOString(),data:{text:`Failed to start session: ${n}`}}),o}}async sendMessage(t,e){const i=this.sessions.get(t),o=this.inputStreams.get(t);if(!i||!o)throw new Error(`Session ${t} not found`);if(i.status==="error")throw new Error(`Session ${t} is in error state`);const n={id:h(),sessionId:t,role:"user",content:e,timestamp:new Date().toISOString()};i.messages.push(n),this.emit("conversation-message",t,n),i.status="thinking",this.emit("status-change",t,"thinking");const a=this.parseMessageContent(e);o.enqueue({type:"user",message:{role:"user",content:a}})}parseMessageContent(t){const e=[],i=/\[图片\s*:\s*([^\]\n]+?)\s*\]/gi;let o=0,n=i.exec(t);for(;n!==null;){if(n.index>o){const s=t.slice(o,n.index).trim();s&&e.push({type:"text",text:s})}const a=n[1].trim();a&&e.push({type:"image",source:{type:"url",url:a}}),o=n.index+n[0].length,n=i.exec(t)}if(o<t.length){const a=t.slice(o).trim();a&&e.push({type:"text",text:a})}return e.length===0&&e.push({type:"text",text:t}),e}async sendConfirmation(t,e){const i=this.pendingPermissions.get(t);i&&(e?i.resolve({behavior:"allow",updatedInput:i.toolInput}):i.resolve({behavior:"deny",message:"User denied"}),this.pendingPermissions.delete(t))}async sendQuestionAnswer(t,e){const i=this.pendingQuestions.get(t);if(!i)return;const o=i.toolInput.questions;let n=`\u7528\u6237\u5DF2\u56DE\u7B54\u4E86\u60A8\u7684\u95EE\u9898\uFF1A
2
+ `;Array.isArray(o)?o.forEach((a,s)=>{const r=String(s),l=e[r]||e[a.header||""]||e[a.question]||"\uFF08\u672A\u586B\u5199\uFF09";n+=`\u2022 ${a.header||a.question}\uFF1A${l}
3
+ `}):n+=JSON.stringify(e),i.resolve({behavior:"deny",message:n}),this.pendingQuestions.delete(t)}async abortCurrentTurn(t){const e=this.abortControllers.get(t);e&&e.abort()}async terminateSession(t){const e=this.sessions.get(t),i=this.sdkQueries.get(t),o=this.inputStreams.get(t);if(o&&o.close(),i)try{i.close()}catch{}e&&(e.status="terminated",this.emit("status-change",t,"terminated"),this.emitEvent(t,{type:"session_complete",sessionId:t,timestamp:new Date().toISOString(),data:{exitCode:0}}));const n=this.sessionAgentIds.get(t);n&&g(n,this.listenerWakeHooks.get(t)),this.listenerWakeHooks.delete(t),this.cleanupSession(t)}getConversation(t){return this.sessions.get(t)?.messages??[]}hasSession(t){return this.sessions.has(t)}getProviderSessionId(t){return this.sessions.get(t)?.providerSessionId}getSessionStatus(t){return this.sessions.get(t)?.status}getSessionPid(t){return this.sessions.get(t)?.pid}cleanup(){for(const t of this.sessions.keys())try{this.terminateSession(t)}catch{}this.sessions.clear(),this.sdkQueries.clear(),this.inputStreams.clear(),this.abortControllers.clear(),this.pendingPermissions.clear(),this.pendingQuestions.clear(),this.idleCommands.clear(),this.idleTimers.clear()}setIdleCommands(t,e){this.idleCommands.set(t,e);const i=this.sessions.get(t);i&&i.status==="waiting_input"&&(e.idleInputCommand||e.nonInputCommand)&&this.startIdleDetection(t)}startIdleDetection(t){this.stopIdleDetection(t);const e=this.idleCommands.get(t);if(e?.idleInputCommand){if(this.isMessagePollingIdleCommand(e.idleInputCommand)){this.getIdlePollLoop(t).start();return}this.lastActivityAt.set(t,Date.now()),this.armIdleCheck(t)}}stopIdleDetection(t){this.idlePollLoops.get(t)?.stop();const e=this.idleTimers.get(t);e&&(clearTimeout(e),this.idleTimers.delete(t))}armIdleCheck(t){const e=this.idleTimers.get(t);e&&clearTimeout(e);const i=setTimeout(()=>{this.idleTimers.get(t)===i&&(this.idleTimers.delete(t),this.armIdleCheck(t),this.checkIdleState(t))},500);this.idleTimers.set(t,i)}checkIdleState(t){const e=this.sessions.get(t);if(!e||e.status!=="waiting_input")return;const i=this.idleCommands.get(t);if(!i||!i.idleInputCommand&&!i.nonInputCommand)return;const o=this.lastActivityAt.get(t)||0;if(!(Date.now()-o<1500)&&(this.lastActivityAt.set(t,Date.now()),i.idleInputCommand)){const s=i.idleInputCommand;this.isMessagePollingIdleCommand(s)?this.sendIdlePrompt(t,this.buildMessagePollingIdlePrompt()):this.sendIdlePrompt(t,s)}}sendIdlePrompt(t,e,i){const o=this.inputStreams.get(t);if(!o)return;const n=this.sessions.get(t);n&&!i?.keepWaitingStatus&&(n.status="thinking",this.emit("status-change",t,"thinking")),o.enqueue({type:"user",message:{role:"user",content:[{type:"text",text:e}]}})}isMessagePollingIdleCommand(t){const e=t.trim();if(!e)return!1;const i=e.toLowerCase();return i.includes("poll_message")||i.includes("get_message")||e.includes("\u53D6\u6D88\u606F")}buildMessagePollingIdlePrompt(){return b}getIdlePollLoop(t){const e=this.idlePollLoops.get(t);if(e)return e;const i=new C({getStatus:()=>this.sessions.get(t)?.status,getCommand:()=>this.idleCommands.get(t)?.idleInputCommand,isPollingCommand:o=>this.isMessagePollingIdleCommand(o),preDispatchHook:()=>null,dispatchPollingPrompt:(o,n)=>this.sendIdlePrompt(t,n?o:this.buildMessagePollingIdlePrompt(),{keepWaitingStatus:!0}),dispatchRegularIdleCommand:o=>this.sendIdlePrompt(t,o)});return this.idlePollLoops.set(t,i),i}async sendShortcutInput(t,e){await this.executeIdleCommand(t,e)}async executeIdleCommand(t,e){const i=this.inputStreams.get(t);if(!i)return;const o=/\[(.+?)\]/g;let n=0;const a=[];let s=o.exec(e);for(;s!==null;){s.index>n&&a.push({type:"text",value:e.slice(n,s.index)});const r=s[1];if(r.startsWith("wait:")){const l=parseFloat(r.slice(5));isNaN(l)||a.push({type:"wait",value:l*1e3})}else{const l={enter:"\r",up:"\x1B[A",down:"\x1B[B",left:"\x1B[D",right:"\x1B[C",tab:" ",esc:"\x1B",escape:"\x1B",space:" ","ctrl+c":""};a.push({type:"key",value:l[r.toLowerCase()]||r})}n=s.index+s[0].length,s=o.exec(e)}n<e.length&&a.push({type:"text",value:e.slice(n)});for(const r of a)if(r.type==="wait")await new Promise(l=>setTimeout(l,r.value));else{const l=String(r.value);i.enqueue({type:"user",message:{role:"user",content:[{type:"text",text:l}]}})}}updateActivity(t){this.lastActivityAt.set(t,Date.now()),this.idleTimers.has(t)&&this.armIdleCheck(t)}async resumeSession(t,e,i){const o={sessionId:t,providerSessionId:e,status:"starting",messages:[],createdAt:new Date().toISOString(),totalUsage:{inputTokens:0,outputTokens:0}};this.sessions.set(t,o);try{await this.startSession(t,i),o.providerSessionId=e}catch(n){throw o.status="error",this.emit("status-change",t,"error"),n}}async loadSdk(){if(!this.sdkModule)try{this.sdkModule=await w("@anthropic-ai/claude-agent-sdk")}catch(t){throw new Error(`Failed to load @anthropic-ai/claude-agent-sdk. Please install: npm install @anthropic-ai/claude-agent-sdk. Original error: ${t}`)}return this.sdkModule}findClaudeExecutable(t){const e=this.extractExecutableCommand(t);if(c.isAbsolute(e)&&p.existsSync(e)){const a=this.resolveWindowsWrapper(e);if(a)return a;if(this.isWindowsWrapperPath(e)){console.warn(`[ClaudeSdkAdapter] Skipping wrapper script for Claude Code executable: ${e}`);return}return e}const i=this.resolveExecutableFromPath(e);if(i)return i;if(process.platform==="win32"&&this.shouldUseDefaultClaudeFallbacks(e)){const a=process.env.USERPROFILE||"",s=process.env.LOCALAPPDATA||"",r=process.env.APPDATA||"",l=[c.join(s,"Volta","tools","shared","@anthropic-ai","claude-code","cli.js"),c.join(s,"Volta","tools","image","packages","@anthropic-ai","claude-code","cli.js")];for(const u of l)if(p.existsSync(u))return u;const d=[c.join(r,"npm","node_modules","@anthropic-ai","claude-code","cli.js"),c.join(s,"Programs","claude-code","claude.exe"),c.join(a,".local","bin","claude.exe")];for(const u of d)if(u&&p.existsSync(u))return u}const o=process.env.HOME||"",n=[c.join(o,".local","bin","claude"),c.join(o,".npm-global","bin","claude"),c.join(o,".local","share","mise","shims","claude"),c.join(o,".asdf","shims","claude"),"/opt/homebrew/bin/claude","/usr/local/bin/claude","/usr/bin/claude","/usr/local/lib/node_modules/@anthropic-ai/claude-code/cli.js","/usr/lib/node_modules/@anthropic-ai/claude-code/cli.js",c.join(o,".local","share","volta","tools","shared","@anthropic-ai","claude-code","cli.js"),c.join(o,".volta","tools","shared","@anthropic-ai","claude-code","cli.js")];if(this.shouldUseDefaultClaudeFallbacks(e)){for(const a of n)if(a&&p.existsSync(a))return a}if(this.shouldUseDefaultClaudeFallbacks(e))try{const a=k("npm root -g",{encoding:"utf8",timeout:5e3}).trim(),s=c.join(a,"@anthropic-ai","claude-code","cli.js");if(p.existsSync(s))return s}catch{}console.warn(`[ClaudeSdkAdapter] Claude Code executable not found for command: ${e}`)}extractExecutableCommand(t){const i=((t||"claude").trim()||"claude").match(/^\s*(?:"([^"]+)"|'([^']+)'|(\S+))/);return i?.[1]||i?.[2]||i?.[3]||"claude"}resolveExecutableFromPath(t){const e=process.env.PATH||"";if(!e)return;const i=c.extname(t).length>0,o=process.platform==="win32"?this.getWindowsPathExtensions(i):[""];for(const n of e.split(c.delimiter))if(n)for(const a of o){const s=c.join(n,`${t}${a}`);if(p.existsSync(s)){if(this.isWindowsWrapperPath(s)){const r=this.resolveWindowsWrapper(s);if(r)return r;continue}return s}}}getWindowsPathExtensions(t){return t?[""]:(process.env.PATHEXT||".EXE;.CMD;.BAT;.COM;.PS1").split(";").map(i=>i.trim()).filter(i=>i.length>0)}shouldUseDefaultClaudeFallbacks(t){return["claude","claude-code","claudecode"].includes(t.toLowerCase())}isWindowsWrapperPath(t){const e=c.extname(t).toLowerCase();return[".cmd",".bat",".ps1"].includes(e)}resolveWindowsWrapper(t){if(this.isWindowsWrapperPath(t))return this.resolveCliJsFromWrapper(t)}resolveCliJsFromWrapper(t){try{if(p.readFileSync(t,"utf8").includes("volta run")){const n=c.join(process.env.LOCALAPPDATA||"","Volta","tools","shared","@anthropic-ai","claude-code","cli.js");if(p.existsSync(n))return n}const i=c.dirname(t),o=c.join(i,"node_modules","@anthropic-ai","claude-code","cli.js");if(p.existsSync(o))return o}catch{}}buildQueryOptions(t,e,i){const o={cwd:e.workingDirectory,abortController:i,settingSources:["user","project","local"],includePartialMessages:!0},n=this.findClaudeExecutable(e.command);if(n?o.pathToClaudeCodeExecutable=n:console.warn(`[ClaudeSdkAdapter] \u2605\u2605\u2605 \u8B66\u544A\uFF1A\u672A\u627E\u5230 Claude Code \u53EF\u6267\u884C\u6587\u4EF6 \u2605\u2605\u2605 command="${e.command}"`),e.model&&(o.model=e.model),e.maxTurns&&e.maxTurns>0&&(o.maxTurns=e.maxTurns),e.mcpConfigPath)try{const a=p.readFileSync(e.mcpConfigPath,"utf-8"),s=JSON.parse(a);o.mcpServers={...e.extraMcpServers,...s.mcpServers}}catch{o.mcpServers=e.extraMcpServers||{}}else o.mcpServers=e.extraMcpServers||{};return o.mcpServers&&typeof o.mcpServers=="object"&&x(o.mcpServers,_(e.agentId)),e.allowedTools&&e.allowedTools.length>0?o.allowedTools=e.allowedTools:o.allowedTools=["Read","Write","Edit","Bash","Glob","Grep","WebSearch","WebFetch","Task","NotebookEdit","LSP","Skill","mcp__*"],o.env={...process.env,...e.envOverrides},o.canUseTool=this.createPermissionHandler(t,e.autoAccept),o}createPermissionHandler(t,e){return async(i,o,n)=>i==="AskUserQuestion"||i==="ask_user_question"?new Promise(a=>{this.pendingQuestions.set(t,{resolve:a,toolInput:o}),this.emit("ask-user-question",{sessionId:t,toolCallId:this.activeToolUseIds.get(t)||void 0,questions:o.questions})}):e?{behavior:"allow",updatedInput:o}:new Promise(a=>{this.pendingPermissions.set(t,{resolve:a,toolInput:o}),this.emit("permission-request",{sessionId:t,toolName:i,toolInput:o,permissionPrompt:`Allow ${i}?`})})}async consumeStream(t,e){const i=this.sessions.get(t);if(i)try{for await(const o of e){const n=o;this.handleSdkMessage(t,i,n)}}catch(o){if(this.abortControllers.get(t)?.signal.aborted)return;const n=o instanceof Error?o.message:String(o);this.emitEvent(t,{type:"error",sessionId:t,timestamp:new Date().toISOString(),data:{text:`Stream error: ${n}`}})}}applyUsage(t,e){e&&(Number.isFinite(e.input_tokens)&&(t.totalUsage.inputTokens=Math.max(t.totalUsage.inputTokens,e.input_tokens??0)),Number.isFinite(e.output_tokens)&&(t.totalUsage.outputTokens=Math.max(t.totalUsage.outputTokens,e.output_tokens??0)))}handleSdkMessage(t,e,i){const o=new Date().toISOString();switch(i.type){case"text":i.delta&&(e.status!=="thinking"&&(e.status="thinking",this.emit("status-change",t,"thinking"),this.stopIdleDetection(t)),this.emitEvent(t,{type:"text_delta",sessionId:t,timestamp:o,data:{text:i.delta}}));break;case"thinking":e.status!=="thinking"&&(e.status="thinking",this.emit("status-change",t,"thinking"),this.stopIdleDetection(t)),(i.content||i.delta)&&this.emitEvent(t,{type:"thinking",sessionId:t,timestamp:o,data:{text:i.delta||i.content}});break;case"tool_use":case"tool_use_start":{const n={...f(i.tool_name,i.tool_input),actionId:i.tool_use_id},a=n.actionType==="idle"?"waiting_input":"tool_using";e.status=a;const s=this.extractMcpServerName(i.tool_name||"");this.emit("status-change",t,a,{actionType:n.actionType,actionLabel:n.actionLabel,actionDetail:n.actionDetail,actionId:n.actionId,usage:e.totalUsage,...s?{metadata:{mcpServer:s}}:{}}),n.actionType!=="idle"&&this.stopIdleDetection(t),this.handleToolUse(t,e,i,o)}break;case"tool_result":case"tool_use_end":this.emitEvent(t,{type:"tool_use_end",sessionId:t,timestamp:o,data:{toolName:i.tool_name,toolResult:i.tool_result,isError:i.is_error,toolUseId:i.tool_use_id}});break;case"result":{const n=i.subtype==="success";this.applyUsage(e,i.usage),this.emitEvent(t,{type:"turn_complete",sessionId:t,timestamp:o,data:{usage:e.totalUsage,text:n?i.result:void 0}}),e.status="waiting_input",(()=>{const s=this.idleCommands.get(t);return!!(s?.idleInputCommand&&this.isMessagePollingIdleCommand(s.idleInputCommand))})()?this.emit("status-change",t,"waiting_input",{actionType:"idle",actionLabel:"\u76D1\u542C\u6D88\u606F",actionDetail:"aws-mcp/poll_message",usage:e.totalUsage}):this.emit("status-change",t,"waiting_input",{usage:e.totalUsage}),this.idleCommands.has(t)&&this.startIdleDetection(t)}break;case"system":break;case"assistant":if(this.applyUsage(e,i.message?.usage),i.message?.content){const n=i.message.content.filter(a=>a.type==="text"&&a.text).map(a=>a.text||"").join("");n&&e.messages.push({id:h(),sessionId:t,role:"assistant",content:n,timestamp:o})}break;case"user":i.tool_use_result;break;case"error":e.status="error",this.emit("status-change",t,"error"),this.emitEvent(t,{type:"error",sessionId:t,timestamp:o,data:{text:i.content||"Unknown error"}});break;case"stream_event":this.handleStreamEvent(t,e,i,o);break;default:break}}handleToolUse(t,e,i,o){const n=this.recentToolNames.get(t),a=this.extractToolNameSuffix(i.tool_name||"");if(n&&Date.now()-n.time<3e4&&n.name===a){this.recentToolNames.delete(t),this.activeToolUseIds.delete(t),e.messages.push({id:h(),sessionId:t,role:"tool_use",content:`${i.tool_name}: ${JSON.stringify(i.tool_input).slice(0,100)}`,timestamp:o,toolName:i.tool_name,toolInput:i.tool_input,toolUseId:i.tool_use_id});return}this.recentToolNames.delete(t),this.activeToolUseIds.delete(t);const s=f(i.tool_name,i.tool_input),r=this.extractMcpServerName(i.tool_name||"");this.emitEvent(t,{type:"tool_use_start",sessionId:t,timestamp:o,data:{toolName:i.tool_name,toolInput:i.tool_input,toolUseId:i.tool_use_id,actionType:s.actionType,actionLabel:s.actionLabel,actionDetail:s.actionDetail,...r?{metadata:{mcpServer:r}}:{}}}),e.messages.push({id:h(),sessionId:t,role:"tool_use",content:`${i.tool_name}: ${JSON.stringify(i.tool_input).slice(0,100)}`,timestamp:o,toolName:i.tool_name,toolInput:i.tool_input,toolUseId:i.tool_use_id})}handleStreamEvent(t,e,i,o){const n=i.event;if(n){if(n.type==="content_block_start"){const a=n.content_block;if(a?.type==="tool_use"&&a.name){const s=a.name,r=a.id||`stream_${Date.now()}`;this.activeToolUseIds.set(t,r);const l=this.extractToolNameSuffix(s);this.recentToolNames.set(t,{name:l,time:Date.now()});const d=`${t}:${r}`;this.toolInputBuffers.set(d,"")}}if(n.type==="content_block_delta"&&n.delta?.type==="input_json_delta"&&n.delta.partial_json){const a=this.activeToolUseIds.get(t);if(a){const s=`${t}:${a}`,r=this.toolInputBuffers.get(s)||"";this.toolInputBuffers.set(s,r+n.delta.partial_json)}}if(n.type==="content_block_stop"){const a=this.activeToolUseIds.get(t),s=this.recentToolNames.get(t);if(a&&s){const r=`${t}:${a}`,l=this.toolInputBuffers.get(r)||"";let d;if(l)try{d=JSON.parse(l)}catch{console.warn("[ClaudeSdkAdapter] Failed to parse tool input JSON:",l.slice(0,100))}const u={...f(s.name,d),actionId:a},m=this.extractMcpServerName(s.name);e.status="tool_using",this.emit("status-change",t,"tool_using",{actionType:u.actionType,actionLabel:u.actionLabel,actionDetail:u.actionDetail,actionId:u.actionId,usage:e.totalUsage,...m?{metadata:{mcpServer:m}}:{}}),this.stopIdleDetection(t),this.emitEvent(t,{type:"tool_use_start",sessionId:t,timestamp:o,data:{toolName:s.name,toolInput:d,toolUseId:a,actionType:u.actionType,actionLabel:u.actionLabel,actionDetail:u.actionDetail,actionId:u.actionId,...m?{metadata:{mcpServer:m}}:{}}}),e.messages.push({id:h(),sessionId:t,role:"tool_use",content:`${s.name}: ${l.slice(0,100)}`,timestamp:o,toolName:s.name,toolInput:d,toolUseId:a}),this.toolInputBuffers.delete(r),this.activeToolUseIds.delete(t)}}}}extractMcpServerName(t){if(t.startsWith("mcp__")){const e=t.split("__");if(e.length>=3)return e[1]}}extractToolNameSuffix(t){if(t.includes("__"))return t.split("__").pop()||t;if(t.includes("-mcp__")){const e=t.indexOf("-mcp__");return t.substring(e+6)}return t}emitEvent(t,e){this.emit("event",e)}cleanupSession(t){this.stopIdleDetection(t),this.sessions.delete(t),this.sdkQueries.delete(t),this.inputStreams.delete(t),this.abortControllers.delete(t),this.pendingPermissions.delete(t),this.pendingQuestions.delete(t),this.idleCommands.delete(t),this.idlePollLoops.delete(t),this.sessionAgentIds.delete(t),this.lastActivityAt.delete(t)}}export{$ as ClaudeSdkAdapter};
4
4
 
@@ -40,6 +40,8 @@ export declare class CodexSdkAdapter extends EventEmitter implements BaseProvide
40
40
  private emitEvent;
41
41
  private startIdleDetection;
42
42
  private stopIdleDetection;
43
+
44
+ private armIdleCheck;
43
45
  private checkIdleState;
44
46
  private sendIdlePrompt;
45
47
  private toIdlePrompt;