aws-runtime-bridge 1.9.172 → 1.9.179

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 (383) hide show
  1. package/CHANGELOG.md +314 -0
  2. package/README.md +61 -2
  3. package/dist/adapter/AcodeSdkAdapter.d.ts +374 -1
  4. package/dist/adapter/AcodeSdkAdapter.js +3 -3
  5. package/dist/adapter/AdapterRegistry.d.ts +28 -0
  6. package/dist/adapter/ClaudeSdkAdapter.d.ts +71 -0
  7. package/dist/adapter/CodexSdkAdapter.d.ts +14 -0
  8. package/dist/adapter/OpencodeSdkAdapter.d.ts +44 -0
  9. package/dist/adapter/acode-tool-names.d.ts +9 -0
  10. package/dist/adapter/idle-poll-loop.d.ts +20 -0
  11. package/dist/adapter/index.d.ts +3 -0
  12. package/dist/adapter/instance-ai-config-resolver.d.ts +20 -0
  13. package/dist/adapter/prompts.d.ts +12 -0
  14. package/dist/adapter/types.d.ts +184 -0
  15. package/dist/browser/browser-bootstrap.d.ts +15 -0
  16. package/dist/browser/browser-connect-token.d.ts +11 -0
  17. package/dist/browser/browser-frame-encode.d.ts +32 -0
  18. package/dist/browser/browser-pool.d.ts +129 -0
  19. package/dist/browser/browser-profile-store.d.ts +41 -0
  20. package/dist/browser/browser-ws-bridge.d.ts +20 -0
  21. package/dist/browser/built-in-browser-tools.d.ts +44 -0
  22. package/dist/browser/element-locator.d.ts +25 -0
  23. package/dist/browser/element-picker.d.ts +30 -0
  24. package/dist/browser/frame-encode.d.ts +19 -0
  25. package/dist/browser/input-dispatcher.d.ts +35 -0
  26. package/dist/browser/listener-store.d.ts +44 -0
  27. package/dist/browser/page-listener-manager.d.ts +88 -0
  28. package/dist/browser/page-listener-types.d.ts +38 -0
  29. package/dist/browser/screencast-differ.d.ts +10 -0
  30. package/dist/browser/screencast-manager.d.ts +94 -0
  31. package/dist/browser/snapshot-serializer.d.ts +56 -0
  32. package/dist/browser/ssrf-guard.d.ts +44 -0
  33. package/dist/browser/stealth.d.ts +21 -0
  34. package/dist/browser/step-archive.d.ts +13 -0
  35. package/dist/browser/types.d.ts +100 -0
  36. package/dist/browser/ws-server.d.ts +54 -0
  37. package/dist/config.d.ts +138 -2
  38. package/dist/config.js +2 -2
  39. package/dist/desktop/built-in-desktop-tools.d.ts +68 -0
  40. package/dist/desktop/built-in-desktop-tools.js +2 -1
  41. package/dist/desktop/desktop-control.d.ts +142 -0
  42. package/dist/desktop/desktop-control.js +2 -0
  43. package/dist/desktop/desktop-mcp-client.d.ts +28 -0
  44. package/dist/desktop/desktop-staleness.d.ts +66 -0
  45. package/dist/desktop/desktop-staleness.js +2 -0
  46. package/dist/index.d.ts +4 -0
  47. package/dist/index.js +1 -1
  48. package/dist/middleware/auth.d.ts +26 -0
  49. package/dist/middleware/auth.js +1 -1
  50. package/dist/remote-desktop/computer-control.d.ts +3 -0
  51. package/dist/remote-desktop/coords.d.ts +6 -0
  52. package/dist/remote-desktop/frame-backpressure.d.ts +10 -0
  53. package/dist/remote-desktop/frame-encode.d.ts +3 -0
  54. package/dist/remote-desktop/index.js +2 -2
  55. package/dist/remote-desktop/input-dispatcher.d.ts +4 -0
  56. package/dist/remote-desktop/permission-manager.d.ts +3 -0
  57. package/dist/remote-desktop/screen-capture.d.ts +91 -0
  58. package/dist/remote-desktop/session-manager.d.ts +47 -0
  59. package/dist/remote-desktop/session-manager.js +1 -1
  60. package/dist/remote-desktop/system-backend.d.ts +64 -0
  61. package/dist/remote-desktop/types.d.ts +25 -0
  62. package/dist/remote-desktop/ui-automation.d.ts +11 -0
  63. package/dist/remote-desktop/win32-api.d.ts +10 -0
  64. package/dist/routes/acode-todos.d.ts +13 -0
  65. package/dist/routes/agent-state.d.ts +15 -0
  66. package/dist/routes/ai-sources.js +1 -1
  67. package/dist/routes/background-tasks.d.ts +18 -0
  68. package/dist/routes/background-tasks.js +2 -2
  69. package/dist/routes/bridge-temp-files.d.ts +1 -0
  70. package/dist/routes/bridge-temp-files.js +2 -0
  71. package/dist/routes/browser-listeners.d.ts +17 -0
  72. package/dist/routes/browser-sessions.d.ts +10 -0
  73. package/dist/routes/capabilities.js +1 -1
  74. package/dist/routes/dashboard-icon.d.ts +9 -0
  75. package/dist/routes/dashboard-icon.js +2 -0
  76. package/dist/routes/dashboard-theme.d.ts +24 -0
  77. package/dist/routes/dashboard-theme.js +157 -0
  78. package/dist/routes/dashboard.d.ts +9 -0
  79. package/dist/routes/dashboard.js +2021 -628
  80. package/dist/routes/debug-mount.d.ts +16 -0
  81. package/dist/routes/desktop-control.d.ts +15 -0
  82. package/dist/routes/desktop-control.js +2 -0
  83. package/dist/routes/events.d.ts +4 -0
  84. package/dist/routes/file-browser.d.ts +15 -10
  85. package/dist/routes/file-browser.js +1 -1
  86. package/dist/routes/file-change-diff.d.ts +25 -0
  87. package/dist/routes/file-diff-rollback.d.ts +28 -0
  88. package/dist/routes/file-snapshot.d.ts +7 -0
  89. package/dist/routes/git.d.ts +185 -0
  90. package/dist/routes/git.js +34 -34
  91. package/dist/routes/instance-tool-status.d.ts +5 -0
  92. package/dist/routes/instance.d.ts +8 -0
  93. package/dist/routes/instance.js +1 -1
  94. package/dist/routes/jdks.d.ts +4 -0
  95. package/dist/routes/launch.d.ts +5 -0
  96. package/dist/routes/lsp-providers.d.ts +11 -0
  97. package/dist/routes/lsp-providers.js +2 -0
  98. package/dist/routes/lsp.d.ts +41 -0
  99. package/dist/routes/lsp.js +4 -2
  100. package/dist/routes/mcp-extra.d.ts +15 -0
  101. package/dist/routes/mcp.d.ts +16 -0
  102. package/dist/routes/mcp.js +1 -1
  103. package/dist/routes/plugins.d.ts +19 -0
  104. package/dist/routes/plugins.js +1 -1
  105. package/dist/routes/processes.d.ts +4 -0
  106. package/dist/routes/properties.d.ts +4 -0
  107. package/dist/routes/pty.d.ts +29 -0
  108. package/dist/routes/runtime-binding.d.ts +3 -0
  109. package/dist/routes/sessions.d.ts +22 -0
  110. package/dist/routes/sessions.js +1 -1
  111. package/dist/routes/skills.d.ts +15 -0
  112. package/dist/routes/skills.js +1 -1
  113. package/dist/routes/sub-agents.d.ts +11 -0
  114. package/dist/routes/sub-agents.js +1 -1
  115. package/dist/routes/task-context.d.ts +5 -0
  116. package/dist/routes/tech-stack.d.ts +6 -0
  117. package/dist/routes/tech-stack.js +2 -0
  118. package/dist/routes/terminal.d.ts +122 -0
  119. package/dist/routes/terminal.js +22 -22
  120. package/dist/routes/workspace-index.d.ts +12 -0
  121. package/dist/routes/workspace-index.js +2 -0
  122. package/dist/routes/yml.d.ts +4 -0
  123. package/dist/scripts/migrate-user-scopes.d.ts +26 -0
  124. package/dist/scripts/migrate-user-scopes.js +2 -0
  125. package/dist/services/access-control.d.ts +21 -0
  126. package/dist/services/acode-bg-manager.d.ts +21 -0
  127. package/dist/services/acode-package.d.ts +10 -0
  128. package/dist/services/acode-package.js +1 -1
  129. package/dist/services/agent-capability-sync.d.ts +26 -0
  130. package/dist/services/agent-capability-sync.js +1 -1
  131. package/dist/services/agent-event-store.d.ts +20 -0
  132. package/dist/services/agent-ownership.d.ts +58 -0
  133. package/dist/services/agent-ownership.js +3 -0
  134. package/dist/services/agent-process-manager.d.ts +154 -0
  135. package/dist/services/agent-pty-manager.d.ts +39 -0
  136. package/dist/services/agent-pty-manager.js +5 -4
  137. package/dist/services/agent-startup-memory.d.ts +34 -0
  138. package/dist/services/agent-startup-memory.js +4 -4
  139. package/dist/services/ai-config-service.d.ts +26 -52
  140. package/dist/services/ai-config-service.js +1 -3
  141. package/dist/services/ai-source-apply.d.ts +7 -15
  142. package/dist/services/ai-source-apply.js +1 -1
  143. package/dist/services/auto-register.d.ts +165 -1
  144. package/dist/services/auto-register.js +1 -1
  145. package/dist/services/aws-client-agent-mcp.d.ts +14 -0
  146. package/dist/services/aws-client-agent-mcp.js +2 -2
  147. package/dist/services/bridge-package-publish-hooks.d.ts +14 -0
  148. package/dist/services/bridge-pairing.d.ts +82 -0
  149. package/dist/services/bridge-pairing.js +2 -0
  150. package/dist/services/bridge-temp-files.d.ts +65 -0
  151. package/dist/services/bridge-temp-files.js +2 -0
  152. package/dist/services/browser-session-manager.d.ts +71 -0
  153. package/dist/services/capability-config.d.ts +60 -15
  154. package/dist/services/capability-config.js +2 -2
  155. package/dist/services/change-cache-retention.d.ts +9 -0
  156. package/dist/services/changelog.d.ts +9 -0
  157. package/dist/services/cli-commands.d.ts +82 -0
  158. package/dist/services/cli-commands.js +6 -6
  159. package/dist/services/connection-key-rotation.d.ts +27 -0
  160. package/dist/services/connection-key-rotation.js +2 -0
  161. package/dist/services/debug-mount.d.ts +49 -0
  162. package/dist/services/desktop-mcp-manager.d.ts +103 -1
  163. package/dist/services/desktop-mcp-manager.js +1 -1
  164. package/dist/services/event-delta-pusher.d.ts +15 -0
  165. package/dist/services/fileSnapshotStore.d.ts +42 -0
  166. package/dist/services/fileSnapshotStore.js +1 -1
  167. package/dist/services/gitignore.d.ts +21 -0
  168. package/dist/services/gitignore.js +2 -0
  169. package/dist/services/instance-ai-config-service.d.ts +9 -0
  170. package/dist/services/instance-ai-config-service.js +1 -1
  171. package/dist/services/instance-features.d.ts +127 -0
  172. package/dist/services/instance-features.js +1 -1
  173. package/dist/services/instance-init-service.d.ts +3 -0
  174. package/dist/services/instance-init-service.js +1 -1
  175. package/dist/services/instance-state.d.ts +23 -0
  176. package/dist/services/jdk-scanner.d.ts +15 -0
  177. package/dist/services/launch-manager.d.ts +138 -0
  178. package/dist/services/launch-metrics.d.ts +42 -0
  179. package/dist/services/launch-streams.d.ts +19 -0
  180. package/dist/services/lifecycle-state.d.ts +5 -0
  181. package/dist/services/log-retention.d.ts +38 -0
  182. package/dist/services/log-retention.js +1 -1
  183. package/dist/services/lsp/install-manager.d.ts +55 -0
  184. package/dist/services/lsp/install-manager.js +2 -0
  185. package/dist/services/lsp/provider-registry.d.ts +108 -0
  186. package/dist/services/lsp/provider-registry.js +2 -0
  187. package/dist/services/lsp/uri-rewrite.d.ts +44 -0
  188. package/dist/services/lsp/uri-rewrite.js +2 -0
  189. package/dist/services/lsp-stdio-bridge.d.ts +41 -4
  190. package/dist/services/lsp-stdio-bridge.js +3 -3
  191. package/dist/services/mcp-deploy.d.ts +45 -4
  192. package/dist/services/mcp-deploy.js +4 -4
  193. package/dist/services/mcp-env-injector.d.ts +52 -0
  194. package/dist/services/mcp-launch-binding-queue.d.ts +12 -0
  195. package/dist/services/mcp-package.d.ts +22 -0
  196. package/dist/services/mcp-package.js +1 -1
  197. package/dist/services/mcp-probe-client.d.ts +19 -0
  198. package/dist/services/mcp-probe-client.js +1 -1
  199. package/dist/services/open-doc-events.d.ts +43 -0
  200. package/dist/services/open-doc-events.js +2 -0
  201. package/dist/services/open-doc-registry.d.ts +59 -0
  202. package/dist/services/open-doc-registry.js +2 -0
  203. package/dist/services/orphan-monitor.d.ts +43 -0
  204. package/dist/services/panel-auth.d.ts +24 -0
  205. package/dist/services/panel-env.d.ts +28 -0
  206. package/dist/services/plugin-deployment.d.ts +34 -1
  207. package/dist/services/plugin-deployment.js +2 -2
  208. package/dist/services/plugin-event-buffer.d.ts +21 -0
  209. package/dist/services/plugin-fs.d.ts +11 -0
  210. package/dist/services/plugin-handler-adapter.d.ts +13 -0
  211. package/dist/services/plugin-listener-runner.d.ts +10 -0
  212. package/dist/services/plugin-loader.d.ts +15 -0
  213. package/dist/services/plugin-manager.d.ts +95 -9
  214. package/dist/services/plugin-manager.js +4 -4
  215. package/dist/services/plugin-manifest.d.ts +14 -0
  216. package/dist/services/plugin-package.d.ts +13 -0
  217. package/dist/services/plugin-runtime.d.ts +15 -0
  218. package/dist/services/port-detector.d.ts +15 -0
  219. package/dist/services/process-detail.d.ts +3 -0
  220. package/dist/services/process-detector.d.ts +132 -0
  221. package/dist/services/process-registry.d.ts +120 -0
  222. package/dist/services/process-top.d.ts +6 -0
  223. package/dist/services/request-identity.d.ts +77 -0
  224. package/dist/services/request-identity.js +2 -0
  225. package/dist/services/request-invalid-dump.d.ts +4 -0
  226. package/dist/services/request-invalid-dump.js +1 -1
  227. package/dist/services/ring-buffer.d.ts +33 -0
  228. package/dist/services/runtime-binding.d.ts +56 -4
  229. package/dist/services/runtime-binding.js +4 -4
  230. package/dist/services/runtime-lifecycle-policy.d.ts +17 -0
  231. package/dist/services/runtime-resources-snapshot.d.ts +26 -0
  232. package/dist/services/runtime-resources-snapshot.js +2 -2
  233. package/dist/services/sdk-tool-file-change-recorder.d.ts +9 -0
  234. package/dist/services/session-output.d.ts +63 -0
  235. package/dist/services/session-output.js +3 -3
  236. package/dist/services/skill-manager.d.ts +42 -5
  237. package/dist/services/skill-manager.js +3 -3
  238. package/dist/services/snapshot-retention.d.ts +30 -0
  239. package/dist/services/snapshot-retention.js +2 -0
  240. package/dist/services/startup-config-wizard.d.ts +7 -1
  241. package/dist/services/startup-config-wizard.js +10 -10
  242. package/dist/services/system-metrics.d.ts +3 -0
  243. package/dist/services/tech-stack-scanner.d.ts +43 -0
  244. package/dist/services/tech-stack-scanner.js +2 -0
  245. package/dist/services/terminal-persistence.d.ts +43 -0
  246. package/dist/services/tool-installer.d.ts +12 -0
  247. package/dist/services/tunnel-client.d.ts +99 -2
  248. package/dist/services/tunnel-client.js +1 -1
  249. package/dist/services/update-log.d.ts +6 -0
  250. package/dist/services/update-notifier.d.ts +17 -0
  251. package/dist/services/update-notifier.js +2 -2
  252. package/dist/services/user-scope.d.ts +115 -0
  253. package/dist/services/user-scope.js +2 -0
  254. package/dist/services/windows-service-manager.d.ts +12 -0
  255. package/dist/services/workspace-files.d.ts +64 -0
  256. package/dist/services/workspace-index/index-manager.d.ts +46 -0
  257. package/dist/services/workspace-index/index-manager.js +2 -0
  258. package/dist/services/workspace-index/indexer.d.ts +15 -0
  259. package/dist/services/workspace-index/indexer.js +2 -0
  260. package/dist/services/workspace-index/query.d.ts +74 -0
  261. package/dist/services/workspace-index/query.js +5 -0
  262. package/dist/services/workspace-index/resolver.d.ts +26 -0
  263. package/dist/services/workspace-index/resolver.js +2 -0
  264. package/dist/services/workspace-index/types.d.ts +89 -0
  265. package/dist/services/workspace-index/types.js +2 -0
  266. package/dist/services/workspace-watch.d.ts +4 -0
  267. package/dist/services/workspaceTaskChangeWatcher.d.ts +49 -0
  268. package/dist/services/workspaceTaskChangeWatcher.js +2 -2
  269. package/dist/types.d.ts +9 -0
  270. package/dist/utils/config-write-queue.d.ts +11 -0
  271. package/dist/utils/env-safety.d.ts +21 -0
  272. package/dist/utils/file-utils.d.ts +15 -0
  273. package/dist/utils/instance-ai-config-debug-logger.d.ts +15 -0
  274. package/dist/utils/lifecycle-log.d.ts +5 -0
  275. package/dist/utils/logger.d.ts +13 -0
  276. package/dist/utils/logger.js +2 -1
  277. package/dist/utils/npm-version.d.ts +10 -0
  278. package/dist/utils/path-utils.d.ts +12 -0
  279. package/dist/utils/scheduler-url.d.ts +18 -0
  280. package/dist/utils/scheduler-url.js +2 -0
  281. package/dist/utils/sdk-package-loader.d.ts +13 -0
  282. package/dist/utils/sdk-package-loader.js +1 -1
  283. package/dist/utils/target-identity.d.ts +31 -0
  284. package/dist/utils/target-identity.js +2 -0
  285. package/dist/utils/validation.d.ts +17 -0
  286. package/dist/utils/yaml-utils.d.ts +48 -0
  287. package/package/acode/dist/__tests__/summary-request-helper.d.ts +12 -0
  288. package/package/acode/dist/__tests__/summary-request-helper.js +2 -0
  289. package/package/acode/dist/ask-user-question-tool.d.ts +17 -0
  290. package/package/acode/dist/await-complete-tool.d.ts +12 -0
  291. package/package/acode/dist/background-command-manager.d.ts +105 -0
  292. package/package/acode/dist/background-command-store.d.ts +27 -0
  293. package/package/acode/dist/background-command-tools.d.ts +8 -0
  294. package/package/acode/dist/background-output-ringbuffer.d.ts +15 -0
  295. package/package/acode/dist/built-in-file-tools.d.ts +65 -0
  296. package/package/acode/dist/built-in-symbols-tool.d.ts +3 -0
  297. package/package/acode/dist/builtins/commandArtifacts.d.ts +3 -0
  298. package/package/acode/dist/builtins/shellCommandPreparation.d.ts +17 -0
  299. package/package/acode/dist/builtins/shellCommandRunner.d.ts +4 -0
  300. package/package/acode/dist/builtins/shellOutputDecoder.d.ts +15 -0
  301. package/package/acode/dist/cache-control.d.ts +71 -0
  302. package/package/acode/dist/cache-control.js +2 -0
  303. package/package/acode/dist/commands/commandLoader.d.ts +3 -0
  304. package/package/acode/dist/commands/commandParser.d.ts +3 -0
  305. package/package/acode/dist/commands/commandRegistry.d.ts +3 -0
  306. package/package/acode/dist/compaction.d.ts +388 -4
  307. package/package/acode/dist/compaction.js +19 -17
  308. package/package/acode/dist/config.d.ts +3 -0
  309. package/package/acode/dist/context-overflow.d.ts +32 -0
  310. package/package/acode/dist/fs-utils.d.ts +18 -0
  311. package/package/acode/dist/hooks/hookBus.d.ts +3 -0
  312. package/package/acode/dist/image-utils.d.ts +35 -0
  313. package/package/acode/dist/index.d.ts +1 -0
  314. package/package/acode/dist/index.js +1 -1
  315. package/package/acode/dist/mcpToolNames.d.ts +32 -0
  316. package/package/acode/dist/microcompact.d.ts +110 -0
  317. package/package/acode/dist/microcompact.js +2 -0
  318. package/package/acode/dist/parsers/ast-cache.d.ts +41 -0
  319. package/package/acode/dist/parsers/file-index.d.ts +83 -0
  320. package/package/acode/dist/parsers/file-index.js +4 -0
  321. package/package/acode/dist/parsers/language-detector.d.ts +4 -0
  322. package/package/acode/dist/parsers/tree-sitter-loader.d.ts +12 -0
  323. package/package/acode/dist/parsers/types.d.ts +11 -0
  324. package/package/acode/dist/paths.d.ts +14 -0
  325. package/package/acode/dist/plugin-types.d.ts +34 -0
  326. package/package/acode/dist/read-file-state.d.ts +15 -0
  327. package/package/acode/dist/runtime-environment.d.ts +16 -0
  328. package/package/acode/dist/runtime.d.ts +828 -9
  329. package/package/acode/dist/runtime.js +40 -33
  330. package/package/acode/dist/skill-tool.d.ts +20 -0
  331. package/package/acode/dist/sub-agent-manager.d.ts +169 -0
  332. package/package/acode/dist/sub-agent-manager.js +1 -1
  333. package/package/acode/dist/sub-agent-store.d.ts +50 -0
  334. package/package/acode/dist/sub-agent-tools.d.ts +15 -0
  335. package/package/acode/dist/sub-agent-types.d.ts +13 -0
  336. package/package/acode/dist/terminal-tool.d.ts +15 -0
  337. package/package/acode/dist/terminal-types.d.ts +10 -0
  338. package/package/acode/dist/todo-store.d.ts +15 -0
  339. package/package/acode/dist/token-estimator.d.ts +32 -0
  340. package/package/acode/dist/token-estimator.js +2 -0
  341. package/package/acode/dist/tool-allocation.d.ts +113 -0
  342. package/package/acode/dist/tool-concurrency/index.d.ts +8 -0
  343. package/package/acode/dist/tool-concurrency/observability.d.ts +32 -0
  344. package/package/acode/dist/tool-concurrency/resource-lock.d.ts +30 -0
  345. package/package/acode/dist/tool-concurrency/scheduler.d.ts +19 -0
  346. package/package/acode/dist/tool-concurrency/types.d.ts +57 -0
  347. package/package/acode/dist/tool-group-manager.d.ts +195 -0
  348. package/package/acode/dist/tool-group-manager.js +4 -4
  349. package/package/acode/dist/types.d.ts +192 -0
  350. package/package/aws-client-agent-mcp/README.md +130 -215
  351. package/package/aws-client-agent-mcp/dist/ability-market-tools.d.ts +57 -0
  352. package/package/aws-client-agent-mcp/dist/ability-market-tools.js +1 -1
  353. package/package/aws-client-agent-mcp/dist/agent-client.d.ts +290 -3
  354. package/package/aws-client-agent-mcp/dist/agent-client.js +1 -1
  355. package/package/aws-client-agent-mcp/dist/config.d.ts +18 -0
  356. package/package/aws-client-agent-mcp/dist/constants.d.ts +2 -0
  357. package/package/aws-client-agent-mcp/dist/context-manager.d.ts +70 -0
  358. package/package/aws-client-agent-mcp/dist/http-client.d.ts +61 -0
  359. package/package/aws-client-agent-mcp/dist/index.d.ts +10 -0
  360. package/package/aws-client-agent-mcp/dist/logger.d.ts +24 -0
  361. package/package/aws-client-agent-mcp/dist/mcp-server.d.ts +610 -0
  362. package/package/aws-client-agent-mcp/dist/mcp-server.js +25 -23
  363. package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts +158 -0
  364. package/package/aws-client-agent-mcp/dist/mcp-tools.js +38 -22
  365. package/package/aws-client-agent-mcp/dist/memory-store.d.ts +102 -2
  366. package/package/aws-client-agent-mcp/dist/memory-store.js +27 -2
  367. package/package/aws-client-agent-mcp/dist/memory-tools.d.ts +18 -0
  368. package/package/aws-client-agent-mcp/dist/memory-tools.js +13 -9
  369. package/package/aws-client-agent-mcp/dist/message-buffer.d.ts +86 -0
  370. package/package/aws-client-agent-mcp/dist/messageContent.d.ts +24 -0
  371. package/package/aws-client-agent-mcp/dist/office/office-equation.d.ts +19 -0
  372. package/package/aws-client-agent-mcp/dist/office/office-image.d.ts +18 -0
  373. package/package/aws-client-agent-mcp/dist/office/office-workspace.d.ts +29 -0
  374. package/package/aws-client-agent-mcp/dist/parent-lifecycle.d.ts +18 -0
  375. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.d.ts +6 -0
  376. package/package/aws-client-agent-mcp/dist/server-memory-store.d.ts +5 -1
  377. package/package/aws-client-agent-mcp/dist/server-memory-store.js +1 -1
  378. package/package/aws-client-agent-mcp/dist/status-reporter.d.ts +41 -0
  379. package/package/aws-client-agent-mcp/dist/tool-groups.d.ts +136 -0
  380. package/package/aws-client-agent-mcp/dist/types.d.ts +174 -0
  381. package/package/aws-client-agent-mcp/dist/watchdog.d.ts +7 -0
  382. package/package/aws-client-agent-mcp/dist/websocket-client.d.ts +108 -0
  383. package/package.json +1 -1
@@ -1,46 +1,52 @@
1
- import{EventEmitter as kt}from"node:events";import{randomUUID as St}from"node:crypto";import D from"node:fs";import Oe from"node:os";import z from"node:path";import{Client as Mt}from"@modelcontextprotocol/sdk/client/index.js";import{SSEClientTransport as vt}from"@modelcontextprotocol/sdk/client/sse.js";import{StdioClientTransport as $t}from"@modelcontextprotocol/sdk/client/stdio.js";import{StreamableHTTPClientTransport as Et}from"@modelcontextprotocol/sdk/client/streamableHttp.js";import{ToolListChangedNotificationSchema as xt}from"@modelcontextprotocol/sdk/types.js";import{createBuiltInFileTools as Rt,DEFAULT_TOOL_PERMISSION_POLICY as Le,getEditFailureSnapshot as It}from"./built-in-file-tools.js";import{ReadFileStateTracker as Nt}from"./read-file-state.js";import{ASK_USER_QUESTION_TOOL_NAME as Pt,createAskUserQuestionTool as Ot}from"./ask-user-question-tool.js";import{createSkillTool as Lt}from"./skill-tool.js";import{createTodoWriteTool as Dt,createTodoReadTool as Bt}from"./todo-tool.js";import{createSubAgentTools as Ut}from"./sub-agent-tools.js";import{createAwaitCompleteTool as qt}from"./await-complete-tool.js";import{cleanupAcodeCmdDist as Ft}from"./builtins/commandArtifacts.js";import{buildRuntimeEnvironmentPrompt as zt}from"./runtime-environment.js";const De="[Runtime Instructions]";import{resolveAcodeHome as jt}from"./paths.js";import{backgroundCommandManager as le}from"./background-command-manager.js";import{createTerminalTool as Wt}from"./terminal-tool.js";import{ToolGroupManager as Gt,createExpandToolsTool as Jt,createCallToolTool as Kt,mcpGroupKeyOf as Be,isPluginGroupKey as Ue,pluginGroupKeyOf as Ht}from"./tool-group-manager.js";import{loadAcodeCommands as Qt}from"./commands/commandLoader.js";import{ACodeCommandRegistry as qe}from"./commands/commandRegistry.js";import{calculateCompactionThreshold as Yt,calculateCompactionBudget as Vt,COMPACTION_LLM_PROMPT_TEMPLATE as Xt,conversationSizeBytes as Fe,conversationSizeKB as Y,estimateConversationTokens as j,isCompactionSummaryMessage as Zt,isRuntimeResourcesMessage as eo,isRuntimeInstructionsMessage as to,performCompaction as pe,resolveReplayWindow as oo,pruneToolOutputs as so,RUNTIME_RESOURCES_PREFIX as no,summarizeConversation as ze,SummaryUnavailableError as io}from"./compaction.js";import{isContextOverflowError as we,resolveFinishReasonOverflow as ro}from"./context-overflow.js";import{loadAcodeConfig as ao,loadAcodeSkillGroup as lo}from"./config.js";import{ACodeHookBus as co,findDeniedHookResult as je}from"./hooks/hookBus.js";import{isMcpPollingToolName as We,isMcpBlockingToolName as ke,isMcpBatchExcludedToolName as Se,isMcpIndefinitelyBlockingToolName as uo,getSemanticToolName as Me}from"./mcpToolNames.js";import{runtimeMeetingDebugLog as B}from"./meeting-debug-log.js";import{BackgroundOutputRingBuffer as mo}from"./background-output-ringbuffer.js";import{buildToolCatalog as Ge,matchesToolAllocation as Je,mergeAllocatableTools as he,PRESET_EXPLORE as po,rebindDefaultAgentId as Ke,resolveToolAllocation as ho,SUB_AGENT_ALLOWED_MCP_TOOLS as fo}from"./tool-allocation.js";import{ConcurrencyLimiter as He,getSharedResourceLock as go,ToolConcurrencyScheduler as yo,ToolTraceRecorder as Qe}from"./tool-concurrency/index.js";function To(n){if(typeof n!="object"||n===null)return!1;const e=n;return e.kind==="builtin"&&typeof e.toolName=="string"&&typeof e.exposedName=="string"&&typeof e.description=="string"&&typeof e.execute=="function"&&typeof e.inputSchema=="object"&&e.inputSchema!==null}function Co(n){return n.type==="text"?{type:"text",text:n.text}:{type:"image_url",image_url:{url:n.image_url.url}}}function _o(n){return{id:n.id,type:"function",function:{name:n.function.name,arguments:n.function.arguments}}}function Ao(n){const e={role:n.role,content:Array.isArray(n.content)?n.content.map(Co):n.content};return n.tool_call_id&&(e.tool_call_id=n.tool_call_id),n.tool_calls&&(e.tool_calls=n.tool_calls.map(_o)),n.reasoning&&(e.reasoning=n.reasoning),e}function ce(n){return n.map(Ao)}function bo(n){return n.map(e=>{const{reasoning:t,...o}=e;return o})}function wo(n,e){const t=W(n.prompt_cache_hit_tokens),o=W(n.prompt_cache_miss_tokens);if(t!==void 0||o!==void 0)return{cacheHitTokens:t??0,cacheMissTokens:o??0};const s=W(n.cache_read_input_tokens),i=W(n.cache_creation_input_tokens);if(s!==void 0||i!==void 0){const u=s??0,c=i??0,d=W(n.input_tokens)??(e!==void 0?Math.max(0,e-u-c):0);return{cacheHitTokens:u,cacheMissTokens:c+d}}const r=W(n.cache_hit_tokens),a=W(n.cache_miss_tokens);if(r!==void 0||a!==void 0)return{cacheHitTokens:r??0,cacheMissTokens:a??0};const l=W(n.prompt_tokens_details?.cached_tokens);if(l!==void 0){const u=e!==void 0?Math.max(0,e-l):0;return{cacheHitTokens:l,cacheMissTokens:u}}}function W(n){const e=typeof n=="number"?n:typeof n=="string"&&n.trim()?Number(n):NaN;if(!(!Number.isFinite(e)||e<0))return e}function ko(n,e){if(!n)return e;const t=o=>{const s=e[o],i=n[o];return o==="prompt_tokens_details"?{...i,...s}:s??i};return{prompt_tokens:t("prompt_tokens"),completion_tokens:t("completion_tokens"),input_tokens:t("input_tokens"),output_tokens:t("output_tokens"),prompt_cache_hit_tokens:t("prompt_cache_hit_tokens"),prompt_cache_miss_tokens:t("prompt_cache_miss_tokens"),cache_read_input_tokens:t("cache_read_input_tokens"),cache_creation_input_tokens:t("cache_creation_input_tokens"),cache_hit_tokens:t("cache_hit_tokens"),cache_miss_tokens:t("cache_miss_tokens"),prompt_tokens_details:t("prompt_tokens_details")}}function So(){return new Date().toISOString()}function S(n){return!!(n&&typeof n=="object"&&!Array.isArray(n))}function fe(n){return S(n)}function Ye(n,e){return e.map(t=>({serverName:n,toolName:t.name,kind:"mcp",exposedName:bs(n,t.name),description:t.description,inputSchema:fe(t.inputSchema)?t.inputSchema:{type:"object",properties:{}}}))}const ge="ACODE_TOOL_GROUPS_V1:";function Mo(n){const e=String(n??"").trim();if(!e.startsWith(ge))return[];const t=e.slice(ge.length).trim();if(!t)return[];let o;try{o=JSON.parse(t)}catch{return[]}if(!fe(o)||!Array.isArray(o.groups))return[];const s=[];for(const i of o.groups){if(!fe(i))continue;const r=typeof i.key=="string"?i.key.trim():"";if(!r)continue;const a=Array.isArray(i.toolNames)?i.toolNames.filter(l=>typeof l=="string"&&l.length>0):[];s.push({key:r,label:typeof i.label=="string"&&i.label.trim()?i.label:r,toolNames:a})}return s}function vo(n){const e=String(n??"").trim();if(!e)return;if(!e.startsWith(ge))return e;const t=e.slice(ge.length).trim();return t.startsWith("{")?void 0:t||void 0}function I(n){return String(n??"").trim()||void 0}const Ve=6e4,Xe=30*6e4,Ze=6e4,et=6e4,ve=-1,tt=0,$o=1e3,Eo=3e4,ye=6e4,ot=0,xo=2147483647,Ro=8,Io=10*6e4+2e3,No=1e4,Te=5e3,st=10*60*1e3,te=10*1024*1024,nt=800*1024,it=32*1024*1024,Po=4,Oo=1.25;function rt(){const n=Number.parseInt(String(process.env.ACODE_MAX_REQUEST_BODY_BYTES??"").trim(),10);return Number.isFinite(n)&&n>0?n:void 0}function Lo(){return rt()!==void 0}function Do(n){const e=rt();if(e!==void 0)return e;if(!Number.isFinite(n)||n<=0)return nt;const t=Math.floor(n*Po*Oo);return Math.min(it,Math.max(nt,t))}const Ce=process.env.ACODE_COMPACTION_DEBUG==="1",at=Ce?z.join(Oe.tmpdir(),"acode-compaction-debug.log"):"";function f(...n){Ce&&console.log(...n)}const Bo=process.env.ACODE_IMAGE_DIAG==="1",Uo=process.env.ACODE_IMAGE_DIAG_LOG||z.join(Oe.tmpdir(),"acode-image-inject.log");function _e(n){if(!Bo)return;const e=`[${new Date().toISOString()}] ${JSON.stringify(n)}
2
- `;D.promises.appendFile(Uo,e).catch(()=>{})}const qo=process.env.ACODE_TOKEN_DEBUG==="1";function oe(...n){qo&&console.log("[TokenDebug][Runtime]",...n)}const Fo=64e3,$e=8e3;function Ae(n){const e=n.contextLimit&&n.contextLimit>0?n.contextLimit:Fo,t=n.maxOutput&&n.maxOutput>0?n.maxOutput:8192,o=n.inputLimit&&n.inputLimit>0?n.inputLimit:void 0,s=Yt(e,t,o);return{contextLimit:e,maxOutput:t,inputLimit:o,threshold:s}}async function $(n,e,t,o){if(e<=0)return await n;let s;try{return await new Promise((i,r)=>{s=setTimeout(()=>{o?.(),r(new Error(`${t} timed out after ${e}ms`))},e),n.then(i,r)})}finally{s&&clearTimeout(s)}}function lt(){return`toolbatch-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`}async function se(n,e,t,o=No){try{await $(e,o,n)}catch(s){t(s instanceof Error?s.message:String(s))}}function ne(n,e){if(n===0||n==="0")return 0;const t=typeof n=="number"?n:Number(n);return t===ve?ve:Number.isFinite(t)&&t>0?Math.floor(t):e}function ue(n,e){const t=ne(n,e);return t>0?t:e}const ct=3;function Ee(n){return n?Math.ceil(n.length/ct):0}function zo(n,e){let t=n.length;for(const o of e){const s=(o.kind==="mcp",o.toolName);if(t+=s.length,o.kind==="mcp")o.description&&(t+=o.description.length),t+=JSON.stringify(o.inputSchema).length;else{const i=o;i.inputSchema&&(t+=JSON.stringify(i.inputSchema).length)}}return Math.ceil(t/ct)}function ie(n){if(n.length===0)return 0;const e=JSON.stringify(_t(n));return Ee(e)}async function jo(n){await new Promise(e=>setTimeout(e,n))}function Wo(n){return typeof n=="boolean"}function Go(n,e,t){if(Wo(t?.supportsImageInput))return t.supportsImageInput;const o=S(e)?e.models:void 0,s=S(o)?o[n]:void 0;if(!S(s))return!1;const i=s.modalities;return!S(i)||!Array.isArray(i.input)?!1:i.input.some(r=>String(r||"").trim().toLowerCase()==="image")}function xe(n,e,t,o){if(n!==void 0)return n;if(!e)return;const s=e.models;if(S(s)){const i=s[t];if(S(i)){const r=i[o];if(r!==void 0)return r}}return e[o]}function Jo(n,e){const t=e.provider?.default,o=t?.options,s=n.model||t?.model||e.model||"acode-default",i=I(n.effort)||I(o?.effort)||I(t?.effort)||void 0;return{model:s,baseURL:I(o?.baseURL||o?.baseUrl),apiKey:I(o?.apiKey),effort:i,systemPrompt:n.systemPrompt||e.systemPrompt,stream:o?.stream!==!1,requestTimeoutMs:ue(o?.requestTimeoutMs??o?.timeoutMs,Ve),requestTotalTimeoutMs:ue(o?.requestTotalTimeoutMs,Xe),requestRetryCount:ne(o?.requestRetryCount,tt),requestFirstByteTimeoutMs:ue(o?.requestFirstByteTimeoutMs,Ze),requestStreamIdleTimeoutMs:ue(o?.requestStreamIdleTimeoutMs,et),mcpToolTimeoutMs:ue(o?.mcpToolTimeoutMs,ye),mcpPollingToolTimeoutMs:ne(o?.mcpPollingToolTimeoutMs,ot),supportsImageInput:Go(s,t,o),contextLimit:ne(xe(o?.contextLimit,t,s,"contextLimit"),0)||void 0,inputLimit:ne(xe(o?.inputLimit,t,s,"inputLimit"),0)||void 0,maxOutput:ne(xe(o?.maxOutput,t,s,"maxOutput"),0)||void 0}}function H(n,e){const t=e.replace(/\s+/g," ").trim();t&&n.push({type:"text",text:t})}function Ko(n,e){const t=e.trim();return/^data:image\/[a-z0-9.+-]+;base64,/i.test(t)?t:`data:${n||"image/png"};base64,${t}`}function Ho(n){return/^data:image\/[a-z0-9.+-]+;base64,/i.test(n.trim())}function Qo(n){let e;try{e=new URL(n)}catch{throw new Error(`ACode image URL is invalid: ${n}`)}if(e.protocol!=="http:"&&e.protocol!=="https:")throw new Error(`ACode image URL protocol is not supported: ${e.protocol}`)}async function Yo(n){const e=await n.arrayBuffer();if(e.byteLength>te)throw new Error(`ACode image is too large to inline: ${e.byteLength} bytes exceeds ${te} bytes`);return Buffer.from(e).toString("base64")}async function Vo(n){const e=n.trim();if(Ho(e)){if(e.slice(e.indexOf(",")+1).length*.75>te)throw new Error(`ACode inline image exceeds the ${te} byte size limit`);return e}Qo(e);const t=await fetch(e);if(!t.ok)throw new Error(`ACode image fetch failed: ${t.status} ${await t.text()}`);const o=t.headers.get("content-type")||"",s=o.split(";")[0]?.trim().toLowerCase()||"";if(!s.startsWith("image/"))throw new Error(`ACode image URL did not return an image content type: ${o||"unknown"}`);return`data:${s};base64,${await Yo(t)}`}function Xo(n){const e=I(n.base64Data??n.base64??n.data);return e?e.length*.75>te?void 0:Ko(I(n.mediaType??n.mimeType)||"image/png",e):I(n.url??n.serverUrl)}function ut(n,e,t,o){return`[Attached file: ${[n?`name=${n}`:void 0,e?`url=${e}`:void 0,t?`mediaType=${t}`:void 0,o?`size=${o}`:void 0].filter(i=>!!i).join(", ")}]`}function Zo(n){const e=/\[(图片|文件)\s*:\s*([^\]\n]*?)\s*\]/gi,t=[];let o=!1,s=0,i=e.exec(n);for(;i!==null;){H(t,n.slice(s,i.index));const r=i[1],a=(i[2]||"").trim();if(r==="\u56FE\u7247"&&a)t.push({type:"image_url",image_url:{url:a}}),o=!0;else if(r==="\u6587\u4EF6"&&a){const[l="",u="",c="",d=""]=a.split("|").map(p=>p.trim());H(t,ut(l,u,c,d))}else H(t,i[0]);s=i.index+i[0].length,i=e.exec(n)}return t.length===0?{content:n,hasImages:!1}:(H(t,n.slice(s)),{content:t,hasImages:o})}function es(n,e){let t=!1;const o=[e.directMessages,e.groupMessages];for(const s of o)if(Array.isArray(s))for(const i of s){if(!S(i))continue;const r=I(i.content);if(!r)continue;const a=I(i.senderName);H(n,a?`Message from ${a}:`:"Message:");const l=Re(r);Array.isArray(l.content)?n.push(...l.content):H(n,l.content),t=t||l.hasImages}return t}function ts(n){for(const e of["directMessages","groupMessages","messages"]){const t=n[e];if(Array.isArray(t))for(const o of t){if(!S(o))continue;const s=o.content;typeof s!="string"||!s.trim()||(o.content=os(s))}}}function os(n){let e;try{e=JSON.parse(n)}catch{return n.replace(/\[(图片|文件)\s*:\s*([^\]\n]*?)\s*\]/gi,"").trim()||n}if(S(e)&&"attachments"in e){const t={...e};return t.attachments=[],JSON.stringify(t)}return n}function ss(n){let e;try{e=JSON.parse(n)}catch{return}if(!S(e))return;const t=[];let o=es(t,e);const s=I(e.text)||"",i=Array.isArray(e.attachments)?e.attachments:[];H(t,s);for(const r of i){if(!S(r))continue;const a=r;if(String(a.type??a.kind??"").toLowerCase()==="image"){const c=Xo(a);c?(t.push({type:"image_url",image_url:{url:c}}),o=!0):I(a.base64Data??a.base64??a.data)&&H(t,`[Image attachment omitted: ${I(a.name)||"unnamed"} exceeds the ${te} byte inline limit]`);continue}const u=I(a.url??a.serverUrl)||"";H(t,ut(I(a.name)||"",u,I(a.mediaType??a.mimeType)||"",I(a.size)||""))}return t.length===0?{content:n,hasImages:!1}:{content:t,hasImages:o}}function Re(n){return ss(n)??Zo(n)}async function mt(n){if(!Array.isArray(n))return n;const e=[];for(const t of n){if(t.type==="text"){e.push(t);continue}e.push({type:"image_url",image_url:{url:await Vo(t.image_url.url)}})}return e}function ns(n){return typeof n=="string"?n:Array.isArray(n)?n.map(e=>e.type==="text"?e.text:"[Image]").join(" ").trim():""}function is(n,e){const t=n.permissions??e.permissions??{},o=n.permissions?[]:e.allowedTools??[],s=n.permissions?[]:e.deniedTools??[];return{mode:t.mode??"default",allow:[...t.allow??[],...o].map(i=>i.trim()).filter(Boolean),deny:[...t.deny??[],...s].map(i=>i.trim()).filter(Boolean)}}function rs(n,e){return n==="*"?!0:n.endsWith("*")?e.startsWith(n.slice(0,-1)):n===e}function as(n){return n.kind==="builtin"?[n.exposedName,n.toolName,`builtin.${n.toolName}`]:[n.exposedName,n.toolName,`${n.serverName}.${n.toolName}`,`mcp.${n.serverName}.${n.toolName}`]}function dt(n,e){return as(e).some(t=>rs(n,t))}function pt(n,e,t){if(e.length>0&&!e.some(o=>dt(o,n)))throw new Error(t)}function ht(n,e,t){if(e.mode!=="bypassPermissions"){if(e.deny.some(o=>dt(o,n)))throw new Error(`ACode tool denied by permission rule: ${n.exposedName}`);pt(n,e.allow,`ACode tool is not in allowed permission rules: ${n.exposedName}`),pt(n,t??[],`ACode slash command does not allow tool: ${n.exposedName}`)}}function ls(n,e,t){try{return ht(n,e,t),!0}catch{return!1}}function be(n){const e=n.replace(/\/+$/g,"");return/\/chat\/completions$/i.test(e)?e:`${e}/chat/completions`}function cs(n){try{const e=new URL(n);e.search="",e.hash="";const t=new URL(be(e.toString()));return`${t.origin}${t.pathname}`}catch{return be(n).replace(/([?&](?:api[_-]?key|token|authorization)=)[^&]+/gi,"$1[redacted]")}}function us(n){const e=[...n].reverse().find(o=>o.role==="user"),t=ns(e?.content??null).trim();if(t)return t.length>300?`${t.slice(0,300)}...`:t}function ms(n){try{const e=JSON.parse(n);return fe(e)?e:{}}catch{return{}}}function ds(n,e,t){if(new Set([Pt,"await_complete"]).has(n.toolName))return 0;if(n.toolName!=="Bash")return t;const s=e.timeout_ms??e.timeoutMs,i=typeof s=="number"?s:typeof s=="string"?Number(s):NaN;return!Number.isFinite(i)||i<=0?Math.max(t,Io):Math.min(Math.floor(i),10*6e4)+2e3}function ps(n,e){const t=n.trim();return`ACode \u5DF2\u63A5\u6536\u4EFB\u52A1\u3002\u5F53\u524D\u5DF2\u52A0\u8F7D ${e.configMcpCount} \u4E2A MCP \u914D\u7F6E\u3001${e.exposedTools.length} \u4E2A MCP Tool \u4E0E ${e.skills.length} \u4E2A Skill\u3002${t?`\u8F93\u5165\u6458\u8981\uFF1A${t.slice(0,200)}`:""}`}function G(n){if(!S(n))return String(n??"");const e=n.content;if(Array.isArray(e)){const t=e.map(o=>S(o)?typeof o.text=="string"?o.text:JSON.stringify(o):"").filter(Boolean);if(t.length>0)return t.join(`
3
- `)}return JSON.stringify(n)}function me(n){return n instanceof Error?n.message:String(n)}function hs(n){const e={orphanToolMessages:0,repairedToolCalls:0,downgradedAssistants:0,relocatedInterruptions:0,reorderedToolResults:0};if(n.length===0)return e;const t=(c,d)=>{const p=typeof c.content=="string"?c.content:JSON.stringify(c.content??"");c.role="user",delete c.tool_call_id,c.content=`[\u7CFB\u7EDF\u63D0\u793A] \u4EE5\u4E0B\u4E3A\u4E00\u6B21\u5DE5\u5177\u6267\u884C\u7684\u7ED3\u679C\uFF08tool_call_id=${d}\uFF09\uFF0C\u5176\u5BF9\u5E94\u7684\u5DE5\u5177\u8C03\u7528\u4E0A\u4E0B\u6587\u5DF2\u4E0D\u5728\u4F1A\u8BDD\u4E2D\uFF0C\u4EC5\u4F9B\u53C2\u8003\uFF1A
4
- ${p}`,e.orphanToolMessages+=1},o=c=>{const d=new Map;for(const T of n)if(T.role==="assistant"&&Array.isArray(T.tool_calls))for(const _ of T.tool_calls){const m=typeof _?.id=="string"?_.id:"";m&&!d.has(m)&&d.set(m,T)}const p=new Set;for(const T of n){if(T.role==="assistant"&&Array.isArray(T.tool_calls)){for(const h of T.tool_calls){const g=typeof h?.id=="string"?h.id:"";g&&p.add(g)}continue}if(T.role!=="tool")continue;const _=typeof T.tool_call_id=="string"?T.tool_call_id.trim():"";if(!_){t(T,"(\u7F3A\u5931)");continue}if(p.has(_))continue;const m=d.get(_);if(m){c.push({message:T,id:_,assistant:m});continue}t(T,_)}},s=c=>{if(c.length!==0){for(const d of c){const p=n.indexOf(d.message);p>=0&&n.splice(p,1)}for(const d of c){const p=n.indexOf(d.assistant);if(p<0){t(d.message,d.id);continue}let T=p+1;for(;T<n.length&&n[T].role==="tool";)T+=1;n.splice(T,0,d.message),e.reorderedToolResults+=1}}},i=[];o(i),s(i);const r=()=>{const c=new Set;for(const d of n)d.role==="tool"&&d.tool_call_id&&c.add(d.tool_call_id);return c};let a=r();const l="\uFF08\u8BE5\u5DE5\u5177\u8C03\u7528\u7ED3\u679C\u7F3A\u5931\uFF1A\u6240\u5C5E\u8F6E\u6B21\u88AB\u4E2D\u65AD\u6216\u4E0A\u4E0B\u6587\u538B\u7F29\u65F6\u5DF2\u79FB\u9664\uFF0C\u8BF7\u52FF\u57FA\u4E8E\u8BE5\u8C03\u7528\u7EE7\u7EED\u63A8\u65AD\uFF0C\u5FC5\u8981\u65F6\u91CD\u65B0\u8C03\u7528\u5DE5\u5177\u3002\uFF09";for(let c=0;c<n.length;c++){const d=n[c];if(d.role!=="assistant"||!Array.isArray(d.tool_calls))continue;const p=d.tool_calls.filter(h=>typeof h?.id=="string"&&h.id.trim().length>0);if(p.length!==d.tool_calls.length){if(e.downgradedAssistants+=1,p.length===0){delete d.tool_calls,(d.content===null||d.content===void 0)&&(d.content="");continue}d.tool_calls=p}const T=d.tool_calls.map(h=>h?.id).filter(h=>typeof h=="string"&&h.length>0&&!a.has(h));if(T.length===0)continue;let _=-1;for(let h=c+1;h<n.length;h++){if(n[h].role==="tool"){_=h+1;continue}break}if(_>c){const h=T.map(g=>({role:"tool",tool_call_id:g,content:l}));n.splice(_,0,...h),c+=h.length,e.repairedToolCalls+=T.length,a=r();continue}if(c===n.length-1){for(const h of T)n.push({role:"tool",tool_call_id:h,content:l});e.repairedToolCalls+=T.length,a=r();continue}const m=new Set(d.tool_calls.map(h=>h?.id).filter(h=>typeof h=="string"&&h.length>0));delete d.tool_calls,(d.content===null||d.content===void 0)&&(d.content="");for(const h of n)if(h.role==="tool"&&h.tool_call_id&&m.has(h.tool_call_id)){const g=typeof h.content=="string"?h.content:JSON.stringify(h.content??""),y=h.tool_call_id;h.role="user",delete h.tool_call_id,h.content=`[\u7CFB\u7EDF\u63D0\u793A] \u4EE5\u4E0B\u4E3A\u4E00\u6B21\u5DE5\u5177\u6267\u884C\u7684\u7ED3\u679C\uFF08tool_call_id=${y}\uFF09\uFF0C\u5176\u5BF9\u5E94\u7684\u5DE5\u5177\u8C03\u7528\u4E0A\u4E0B\u6587\u5DF2\u4E0D\u5728\u4F1A\u8BDD\u4E2D\uFF0C\u4EC5\u4F9B\u53C2\u8003\uFF1A
5
- ${g}`,e.orphanToolMessages+=1}a=r(),e.downgradedAssistants+=1}for(let c=0;c<n.length;c++){const d=n[c];if(d.role!=="assistant"||!Array.isArray(d.tool_calls))continue;const p=new Set(d.tool_calls.map(g=>g?.id).filter(g=>typeof g=="string"&&g.length>0));if(p.size===0)continue;const T=g=>g.role==="tool"&&typeof g.tool_call_id=="string"&&p.has(g.tool_call_id),_=[];for(let g=c+1;g<n.length;g++){const y=n[g];if(T(y))continue;if(y.role==="tool")break;let w=!1;for(let A=g+1;A<n.length;A++)if(T(n[A])){w=!0;break}if(!w)break;_.push(y)}if(_.length===0)continue;const m=n.filter(g=>!_.includes(g));let h=-1;for(let g=0;g<m.length;g++)T(m[g])&&(h=g);h<0||(m.splice(h+1,0,..._),n.length=0,n.push(...m),e.relocatedInterruptions+=_.length)}const u=[];return o(u),s(u),e}const ft={truncatedCount:0,strategy:"none",prunedToolMessages:0,summarizedMessages:0,freedTokens:0};async function fs(n,e,t,o,s,i){if(Fe(n)<=e)return ft;const a=await pe(n,t,o,{llmSummarizer:s});if(a.strategy!=="none")return a.summarizedMessages>0&&i&&await i(),{truncatedCount:a.prunedToolMessages+a.summarizedMessages,strategy:a.strategy,prunedToolMessages:a.prunedToolMessages,summarizedMessages:a.summarizedMessages,freedTokens:a.freedTokens};const l=await ze(n,{llmSummarizer:s,contextLimit:t});return l>0&&i&&await i(),{truncatedCount:l,strategy:l>0?"summarize":"none",prunedToolMessages:0,summarizedMessages:l,freedTokens:0}}function gs(n){return we(n)}function ys(n){const e=me(n).toLowerCase();return gs(n)?!1:e.includes("fetch failed")||e.includes("timed out")||e.includes("timeout")||e.includes("econnreset")||e.includes("econnrefused")||e.includes("etimedout")||e.includes("enotfound")||e.includes("socket hang up")||e.includes("network error")||/\b(408|429|500|502|503|504|520|521|522|523|524)\b/.test(e)}function Ts(n){if(typeof n!="object"||n===null)return!1;const e=Reflect.get(n,"code"),t=me(n).toLowerCase();return e===-32001||t.includes("request timed out")}function Cs(n){if(typeof n=="object"&&n!==null){const e=Reflect.get(n,"code");if(typeof e=="string"&&e)return e;const t=Reflect.get(n,"name");if(typeof t=="string"&&t)return t}return"tool_error"}function gt(n,e,t){return JSON.stringify({ok:!1,tool:n.exposedName,error:{type:Cs(e),message:me(e)},...t?{file_snapshot:{path:t.path,bytes:t.bytes,content:t.content}}:{}})}function _s(n){const e=JSON.stringify(n);return e.length>500?`${e.slice(0,500)}\u2026`:e}function yt(n){const e=[n?.reasoning_content,n?.reasoning_text,n?.reasoning];for(const t of e){if(typeof t=="string"&&t)return t;if(S(t)){const o=t.text??t.content;if(typeof o=="string"&&o)return o}}return""}function Tt(n){return n.length===0?"":["Skills are available for this session.","Use the `skill` tool to load specialized skill instructions when a user task matches one of the available skills listed in the tool description.","Do not attempt to follow skill instructions from memory \u2014 always invoke the `skill` tool first to load the full content."].join(" ")}function Ct(n){return n.length===0?"":["Available slash commands:",...n.map(e=>`- /${e.name}${e.description?`: ${e.description}`:""}`),"When the user invokes a slash command, ACode expands it before model execution."].join(`
6
- `)}function As(n){if(!n||typeof n!="object")return"";const e=n,t=[],o=e.displayName,s=e.roleName,i=e.instanceName,r=e.projectId,a=e.workspacePath,l=e.runtimeMode,u=e.describe;return typeof o=="string"&&o.trim()&&t.push(`Display Name: ${o.trim()}`),typeof s=="string"&&s.trim()&&t.push(`Role: ${s.trim()}`),typeof i=="string"&&i.trim()&&t.push(`Instance: ${i.trim()}`),typeof r=="string"&&r.trim()&&t.push(`Project: ${r.trim()}`),typeof a=="string"&&a.trim()&&t.push(`Workspace: ${a.trim()}`),typeof l=="string"&&l.trim()&&t.push(`Runtime Mode: ${l.trim()}`),typeof u=="string"&&u.trim()&&t.push(`Description: ${u.trim()}`),t.length===0?"":["[User Profile]",...t].join(`
7
- `)}function _t(n){return n.map(e=>({type:"function",function:{name:e.exposedName,description:e.description||e.toolName,parameters:e.inputSchema}}))}function bs(n,e){return`${n}__${e}`.replace(/[^a-zA-Z0-9_-]/g,"_").slice(0,64)||"mcp_tool"}function ws(n){const e={"Content-Type":"application/json"};return n.apiKey&&(e.Authorization=`Bearer ${n.apiKey}`),e}function ks(n){return Object.fromEntries(Object.entries(n).map(([e,t])=>[e,Ss(e)?Ms(t):t]))}function Ss(n){const e=n.trim().toLowerCase();return e==="authorization"||e==="api-key"||e==="x-api-key"||e==="openai-api-key"}function Ms(n){return n.trim().toLowerCase().startsWith("bearer ")?"Bearer ***":"***"}function At(n){return n.split(/\r?\n/).filter(e=>e.startsWith("data:")).map(e=>e.slice(5).trim()).filter(Boolean)}function Ie(n){if(!S(n))return null;const e=n.error;if(S(e)){const t=typeof e.message=="string"?e.message:"",o=e.code??e.status??e.type,s=o==null?"":String(o);return t||s?[s,t].filter(Boolean).join(" "):null}if(typeof e=="string"&&e)return e;if(n.type==="error"||n.object==="error"){const t=typeof n.message=="string"?n.message:"",o=n.code??n.status,s=o==null?"":String(o);if(t||s)return[s,t].filter(Boolean).join(" ")}return null}const vs=/role 'tool'|tool calls and tool results|tool_call_sequence|\b11148\b/i;let bt=0,de="";function Ne(n,e,t){if(!vs.test(t))return null;try{const o=new Map,s=new Map;n.forEach((m,h)=>{if(m.role==="assistant"&&Array.isArray(m.tool_calls))for(const g of m.tool_calls){const y=typeof g?.id=="string"?g.id.trim():"";y&&!o.has(y)&&o.set(y,h)}else if(m.role==="tool"){const g=typeof m.tool_call_id=="string"?m.tool_call_id.trim():"";g&&!s.has(g)&&s.set(g,h)}});const i=[];n.forEach((m,h)=>{if(m.role==="tool"){const g=typeof m.tool_call_id=="string"?m.tool_call_id.trim():"",y=g?o.get(g):void 0;(g===""||y===void 0||y>h)&&i.push(h)}else if(m.role==="assistant"&&Array.isArray(m.tool_calls))for(const g of m.tool_calls){const y=typeof g?.id=="string"?g.id.trim():"";if(y===""||!s.has(y)){i.push(h);break}}});const r=m=>` [\u5DE5\u5177\u5E8F\u5217\u8BC1\u636E] \u53EF\u7591\u6D88\u606F ${i.length}/${n.length} \u6761\uFF08${m?`\u5DF2\u5199\u5165 ${m}`:"\u843D\u76D8\u5931\u8D25"}\uFF09`,a=Date.now();if(a-bt<1e4&&de)return r(de);bt=a;const l=m=>({role:m.role,tool_call_id:m.tool_call_id,tool_calls:Array.isArray(m.tool_calls)?m.tool_calls.map(h=>h?.id??null):void 0,contentPreview:typeof m.content=="string"?m.content.slice(0,300):m.content===null?null:JSON.stringify(m.content).slice(0,300)}),u=`acode-tool-seq-${new Date(a).toISOString().replace(/[:.]/g,"-")}.json`,c=String(process.env.AWS_TEST_HOME||"").trim()||String(process.env.AWS_RUNTIME_HOME_DIR||"").trim(),d=String(process.env.AWS_RUNTIME_ENV||"").trim().toLowerCase()==="development",p=c||(d?z.resolve(process.cwd(),"..",".dev-home"):z.dirname(jt())),T=z.join(p,".aws-bridge","log"),_={timestamp:new Date(a).toISOString(),status:e,errorBody:t.slice(0,4e3),suspectIndexes:i,messages:n.map((m,h)=>({index:h,role:m.role,tool_call_id:m.tool_call_id,tool_calls:Array.isArray(m.tool_calls)?m.tool_calls.map(g=>g?.id??null):void 0})),suspectWindows:i.map(m=>{const h=Math.max(0,m-6),g=Math.min(n.length,m+7);return{center:m,range:[h,g],messages:n.slice(h,g).map((y,w)=>({index:h+w,...l(y)}))}})};return de=`.aws-bridge/log/${u}`,D.promises.mkdir(T,{recursive:!0}).then(()=>D.promises.writeFile(z.join(T,u),JSON.stringify(_,null,2),"utf-8")).then(()=>D.promises.readdir(T)).then(m=>{const h=m.filter(y=>y.startsWith("acode-tool-seq-")).sort(),g=h.length-20;return g<=0?null:Promise.all(h.slice(0,g).map(y=>D.promises.unlink(z.join(T,y)).catch(()=>{})))}).catch(()=>{de=""}),r(de)}catch{return null}}function wt(n){const e=new Set,t=Date.now();return n.map((o,s)=>{const i=typeof o?.id=="string"?o.id.trim():"";if(i&&!e.has(i))return e.add(i),o;let r=`call-${t}-${s}`,a=1;for(;e.has(r);)r=`call-${t}-${s}-${a}`,a+=1;return e.add(r),{...o,id:r}})}function $s(n,e){const t=Number.isFinite(e.index)?Number(e.index):0,o=n.get(t)??{id:e.id||`call-${t}`,type:"function",function:{name:"",arguments:""}};e.id&&(o.id=e.id),e.function?.name&&(o.function.name+=e.function.name),e.function?.arguments&&(o.function.arguments+=e.function.arguments),n.set(t,o)}function Es(n){return wt([...n.entries()].sort(([e],[t])=>e-t).map(([,e])=>e).filter(e=>e.function.name.trim().length>0))}function xs(){const n=process.env.ACODE_ABORT_FORCE_SETTLE_GRACE_MS;if(n===void 0||n.trim()==="")return 6e4;const e=Number(n.trim());return Number.isFinite(e)&&e>=0?Math.floor(e):6e4}class Z extends kt{hasActiveBlockingToolCall(){return this.activeBlockingToolCalls>0}static isLongBlockingMcpToolName(e){return uo(e)}constructor(e){super(),this.config=e,this.initialConversation=[],this.mcpStderrBuffers=new Map,this.state={started:!1,terminated:!1,configMcpCount:0,skills:[],provider:{model:"acode-default",stream:!1,requestTimeoutMs:Ve,requestTotalTimeoutMs:Xe,requestRetryCount:tt,requestFirstByteTimeoutMs:Ze,requestStreamIdleTimeoutMs:et,mcpToolTimeoutMs:ye,mcpPollingToolTimeoutMs:ot,supportsImageInput:!1},permissions:{mode:"default",allow:[],deny:[]},mcpConnections:[],ownsMcpConnections:!0,exposedTools:[],commands:[],commandRegistry:new qe([]),conversation:[],accumulatedInputTokens:0,accumulatedOutputTokens:0,accumulatedCacheHitTokens:0,accumulatedCacheMissTokens:0,toolPermissionPolicy:{...Le}},this.abortController=null,this.exposedToolsInitialized=!1,this.recoveredToolNames=new Set,this.readFileStateTracker=new Nt,this.pendingMemorySubAgents=new Map,this.memoryDelegateCooldownUntil=new Map,this.toolGroupManager=null,this.pluginGroupStates=new Map,this.submitQueue=Promise.resolve(),this.activeTurnToken=null,this.forceSettleWaiters=new Map,this.abortForceSettleTimer=null,this.activeTurn=!1,this.activeBlockingToolCalls=0,this.forceMessagePending=!1,this.compactRequested=!1,this.instructionsDirty=!1,this.turnPromptPushed=!1,this.abortRequested=!1,this.toolSettleSlots=new Map,this.toolSettleSeq=0,this.toolResourceLock=go(),this.toolConcurrencyScheduler=new yo,this.toolReadOnlyLimiter=null,this.toolBashLimiter=null,this.toolConcurrencyEnabled=!0,this.pendingAwaitedSubIds=new Set,this.pendingAwaitedBgTaskIds=new Set,this.sessionCompleteEmitted=!1,this.contextVersion=0,this.stopWaiters=new Set,this.compactionDebugTimer=null,this.skillTool=null,this.skillWatchers=[],this.skillRefreshTimer=null,this.questionWaiters=new Map,this.permissionWaiters=new Map,this.hookBus=new co({sessionId:e.sessionId,onError:(i,r)=>{this.emitAcodeEvent("error",{message:`ACode hook failed: ${i.name}: ${r instanceof Error?r.message:String(r)}`})}});for(const i of e.hooks??[])this.hookBus.register(i);e.toolPermissionPolicy&&(this.state.toolPermissionPolicy={...Le,...e.toolPermissionPolicy});const t=e.toolConcurrency;this.toolConcurrencyEnabled=t?.enabled!==!1;const o=t?.maxReadOnly??8;this.toolReadOnlyLimiter=new He(o);const s=t?.maxBash??0;this.toolBashLimiter=s>0?new He(s):null}getAvailableTools(){return this.state.exposedTools.map(e=>e.exposedName)}emitAcodeEvent(e,t){const o={type:e,sessionId:this.config.sessionId,timestamp:So(),data:t};this.emit("event",o)}emitCompactionPhase(e,t,o,s,i){this.emitAcodeEvent("context_compaction",{action:"phase",compactionId:e,parentId:e,phase:t,phaseLabel:o,phaseDetail:s,...i?{trigger:i}:{}})}handleCompactionPhase(e,t){switch(t.phase){case"prune_start":this.emitCompactionPhase(e,"prune","\u9636\u6BB51: \u88C1\u526A\u5DE5\u5177\u8F93\u51FA",`\u6B63\u5728\u88C1\u526A ${t.messageCount??0} \u6761\u6D88\u606F\u4E2D\u7684\u5DE5\u5177\u8F93\u51FA...`);break;case"prune_end":this.emitCompactionPhase(e,"prune_done","\u9636\u6BB51: \u88C1\u526A\u5DE5\u5177\u8F93\u51FA",`\u88C1\u526A\u4E86 ${t.prunedCount??0} \u6761\u5DE5\u5177\u8F93\u51FA, \u91CA\u653E ${t.freedTokens??0} tokens`);break;case"summarize_start":this.emitCompactionPhase(e,"summarize","\u9636\u6BB52: \u6458\u8981\u5316\u5BF9\u8BDD",`\u6B63\u5728\u6458\u8981 ${t.messageCount??0} \u6761\u65E9\u671F\u5BF9\u8BDD\uFF08\u4FDD\u771F\u7EA7\u522B L${t.level??1}\uFF09...`);break;case"summarize_end":this.emitCompactionPhase(e,"summarize_done","\u9636\u6BB52: \u6458\u8981\u5316\u5BF9\u8BDD",`\u6458\u8981\u5316\u4E86 ${t.summarizedCount??0} \u6761\u6D88\u606F${t.usedLLM?" (LLM \u6458\u8981)":" (\u89C4\u5219\u6458\u8981)"}`);break;case"degrade":this.emitCompactionPhase(e,`degrade_l${t.level??2}`,`\u964D\u7EA7\u5230 L${t.level??2}`,t.reason??"\u4FDD\u771F\u7EA7\u522B\u4E0B\u964D");break}}async runCompactionPass(e){const{contextLimit:t,maxOutput:o,effectiveUsed:s,trigger:i,force:r}=e,a=Y(this.state.conversation),l=`compaction-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;this.emitAcodeEvent("context_compaction",{action:"start",compactionId:l,sizeKB:a,estimatedTokens:s,actualInputTokens:this.state.accumulatedInputTokens,actualOutputTokens:this.state.accumulatedOutputTokens,messageCount:this.state.conversation.length,model:this.state.provider.model,trigger:i}),this.emitCompactionPhase(l,"detect",e.detectLabel,e.detectDetail);const u=Vt({contextLimit:t,maxOutput:o,...this.state.provider.inputLimit?{inputLimit:this.state.provider.inputLimit}:{},toolsTokens:ie(this.state.exposedTools)});let c;try{c=await pe(this.state.conversation,t,o,{llmSummarizer:p=>this.summarizeConversationWithLLM(p),onPhase:p=>this.handleCompactionPhase(l,p),actualUsedTokens:s,force:r,budget:u,allowRuleFallback:!1,retryPolicy:{maxAttempts:Math.max(1,this.state.provider.requestRetryCount??3)}})}catch(p){if(!(p instanceof io))throw p;this.emitAcodeEvent("warning",{message:`LLM \u6458\u8981\u4E0D\u53EF\u7528\uFF0C\u5DF2\u4F7F\u7528\u89C4\u5219\u6458\u8981\u515C\u5E95\uFF1A${p.message}`}),c=await pe(this.state.conversation,t,o,{onPhase:T=>this.handleCompactionPhase(l,T),actualUsedTokens:s,force:r,budget:u})}const d=Y(this.state.conversation);return this.emitAcodeEvent("context_compaction",{action:"end",compactionId:l,sizeBeforeKB:a,sizeAfterKB:d,freedKB:Math.round((a-d)*10)/10,strategy:c.strategy,freedTokens:c.freedTokens,tokensBefore:c.tokensBefore,tokensAfter:c.tokensAfter,prunedToolMessages:c.prunedToolMessages,summarizedMessages:c.summarizedMessages,messageCountBefore:c.messageCountBefore,messageCountAfter:c.messageCountAfter,level:c.level,...c.levelLabel?{levelLabel:c.levelLabel}:{},...c.ladderStep?{ladderStep:c.ladderStep}:{},...c.summaryChunks?{summaryChunks:c.summaryChunks}:{},...c.downsampleCount!==void 0?{downsampleCount:c.downsampleCount}:{},...c.noSummary!==void 0?{noSummary:c.noSummary}:{},...c.reachedTarget!==void 0?{reachedTarget:c.reachedTarget}:{}}),this.state.accumulatedInputTokens=0,this.state.accumulatedOutputTokens=0,c.summarizedMessages>0&&await this.rebuildRuntimeResourcesMessage(),this.rebuildRuntimeInstructionsMessage(),c}compactContext(){if(!this.state.started||this.state.terminated)throw new Error("ACode runtime is not active");return this.compactRequested=!0,f("[ACodeRuntime] \u{1F5DC}\uFE0F Manual compaction requested (\u5148\u884C\u538B\u7F29): unified high-fidelity cascade"),{requested:!0}}async start(){this.emitAcodeEvent("startup_phase",{phase:"loading_config"});const e=await ao(this.config.configPath);this.emitAcodeEvent("startup_phase",{phase:"loading_skills"});const{skills:t,skillGroups:o,watchedDirs:s}=await this.loadAllSkills(),i=Jo(this.config,e);f(`[ACodeRuntime] \u2605\u2605\u2605 DEBUG \u2605\u2605\u2605 resolveProviderConfig \u7ED3\u679C: config.model=${this.config.model??"(undefined)"}, resolvedModel=${i.model}, baseURL=${i.baseURL??"(none)"}, apiKey=${i.apiKey?"[set]":"(none)"}, configPath=${this.config.configPath??"(none)"}`);const r=is(this.config,e),a=this.config.sharedMcpConnections?this.filterSharedMcpConnectionsForSubAgent(this.config.sharedMcpConnections):await this.connectMcpServers(e.mcpServers??{},i.mcpToolTimeoutMs),l=!this.config.sharedMcpConnections;this.emitAcodeEvent("startup_phase",{phase:"fetching_profile"});const u=await this.fetchProfilePrompt(a),c=this.config.agentId||"unknown";Ft(c),le.reconcileOrphans(c);const d=Rt(this.config.workingDirectory,c,this.config.onFileChange,{manager:le,emitCompleted:C=>{this.emitAcodeEvent("background_command_completed",C)}},this.createToolPermissionController(),{tracker:this.readFileStateTracker,enabled:this.config.enableStaleFileGuard!==!1}),p=Ot(this.buildAskUserQuestionDeps(),()=>this.contextVersion),T=Lt(t);this.skillTool=T;const _=Dt(c),m=Bt(c),h=this.config.subAgentManager?Ut(this.buildSubAgentToolDeps(this.config.subAgentManager)):[],g=qt(this.buildAwaitCompleteDeps()),y=this.config.terminalManager?Wt(c,{terminalManager:this.config.terminalManager}):null,w=new Map;this.pluginGroupStates=w;const A=new Gt({stateOf:C=>Ue(C)?w.get(C)??"disabled":(this.config.capabilityState??(()=>"disabled"))(C)});A.register({key:"pencil",label:"\u8BBE\u8BA1\u753B\u5E03(pencil)",summary:"UI design editor",collapsible:!0}),A.register({key:"draw",label:"\u7ED8\u56FE",summary:"\u7ED8\u5236 draw.io \u6D41\u7A0B\u56FE/\u6CF3\u9053\u56FE",collapsible:!0}),A.register({key:"office",label:"Office \u6587\u4EF6",summary:"\u53EF\u8FDB\u884C\u67E5\u770B/\u521B\u5EFA\u548C\u590D\u6742\u7F16\u8F91 Word/PPT/Excel",collapsible:!0}),A.register({key:"launch",label:"\u542F\u52A8\u9879\u7BA1\u7406",summary:"\u7BA1\u7406\u9879\u76EE\u4E2D\u4E1A\u52A1\u7A0B\u5E8F\u7684\u8D77\u505C\uFF0C\u82E5\u540E\u9762\u9700\u8981\u542F\u52A8\u9879\u76EE\u5E94\u4F7F\u7528\u6B64\u5DE5\u5177",collapsible:!0}),A.register({key:"hire",label:"\u62DB\u8058\u5DE5\u5177",summary:"\u62DB\u8058\u65B0\u7684\u540C\u4E8B Agent",collapsible:!0}),A.register({key:"browser",label:"\u6D4F\u89C8\u5668\u64CD\u4F5C",summary:"\u542F\u52A8\u6D4F\u89C8\u5668\u4F1A\u8BDD\u3001\u5BFC\u822A\u3001\u622A\u56FE\u4E0E\u9875\u9762\u4EA4\u4E92",collapsible:!0}),A.register({key:"desktop",label:"\u684C\u9762\u64CD\u4F5C",summary:"\u622A\u5C4F\u3001\u9F20\u6807\u952E\u76D8\u63A7\u5236\u4E0E UI \u81EA\u52A8\u5316",collapsible:!1}),A.register({key:"task",label:"\u6D41\u7A0B\u4EFB\u52A1",summary:"\u5904\u7406\u6D41\u7A0B\u7EBF\u4EFB\u52A1\uFF1A\u67E5\u770B\u5F53\u524D\u4EFB\u52A1\u3001\u63D0\u4EA4\u6267\u884C\u7ED3\u679C\u3001\u56DE\u9000\u4EFB\u52A1\u3001\u7ED9\u6D41\u7A0B\u5B9E\u4F8B\u7559\u8A00",collapsible:!0,toolNames:["my_task","submit_task_result","start_task_rollback","finish_task_rollback","create_task_instance_comment"]}),A.register({key:"meeting",label:"\u4F1A\u8BAE",summary:"\u521B\u5EFA/\u52A0\u5165\u4F1A\u8BAE\u3001\u53D1\u8A00\u3001\u67E5\u770B\u4F1A\u8BAE\u4FE1\u606F\u3001\u79BB\u5F00/\u7ED3\u675F\u4F1A\u8BAE",collapsible:!0,toolNames:["create_meeting","leave_meeting","end_meeting","meeting_speak","get_meeting_info","my_meetings"]}),A.register({key:"debug",label:"\u8C03\u8BD5\u65E5\u5FD7",summary:"\u6309\u6761\u4EF6\u5206\u9875\u67E5\u8BE2 Debug \u65E5\u5FD7\u4E0E\u83B7\u53D6\u65E5\u5FD7\u4E0A\u62A5\u914D\u7F6E",collapsible:!0,toolNames:["get_debug_log_config","query_debug_logs"]}),A.register({key:"fileHistory",label:"\u6587\u4EF6\u53D8\u66F4\u5386\u53F2",summary:"\u6309\u89D2\u8272/\u5B9E\u4F8B/\u6587\u4EF6\u8DEF\u5F84\u8FC7\u6EE4\u67E5\u8BE2\u6587\u4EF6\u53D8\u66F4\u5386\u53F2",collapsible:!0,toolNames:["query_file_changes_history"]}),A.register({key:"email",label:"\u90AE\u7BB1",summary:"\u6536\u53D1\u89D2\u8272\u5B9E\u4F8B\u57DF\u540D\u90AE\u7BB1\uFF08xxxxx@\u57DF\u540D\uFF09\uFF1A\u53D1\u4FE1\u3001\u5217\u90AE\u4EF6\u3001\u8BFB\u6B63\u6587\u4E0E\u9644\u4EF6\u3001\u56DE\u4FE1\u4FDD\u6301\u7EBF\u7A0B\u3001\u786E\u8BA4\u4E1A\u52A1\u6D88\u8D39",collapsible:!0,toolNames:["send_email","list_emails","read_email","reply_email","ack_email"]}),this.toolGroupManager=A;for(const C of a){const R=C.spec??e.mcpServers?.[C.serverName];R&&this.registerMcpCollapsedGroup(C.serverName,R,C)}for(const C of a)this.registerToolGroupsFromMcp(C);if(this.config.pluginBridge)try{const C=await this.config.pluginBridge.listPlugins();this.applyPluginGroups(C,w,A)}catch(C){f(`[ACodeRuntime] \u63D2\u4EF6\u7EC4\u6CE8\u518C\u5931\u8D25\uFF08\u5FFD\u7565\uFF09: ${C instanceof Error?C.message:String(C)}`)}const N=Jt({toolGroupManager:A,getAllTools:()=>this.state.exposedTools,capabilityToolRelay:this.config.capabilityToolRelay,pluginBridge:this.config.pluginBridge}),k=Kt({toolGroupManager:A,pluginBridge:this.config.pluginBridge,capabilityToolRelay:this.config.capabilityToolRelay,findTool:C=>{const R=this.state.exposedTools.find(Pe=>Pe.exposedName===C||Pe.toolName===C);if(!R)return;const ae=R.group??A.getGroupForExposedName(R.exposedName);return{kind:R.kind,group:ae,toolName:R.toolName}},dispatchTool:(C,R,ae)=>this.executeSingleToolByName(C,R,ae)}),v=[...d,p,T,_,m,...h,g,...y?[y]:[],N,k,...a.flatMap(C=>C.tools),...Ke(this.config.extraBuiltInTools??[],this.config.agentId??"")];if(this.config.subAgentAllowedTools&&this.config.subAgentAllowedTools.length>0){const C=Ke(this.config.subAgentSuiteTools??[],this.config.agentId??""),R=he(v,C);v.length=0,v.push(...R)}let M=v;const L=this.config.subAgentAllowedTools;L&&L.length>0&&(M=M.filter(C=>Je(C,L)));const E=this.resolveCommandDirs(e);let O=[...E,...this.discoverPluginCommandDirs()];if(this.config.pluginBridge?.getCommandDirs)try{const C=await this.config.pluginBridge.getCommandDirs();C.length>0&&(O=[...O,...C])}catch(C){f(`[ACodeRuntime] \u63D2\u4EF6\u547D\u4EE4\u76EE\u5F55\u83B7\u53D6\u5931\u8D25\uFF08\u5FFD\u7565\uFF09: ${C instanceof Error?C.message:String(C)}`)}O=[...new Set(O)],this.emitAcodeEvent("startup_phase",{phase:"loading_commands"});const U=await Qt(O),re=new qe(U),ee=Tt(t),b=Ct(U),P=A.buildCapabilityPrompt(),Q=this.config.pluginBridge?["","## \u63D2\u4EF6\u7CFB\u7EDF","\u5DF2\u5B89\u88C5\u63D2\u4EF6\u4EE5\u6536\u7EB3\u7EC4\u5F62\u5F0F\u5217\u51FA\uFF08\u89C1\u4E0A\u65B9\u300C\u53EF\u7528\u80FD\u529B\u300D\u4E2D\u7684 plugin:{\u63D2\u4EF6\u540D} \u6761\u76EE\uFF09\u3002",'\u9700\u8981\u67D0\u63D2\u4EF6\u7684\u5DE5\u5177\u65F6\uFF0C\u5148 expand_tools({ group: "plugin:\u63D2\u4EF6\u540D" }) \u5C55\u5F00\uFF1B','\u5DE5\u5177\u5B9A\u4E49\uFF08\u542B\u53C2\u6570 schema\uFF09\u968F\u5C55\u5F00\u7ED3\u679C\u8FD4\u56DE\uFF0C\u518D\u7528 call_tool({ name: "\u63D2\u4EF6\u540D.\u5DE5\u5177\u540D", arguments: {...} }) \u8C03\u7528\u3002',"\u63D2\u4EF6\u4E8B\u4EF6\u4EE5 [plugin-event] \u6D88\u606F\u51FA\u73B0\uFF0C\u6D88\u606F\u6807\u660E\u6765\u6E90\u63D2\u4EF6\u4E0E\u4E8B\u4EF6\u540D\u5E76\u5E26 toolHints\uFF08\u5EFA\u8BAE\u8C03\u7528\u7684\u5DE5\u5177\uFF09\uFF0C\u6309\u63D0\u793A\u5C55\u5F00\u5E76\u5904\u7406\u3002","\u80FD\u529B\u7BA1\u7406\u5206\u5C5E\u4E24\u4E2A\u72EC\u7ACB\u6388\u6743\u7684\u5DE5\u5177\u7EC4\uFF1A","\u300C\u80FD\u529B\u5E02\u573A\u300D\u7EC4\u8D1F\u8D23\u5B89\u88C5/\u5378\u8F7D MCP / Skill / Plugin\uFF1Alist_ability_market \u6D4F\u89C8\uFF08\u8FD4\u56DE\u73AF\u5883\u53D8\u91CF\u5951\u7EA6 envSchema\uFF0CMCP \u9700\u636E\u6B64\u914D\u7F6E env\uFF0C\u654F\u611F\u503C\u5FC5\u987B\u7531\u7528\u6237\u63D0\u4F9B\uFF09\u3001install_ability_market_item \u5B89\u88C5\u3001uninstall_ability_market_item \u5378\u8F7D\uFF08kind=plugin \u5373\u5B89\u88C5/\u5378\u8F7D\u63D2\u4EF6\uFF09\u3002","\u300C\u80FD\u529B\u5F00\u53D1\u300D\u7EC4\u8D1F\u8D23\u81EA\u7814 MCP / \u63D2\u4EF6 / Skill \u5E76\u7BA1\u7406\u5DF2\u88C5\u63D2\u4EF6\uFF1A","\u7528 ability_dev_ide \u8BFB\u7F16\u5199\u89C4\u8303\uFF08action=guide\uFF0Ckind=plugin|mcp|skill\uFF09\u5E76\u5728\u81EA\u5DF1\u7684\u4F1A\u8BDD\u5DE5\u4F5C\u533A\u5185\u7F16\u5199\uFF1B","MCP/\u63D2\u4EF6\u7528 ability_dev_ide \u4E34\u65F6\u6302\u8F7D\u8C03\u8BD5\uFF08action=mount/unmount/list/logs\uFF1B\u4E0D\u6301\u4E45\u5316\u3001\u91CD\u542F\u5373\u5931\u6548\uFF0C\u6539\u4EE3\u7801\u81EA\u52A8\u91CD\u8F7D\uFF09\uFF0C","mount \u540E\u5DE5\u5177\u540D\u5F62\u5982 <server>__<tool>\uFF08\u53CC\u4E0B\u5212\u7EBF\uFF09\uFF0C\u7528 call_tool \u8C03\u7528\uFF1B","action=list \u67E5\u770B\u6302\u8F7D\u9879\u4E0E\u66B4\u9732\u7684\u5DE5\u5177\u540D\uFF0Caction=logs \u6392\u67E5\u5B50\u8FDB\u7A0B\u62A5\u9519\uFF0Caction=unmount \u6458\u9664\uFF1B","\u8C03\u8BD5\u901A\u8FC7\u540E\u7528 formal_ability \u8F6C\u6B63\uFF08\u7F3A\u7701 scope=global \u4EC5\u767B\u8BB0\u5168\u5C40\u914D\u7F6E\u6A21\u677F\u4E14\u521D\u59CB\u5316\u5173\u95ED\uFF0C\u9700\u7528\u6237\u5728\u9762\u677F\u5F00\u542F\u540E\u751F\u6548\uFF1Bscope=instance \u624D\u7ACB\u5373\u751F\u6548\uFF09\uFF1BSkill \u65E0\u8C03\u8BD5\u6001\uFF0C\u540C\u6837\u53EF\u7ECF formal_ability \u6216\u80FD\u529B\u5E02\u573A\u5B89\u88C5\u3002","\u5DF2\u5B89\u88C5\u63D2\u4EF6\u7684\u542F\u505C/\u91CD\u8F7D\u7531\u7528\u6237\u5728\u9762\u677F\u64CD\u4F5C\uFF1B","\u67E5\u770B\u81EA\u8EAB\u5168\u90E8\u80FD\u529B\uFF08MCP/Skill/Plugin \u542F\u505C\u4E0E\u6765\u6E90\u3001\u5DE5\u5177\u5F00\u5173\u3001\u8C03\u8BD5\u6302\u8F7D\uFF09\u7528 list_my_abilities\u3002","\u672A\u7ECF\u7528\u6237\u660E\u786E\u8981\u6C42\u4E0D\u8981\u5B89\u88C5\u6216\u5378\u8F7D\u63D2\u4EF6\u3002"].join(`
8
- `):"",q=P+Q,x=[De,i.systemPrompt,ee,b,q].map(C=>C?.trim()).filter(C=>!!C).join(`
1
+ import{EventEmitter as Et}from"node:events";import{randomUUID as It}from"node:crypto";import D from"node:fs";import De from"node:os";import z from"node:path";import{Client as Nt}from"@modelcontextprotocol/sdk/client/index.js";import{SSEClientTransport as Pt}from"@modelcontextprotocol/sdk/client/sse.js";import{StdioClientTransport as Ot}from"@modelcontextprotocol/sdk/client/stdio.js";import{StreamableHTTPClientTransport as Lt}from"@modelcontextprotocol/sdk/client/streamableHttp.js";import{ToolListChangedNotificationSchema as Bt}from"@modelcontextprotocol/sdk/types.js";import{createBuiltInFileTools as Dt,DEFAULT_TOOL_PERMISSION_POLICY as Ue,getEditFailureSnapshot as Ut}from"./built-in-file-tools.js";import{ReadFileStateTracker as qt}from"./read-file-state.js";import{ASK_USER_QUESTION_TOOL_NAME as Ft,createAskUserQuestionTool as zt}from"./ask-user-question-tool.js";import{createSkillTool as jt}from"./skill-tool.js";import{createTodoWriteTool as Wt,createTodoReadTool as Gt}from"./todo-tool.js";import{createSubAgentTools as Jt}from"./sub-agent-tools.js";import{createAwaitCompleteTool as Kt}from"./await-complete-tool.js";import{cleanupAcodeCmdDist as Ht}from"./builtins/commandArtifacts.js";import{buildRuntimeEnvironmentPrompt as Qt}from"./runtime-environment.js";const qe="[Runtime Instructions]";import{resolveAcodeHome as Yt}from"./paths.js";import{backgroundCommandManager as le}from"./background-command-manager.js";import{createTerminalTool as Vt}from"./terminal-tool.js";import{ToolGroupManager as Xt,createExpandToolsTool as Zt,createCallToolTool as eo,mcpGroupKeyOf as Fe,isPluginGroupKey as ze,pluginGroupKeyOf as to,registerBuiltinNamedToolGroups as oo}from"./tool-group-manager.js";import{loadAcodeCommands as so}from"./commands/commandLoader.js";import{ACodeCommandRegistry as je}from"./commands/commandRegistry.js";import{calculateCompactionThreshold as no,calculateCompactionBudget as We,COMPACTION_LLM_PROMPT_TEMPLATE as io,conversationSizeBytes as Ge,conversationSizeKB as X,estimateConversationTokens as G,estimateContextTokens as Me,isCompactionSummaryMessage as ro,isEmptyAnchors as ao,isRuntimeResourcesMessage as lo,isRuntimeInstructionsMessage as co,performCompaction as fe,renderAnchorsForPrompt as uo,resolveReplayWindow as mo,pruneToolOutputs as po,RUNTIME_RESOURCES_PREFIX as ho,summarizeConversation as Se,SummaryUnavailableError as Je}from"./compaction.js";import{isContextOverflowError as ve,resolveFinishReasonOverflow as fo}from"./context-overflow.js";import{asCacheControlMessages as Ke,injectCacheControl as He}from"./cache-control.js";import{maybeMicrocompact as go}from"./microcompact.js";import{loadAcodeConfig as To,loadAcodeSkillGroup as yo}from"./config.js";import{ACodeHookBus as Co,findDeniedHookResult as Qe}from"./hooks/hookBus.js";import{isMcpPollingToolName as Ye,isMcpBlockingToolName as $e,isMcpBatchExcludedToolName as xe,isMcpIndefinitelyBlockingToolName as Ao,getSemanticToolName as Re}from"./mcpToolNames.js";import{runtimeMeetingDebugLog as U}from"./meeting-debug-log.js";import{BackgroundOutputRingBuffer as _o}from"./background-output-ringbuffer.js";import{buildToolCatalog as Ve,matchesToolAllocation as Xe,mergeAllocatableTools as ge,PRESET_EXPLORE as bo,rebindDefaultAgentId as Ze,resolveToolAllocation as wo,SUB_AGENT_ALLOWED_MCP_TOOLS as ko}from"./tool-allocation.js";import{ConcurrencyLimiter as et,getSharedResourceLock as Mo,ToolConcurrencyScheduler as So,ToolTraceRecorder as tt}from"./tool-concurrency/index.js";function vo(n){if(typeof n!="object"||n===null)return!1;const e=n;return e.kind==="builtin"&&typeof e.toolName=="string"&&typeof e.exposedName=="string"&&typeof e.description=="string"&&typeof e.execute=="function"&&typeof e.inputSchema=="object"&&e.inputSchema!==null}function $o(n){return n.type==="text"?{type:"text",text:n.text}:{type:"image_url",image_url:{url:n.image_url.url}}}function xo(n){return{id:n.id,type:"function",function:{name:n.function.name,arguments:n.function.arguments}}}function Ro(n){const e={role:n.role,content:Array.isArray(n.content)?n.content.map($o):n.content};return n.tool_call_id&&(e.tool_call_id=n.tool_call_id),n.tool_calls&&(e.tool_calls=n.tool_calls.map(xo)),n.reasoning&&(e.reasoning=n.reasoning),e}function ce(n){return n.map(Ro)}function Eo(n){return n.map(e=>{const{reasoning:t,...o}=e;return o})}function Te(n){const e=[];for(const t of n){if(t.role!=="system")break;e.push({role:"system",content:t.content})}return e}function Io(n,e){const t=J(n.prompt_cache_hit_tokens),o=J(n.prompt_cache_miss_tokens);if(t!==void 0||o!==void 0)return{cacheHitTokens:t??0,cacheMissTokens:o??0};const s=J(n.cache_read_input_tokens),i=J(n.cache_creation_input_tokens);if(s!==void 0||i!==void 0){const u=s??0,c=i??0,d=J(n.input_tokens)??(e!==void 0?Math.max(0,e-u-c):0);return{cacheHitTokens:u,cacheMissTokens:c+d}}const r=J(n.cache_hit_tokens),a=J(n.cache_miss_tokens);if(r!==void 0||a!==void 0)return{cacheHitTokens:r??0,cacheMissTokens:a??0};const l=J(n.prompt_tokens_details?.cached_tokens);if(l!==void 0){const u=e!==void 0?Math.max(0,e-l):0;return{cacheHitTokens:l,cacheMissTokens:u}}}function J(n){const e=typeof n=="number"?n:typeof n=="string"&&n.trim()?Number(n):NaN;if(!(!Number.isFinite(e)||e<0))return e}function No(n,e){if(!n)return e;const t=o=>{const s=e[o],i=n[o];return o==="prompt_tokens_details"?{...i,...s}:s??i};return{prompt_tokens:t("prompt_tokens"),completion_tokens:t("completion_tokens"),input_tokens:t("input_tokens"),output_tokens:t("output_tokens"),prompt_cache_hit_tokens:t("prompt_cache_hit_tokens"),prompt_cache_miss_tokens:t("prompt_cache_miss_tokens"),cache_read_input_tokens:t("cache_read_input_tokens"),cache_creation_input_tokens:t("cache_creation_input_tokens"),cache_hit_tokens:t("cache_hit_tokens"),cache_miss_tokens:t("cache_miss_tokens"),prompt_tokens_details:t("prompt_tokens_details")}}function Po(){return new Date().toISOString()}function M(n){return!!(n&&typeof n=="object"&&!Array.isArray(n))}function ye(n){return M(n)}function ot(n,e){return e.map(t=>({serverName:n,toolName:t.name,kind:"mcp",exposedName:Ps(n,t.name),description:t.description,inputSchema:ye(t.inputSchema)?t.inputSchema:{type:"object",properties:{}}}))}const Ce="ACODE_TOOL_GROUPS_V1:";function Oo(n){const e=String(n??"").trim();if(!e.startsWith(Ce))return[];const t=e.slice(Ce.length).trim();if(!t)return[];let o;try{o=JSON.parse(t)}catch{return[]}if(!ye(o)||!Array.isArray(o.groups))return[];const s=[];for(const i of o.groups){if(!ye(i))continue;const r=typeof i.key=="string"?i.key.trim():"";if(!r)continue;const a=Array.isArray(i.toolNames)?i.toolNames.filter(l=>typeof l=="string"&&l.length>0):[];s.push({key:r,label:typeof i.label=="string"&&i.label.trim()?i.label:r,toolNames:a})}return s}function Lo(n){const e=String(n??"").trim();if(!e)return;if(!e.startsWith(Ce))return e;const t=e.slice(Ce.length).trim();return t.startsWith("{")?void 0:t||void 0}function R(n){return String(n??"").trim()||void 0}const st=6e4,nt=30*6e4,it=6e4,rt=6e4,Ee=-1,at=0,Bo=1e3,Do=3e4,Ae=6e4,lt=0,Uo=2147483647,qo=8,Fo=10*6e4+2e3,zo=1e4,_e=5e3,ct=10*60*1e3,se=10*1024*1024,ut=800*1024,dt=32*1024*1024,jo=4,Wo=1.25;function mt(){const n=Number.parseInt(String(process.env.ACODE_MAX_REQUEST_BODY_BYTES??"").trim(),10);return Number.isFinite(n)&&n>0?n:void 0}function Go(){return mt()!==void 0}function Jo(n){const e=mt();if(e!==void 0)return e;if(!Number.isFinite(n)||n<=0)return ut;const t=Math.floor(n*jo*Wo);return Math.min(dt,Math.max(ut,t))}const be=process.env.ACODE_COMPACTION_DEBUG==="1",pt=be?z.join(De.tmpdir(),"acode-compaction-debug.log"):"";function h(...n){be&&console.log(...n)}const Ko=process.env.ACODE_IMAGE_DIAG==="1",Ho=process.env.ACODE_IMAGE_DIAG_LOG||z.join(De.tmpdir(),"acode-image-inject.log");function we(n){if(!Ko)return;const e=`[${new Date().toISOString()}] ${JSON.stringify(n)}
2
+ `;D.promises.appendFile(Ho,e).catch(()=>{})}const Qo=process.env.ACODE_TOKEN_DEBUG==="1";function ne(...n){Qo&&console.log("[TokenDebug][Runtime]",...n)}const Yo=64e3,Ie=8e3;function ue(n){const e=n.contextLimit&&n.contextLimit>0?n.contextLimit:Yo,t=n.maxOutput&&n.maxOutput>0?n.maxOutput:8192,o=n.inputLimit&&n.inputLimit>0?n.inputLimit:void 0,s=no(e,t,o);return{contextLimit:e,maxOutput:t,inputLimit:o,threshold:s}}async function E(n,e,t,o){if(e<=0)return await n;let s;try{return await new Promise((i,r)=>{s=setTimeout(()=>{o?.(),r(new Error(`${t} timed out after ${e}ms`))},e),n.then(i,r)})}finally{s&&clearTimeout(s)}}function ht(){return`toolbatch-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`}async function ie(n,e,t,o=zo){try{await E(e,o,n)}catch(s){t(s instanceof Error?s.message:String(s))}}function V(n,e){if(n===0||n==="0")return 0;const t=typeof n=="number"?n:Number(n);return t===Ee?Ee:Number.isFinite(t)&&t>0?Math.floor(t):e}function de(n,e){const t=V(n,e);return t>0?t:e}const ft=3;function Ne(n){return n?Math.ceil(n.length/ft):0}function Vo(n,e){let t=n.length;for(const o of e){const s=(o.kind==="mcp",o.toolName);if(t+=s.length,o.kind==="mcp")o.description&&(t+=o.description.length),t+=JSON.stringify(o.inputSchema).length;else{const i=o;i.inputSchema&&(t+=JSON.stringify(i.inputSchema).length)}}return Math.ceil(t/ft)}function K(n){if(n.length===0)return 0;const e=JSON.stringify(vt(n));return Ne(e)}async function Xo(n){await new Promise(e=>setTimeout(e,n))}function Zo(n){return typeof n=="boolean"}function es(n,e,t){if(Zo(t?.supportsImageInput))return t.supportsImageInput;const o=M(e)?e.models:void 0,s=M(o)?o[n]:void 0;if(!M(s))return!1;const i=s.modalities;return!M(i)||!Array.isArray(i.input)?!1:i.input.some(r=>String(r||"").trim().toLowerCase()==="image")}function me(n,e,t,o){if(n!==void 0)return n;if(!e)return;const s=e.models;if(M(s)){const i=s[t];if(M(i)){const r=i[o];if(r!==void 0)return r}}return e[o]}function ts(n,e,t){const o=me(n,e,t,"cacheControlMode");if(typeof o!="string")return"off";const s=o.trim().toLowerCase();return s==="message"?"message":s==="content-block"||s==="contentblock"?"content-block":"off"}function os(n,e,t){const o=me(n,e,t,"microcompact");if(!M(o))return;const s=o.enabled===!0,i=V(o.thresholdTokens,0),r=V(o.keepRecentToolResults,0),a=V(o.minTokenSavings,0);return{enabled:s,...i>0?{thresholdTokens:i}:{},...r>0?{keepRecentToolResults:r}:{},...a>0?{minTokenSavings:a}:{}}}function ss(n,e){const t=e.provider?.default,o=t?.options,s=n.model||t?.model||e.model||"acode-default",i=R(n.effort)||R(o?.effort)||R(t?.effort)||void 0;return{model:s,baseURL:R(o?.baseURL||o?.baseUrl),apiKey:R(o?.apiKey),effort:i,systemPrompt:n.systemPrompt||e.systemPrompt,stream:o?.stream!==!1,requestTimeoutMs:de(o?.requestTimeoutMs??o?.timeoutMs,st),requestTotalTimeoutMs:de(o?.requestTotalTimeoutMs,nt),requestRetryCount:V(o?.requestRetryCount,at),requestFirstByteTimeoutMs:de(o?.requestFirstByteTimeoutMs,it),requestStreamIdleTimeoutMs:de(o?.requestStreamIdleTimeoutMs,rt),mcpToolTimeoutMs:de(o?.mcpToolTimeoutMs,Ae),mcpPollingToolTimeoutMs:V(o?.mcpPollingToolTimeoutMs,lt),supportsImageInput:es(s,t,o),contextLimit:V(me(o?.contextLimit,t,s,"contextLimit"),0)||void 0,inputLimit:V(me(o?.inputLimit,t,s,"inputLimit"),0)||void 0,maxOutput:V(me(o?.maxOutput,t,s,"maxOutput"),0)||void 0,cacheControlMode:ts(o?.cacheControlMode,t,s),microcompact:os(o?.microcompact,t,s)}}function j(n,e){const t=e.replace(/\s+/g," ").trim();t&&n.push({type:"text",text:t})}function ns(n,e){const t=e.trim();return/^data:image\/[a-z0-9.+-]+;base64,/i.test(t)?t:`data:${n||"image/png"};base64,${t}`}function is(n){return/^data:image\/[a-z0-9.+-]+;base64,/i.test(n.trim())}function rs(n){let e;try{e=new URL(n)}catch{throw new Error(`ACode image URL is invalid: ${n}`)}if(e.protocol!=="http:"&&e.protocol!=="https:")throw new Error(`ACode image URL protocol is not supported: ${e.protocol}`)}async function as(n){const e=await n.arrayBuffer();if(e.byteLength>se)throw new Error(`ACode image is too large to inline: ${e.byteLength} bytes exceeds ${se} bytes`);return Buffer.from(e).toString("base64")}async function ls(n){const e=n.trim();if(is(e)){if(e.slice(e.indexOf(",")+1).length*.75>se)throw new Error(`ACode inline image exceeds the ${se} byte size limit`);return e}rs(e);const t=await fetch(e);if(!t.ok)throw new Error(`ACode image fetch failed: ${t.status} ${await t.text()}`);const o=t.headers.get("content-type")||"",s=o.split(";")[0]?.trim().toLowerCase()||"";if(!s.startsWith("image/"))throw new Error(`ACode image URL did not return an image content type: ${o||"unknown"}`);return`data:${s};base64,${await as(t)}`}function cs(n){const e=R(n.base64Data??n.base64??n.data);return e?e.length*.75>se?void 0:ns(R(n.mediaType??n.mimeType)||"image/png",e):R(n.url??n.serverUrl)}function gt(n,e,t,o){return`[Attached file: ${[n?`name=${n}`:void 0,e?`url=${e}`:void 0,t?`mediaType=${t}`:void 0,o?`size=${o}`:void 0].filter(i=>!!i).join(", ")}]`}function Tt(n){const e=R(n.url)||"",t=Number(n.durationMs),o=Number.isFinite(t)&&t>0?`${(t/1e3).toFixed(1)}s`:"unknown",s=R(n.transcriptState)||"",i=R(n.lang)||"",r=R(n.source)||"",a=[`duration=${o}`,e?`url=${e}`:void 0,i?`lang=${i}`:void 0].filter(l=>!!l);return s==="failed"?`[Voice message: ${a.join(", ")}] \u8BE5\u8BED\u97F3\u7684\u81EA\u52A8\u8F6C\u5199\u5931\u8D25\uFF0C\u4E0A\u65B9\u6587\u672C\u4E0D\u53EF\u4FE1\u3002\u5982\u9700\u7406\u89E3\u5176\u5185\u5BB9\uFF0C\u8BF7\u8C03\u7528 transcribe_voice \u5DE5\u5177\uFF08\u4F20\u5165\u4E0A\u9762\u7684 url\uFF09\u91CD\u65B0\u8BC6\u522B\u3002`:r==="tts"?`[Voice message: ${a.join(", ")}] \u4E0A\u65B9\u6587\u672C\u4E3A\u8BE5\u8BED\u97F3\u7684\u539F\u6587\uFF08\u7531\u6587\u5B57\u5408\u6210\u8BED\u97F3\u540E\u53D1\u51FA\uFF0C\u6587\u5B57\u4E0E\u97F3\u9891\u5185\u5BB9\u4E00\u81F4\uFF09\u3002`:`[Voice message: ${a.join(", ")}] \u4E0A\u65B9\u6587\u672C\u4E3A\u8BE5\u8BED\u97F3\u7684\u81EA\u52A8\u8F6C\u5199\u7ED3\u679C\u3002`}function us(n,e,t,o){return`[Attached temp file: ${[n?`name=${n}`:void 0,e?`path=${e}`:void 0,t?`mediaType=${t}`:void 0,o?`size=${o}`:void 0].filter(i=>!!i).join(", ")}] \u8BE5\u6587\u4EF6\u4FDD\u5B58\u5728\u672C\u673A\u4E34\u65F6\u76EE\u5F55\u4E2D\uFF0Cuse read_file with the absolute path above to read it.`}function ds(n){const e=/\[(图片|文件|临时文件|语音)\s*:\s*([^\]\n]*?)\s*\]/gi,t=[];let o=!1,s=0,i=e.exec(n);for(;i!==null;){j(t,n.slice(s,i.index));const r=i[1],a=(i[2]||"").trim();if(r==="\u56FE\u7247"&&a)t.push({type:"image_url",image_url:{url:a}}),o=!0;else if(r==="\u6587\u4EF6"&&a){const[l="",u="",c="",d=""]=a.split("|").map(p=>p.trim());j(t,gt(l,u,c,d))}else if(r==="\u8BED\u97F3"&&a){const[l="",u="",c=""]=a.split("|").map(d=>d.trim());j(t,Tt({url:l,durationMs:Number(u),transcriptState:c||void 0}))}else if(r==="\u4E34\u65F6\u6587\u4EF6"&&a){const[l="",u="",c="",d=""]=a.split("|").map(p=>p.trim());j(t,us(l,u,c,d))}else j(t,i[0]);s=i.index+i[0].length,i=e.exec(n)}return t.length===0?{content:n,hasImages:!1}:(j(t,n.slice(s)),{content:t,hasImages:o})}function ms(n,e){let t=!1;const o=[e.directMessages,e.groupMessages];for(const s of o)if(Array.isArray(s))for(const i of s){if(!M(i))continue;const r=R(i.content);if(!r)continue;const a=R(i.senderName);j(n,a?`Message from ${a}:`:"Message:");const l=Pe(r);Array.isArray(l.content)?n.push(...l.content):j(n,l.content),t=t||l.hasImages}return t}function ps(n){for(const e of["directMessages","groupMessages","messages"]){const t=n[e];if(Array.isArray(t))for(const o of t){if(!M(o))continue;const s=o.content;typeof s!="string"||!s.trim()||(o.content=hs(s))}}}function hs(n){let e;try{e=JSON.parse(n)}catch{return n.replace(/\[(图片|文件)\s*:\s*([^\]\n]*?)\s*\]/gi,"").trim()||n}if(M(e)&&"attachments"in e){const t={...e};return t.attachments=[],JSON.stringify(t)}return n}function fs(n){let e;try{e=JSON.parse(n)}catch{return}if(!M(e))return;const t=[];let o=ms(t,e);const s=R(e.text)||"",i=Array.isArray(e.attachments)?e.attachments:[];j(t,s);const r=M(e.voice)?e.voice:void 0;r&&j(t,Tt(r));for(const a of i){if(!M(a))continue;const l=a;if(String(l.type??l.kind??"").toLowerCase()==="image"){const d=cs(l);d?(t.push({type:"image_url",image_url:{url:d}}),o=!0):R(l.base64Data??l.base64??l.data)&&j(t,`[Image attachment omitted: ${R(l.name)||"unnamed"} exceeds the ${se} byte inline limit]`);continue}const c=R(l.url??l.serverUrl)||"";j(t,gt(R(l.name)||"",c,R(l.mediaType??l.mimeType)||"",R(l.size)||""))}return t.length===0?{content:n,hasImages:!1}:{content:t,hasImages:o}}function Pe(n){return fs(n)??ds(n)}async function yt(n){if(!Array.isArray(n))return n;const e=[];for(const t of n){if(t.type==="text"){e.push(t);continue}e.push({type:"image_url",image_url:{url:await ls(t.image_url.url)}})}return e}function gs(n){return typeof n=="string"?n:Array.isArray(n)?n.map(e=>e.type==="text"?e.text:"[Image]").join(" ").trim():""}function Ts(n,e){const t=n.permissions??e.permissions??{},o=n.permissions?[]:e.allowedTools??[],s=n.permissions?[]:e.deniedTools??[];return{mode:t.mode??"default",allow:[...t.allow??[],...o].map(i=>i.trim()).filter(Boolean),deny:[...t.deny??[],...s].map(i=>i.trim()).filter(Boolean)}}function ys(n,e){return n==="*"?!0:n.endsWith("*")?e.startsWith(n.slice(0,-1)):n===e}function Cs(n){return n.kind==="builtin"?[n.exposedName,n.toolName,`builtin.${n.toolName}`]:[n.exposedName,n.toolName,`${n.serverName}.${n.toolName}`,`mcp.${n.serverName}.${n.toolName}`]}function Ct(n,e){return Cs(e).some(t=>ys(n,t))}function At(n,e,t){if(e.length>0&&!e.some(o=>Ct(o,n)))throw new Error(t)}function _t(n,e,t){if(e.mode!=="bypassPermissions"){if(e.deny.some(o=>Ct(o,n)))throw new Error(`ACode tool denied by permission rule: ${n.exposedName}`);At(n,e.allow,`ACode tool is not in allowed permission rules: ${n.exposedName}`),At(n,t??[],`ACode slash command does not allow tool: ${n.exposedName}`)}}function As(n,e,t){try{return _t(n,e,t),!0}catch{return!1}}function ke(n){const e=n.replace(/\/+$/g,"");return/\/chat\/completions$/i.test(e)?e:`${e}/chat/completions`}function _s(n){try{const e=new URL(n);e.search="",e.hash="";const t=new URL(ke(e.toString()));return`${t.origin}${t.pathname}`}catch{return ke(n).replace(/([?&](?:api[_-]?key|token|authorization)=)[^&]+/gi,"$1[redacted]")}}function bs(n){const e=[...n].reverse().find(o=>o.role==="user"),t=gs(e?.content??null).trim();if(t)return t.length>300?`${t.slice(0,300)}...`:t}function ws(n){try{const e=JSON.parse(n);return ye(e)?e:{}}catch{return{}}}function ks(n,e,t){if(new Set([Ft,"await_complete"]).has(n.toolName))return 0;if(n.toolName!=="Bash")return t;const s=e.timeout_ms??e.timeoutMs,i=typeof s=="number"?s:typeof s=="string"?Number(s):NaN;return!Number.isFinite(i)||i<=0?Math.max(t,Fo):Math.min(Math.floor(i),10*6e4)+2e3}function Ms(n,e){const t=n.trim();return`ACode \u5DF2\u63A5\u6536\u4EFB\u52A1\u3002\u5F53\u524D\u5DF2\u52A0\u8F7D ${e.configMcpCount} \u4E2A MCP \u914D\u7F6E\u3001${e.exposedTools.length} \u4E2A MCP Tool \u4E0E ${e.skills.length} \u4E2A Skill\u3002${t?`\u8F93\u5165\u6458\u8981\uFF1A${t.slice(0,200)}`:""}`}function H(n){if(!M(n))return String(n??"");const e=n.content;if(Array.isArray(e)){const t=e.map(o=>M(o)?typeof o.text=="string"?o.text:JSON.stringify(o):"").filter(Boolean);if(t.length>0)return t.join(`
3
+ `)}return JSON.stringify(n)}function pe(n){return n instanceof Error?n.message:String(n)}function Ss(n){const e={orphanToolMessages:0,repairedToolCalls:0,downgradedAssistants:0,relocatedInterruptions:0,reorderedToolResults:0};if(n.length===0)return e;const t=(c,d)=>{const p=typeof c.content=="string"?c.content:JSON.stringify(c.content??"");c.role="user",delete c.tool_call_id,c.content=`[\u7CFB\u7EDF\u63D0\u793A] \u4EE5\u4E0B\u4E3A\u4E00\u6B21\u5DE5\u5177\u6267\u884C\u7684\u7ED3\u679C\uFF08tool_call_id=${d}\uFF09\uFF0C\u5176\u5BF9\u5E94\u7684\u5DE5\u5177\u8C03\u7528\u4E0A\u4E0B\u6587\u5DF2\u4E0D\u5728\u4F1A\u8BDD\u4E2D\uFF0C\u4EC5\u4F9B\u53C2\u8003\uFF1A
4
+ ${p}`,e.orphanToolMessages+=1},o=c=>{const d=new Map;for(const C of n)if(C.role==="assistant"&&Array.isArray(C.tool_calls))for(const y of C.tool_calls){const m=typeof y?.id=="string"?y.id:"";m&&!d.has(m)&&d.set(m,C)}const p=new Set;for(const C of n){if(C.role==="assistant"&&Array.isArray(C.tool_calls)){for(const f of C.tool_calls){const g=typeof f?.id=="string"?f.id:"";g&&p.add(g)}continue}if(C.role!=="tool")continue;const y=typeof C.tool_call_id=="string"?C.tool_call_id.trim():"";if(!y){t(C,"(\u7F3A\u5931)");continue}if(p.has(y))continue;const m=d.get(y);if(m){c.push({message:C,id:y,assistant:m});continue}t(C,y)}},s=c=>{if(c.length!==0){for(const d of c){const p=n.indexOf(d.message);p>=0&&n.splice(p,1)}for(const d of c){const p=n.indexOf(d.assistant);if(p<0){t(d.message,d.id);continue}let C=p+1;for(;C<n.length&&n[C].role==="tool";)C+=1;n.splice(C,0,d.message),e.reorderedToolResults+=1}}},i=[];o(i),s(i);const r=()=>{const c=new Set;for(const d of n)d.role==="tool"&&d.tool_call_id&&c.add(d.tool_call_id);return c};let a=r();const l="\uFF08\u8BE5\u5DE5\u5177\u8C03\u7528\u7ED3\u679C\u7F3A\u5931\uFF1A\u6240\u5C5E\u8F6E\u6B21\u88AB\u4E2D\u65AD\u6216\u4E0A\u4E0B\u6587\u538B\u7F29\u65F6\u5DF2\u79FB\u9664\uFF0C\u8BF7\u52FF\u57FA\u4E8E\u8BE5\u8C03\u7528\u7EE7\u7EED\u63A8\u65AD\uFF0C\u5FC5\u8981\u65F6\u91CD\u65B0\u8C03\u7528\u5DE5\u5177\u3002\uFF09";for(let c=0;c<n.length;c++){const d=n[c];if(d.role!=="assistant"||!Array.isArray(d.tool_calls))continue;const p=d.tool_calls.filter(f=>typeof f?.id=="string"&&f.id.trim().length>0);if(p.length!==d.tool_calls.length){if(e.downgradedAssistants+=1,p.length===0){delete d.tool_calls,(d.content===null||d.content===void 0)&&(d.content="");continue}d.tool_calls=p}const C=d.tool_calls.map(f=>f?.id).filter(f=>typeof f=="string"&&f.length>0&&!a.has(f));if(C.length===0)continue;let y=-1;for(let f=c+1;f<n.length;f++){if(n[f].role==="tool"){y=f+1;continue}break}if(y>c){const f=C.map(g=>({role:"tool",tool_call_id:g,content:l}));n.splice(y,0,...f),c+=f.length,e.repairedToolCalls+=C.length,a=r();continue}if(c===n.length-1){for(const f of C)n.push({role:"tool",tool_call_id:f,content:l});e.repairedToolCalls+=C.length,a=r();continue}const m=new Set(d.tool_calls.map(f=>f?.id).filter(f=>typeof f=="string"&&f.length>0));delete d.tool_calls,(d.content===null||d.content===void 0)&&(d.content="");for(const f of n)if(f.role==="tool"&&f.tool_call_id&&m.has(f.tool_call_id)){const g=typeof f.content=="string"?f.content:JSON.stringify(f.content??""),T=f.tool_call_id;f.role="user",delete f.tool_call_id,f.content=`[\u7CFB\u7EDF\u63D0\u793A] \u4EE5\u4E0B\u4E3A\u4E00\u6B21\u5DE5\u5177\u6267\u884C\u7684\u7ED3\u679C\uFF08tool_call_id=${T}\uFF09\uFF0C\u5176\u5BF9\u5E94\u7684\u5DE5\u5177\u8C03\u7528\u4E0A\u4E0B\u6587\u5DF2\u4E0D\u5728\u4F1A\u8BDD\u4E2D\uFF0C\u4EC5\u4F9B\u53C2\u8003\uFF1A
5
+ ${g}`,e.orphanToolMessages+=1}a=r(),e.downgradedAssistants+=1}for(let c=0;c<n.length;c++){const d=n[c];if(d.role!=="assistant"||!Array.isArray(d.tool_calls))continue;const p=new Set(d.tool_calls.map(g=>g?.id).filter(g=>typeof g=="string"&&g.length>0));if(p.size===0)continue;const C=g=>g.role==="tool"&&typeof g.tool_call_id=="string"&&p.has(g.tool_call_id),y=[];for(let g=c+1;g<n.length;g++){const T=n[g];if(C(T))continue;if(T.role==="tool")break;let _=!1;for(let b=g+1;b<n.length;b++)if(C(n[b])){_=!0;break}if(!_)break;y.push(T)}if(y.length===0)continue;const m=n.filter(g=>!y.includes(g));let f=-1;for(let g=0;g<m.length;g++)C(m[g])&&(f=g);f<0||(m.splice(f+1,0,...y),n.length=0,n.push(...m),e.relocatedInterruptions+=y.length)}const u=[];return o(u),s(u),e}const bt={truncatedCount:0,strategy:"none",prunedToolMessages:0,summarizedMessages:0,freedTokens:0};async function vs(n,e,t,o,s,i){if(Ge(n)<=e)return bt;const a=Te(n),l=await fe(n,t,o,{llmSummarizer:s,...a.length>0?{prefixMessages:a}:{}});if(l.strategy!=="none")return l.summarizedMessages>0&&i&&await i(),{truncatedCount:l.prunedToolMessages+l.summarizedMessages,strategy:l.strategy,prunedToolMessages:l.prunedToolMessages,summarizedMessages:l.summarizedMessages,freedTokens:l.freedTokens};const u=await Se(n,{llmSummarizer:s,contextLimit:t,...a.length>0?{prefixMessages:a}:{}});return u>0&&i&&await i(),{truncatedCount:u,strategy:u>0?"summarize":"none",prunedToolMessages:0,summarizedMessages:u,freedTokens:0}}function $s(n){return ve(n)}function xs(n){const e=pe(n).toLowerCase();return $s(n)?!1:e.includes("fetch failed")||e.includes("timed out")||e.includes("timeout")||e.includes("econnreset")||e.includes("econnrefused")||e.includes("etimedout")||e.includes("enotfound")||e.includes("socket hang up")||e.includes("network error")||/\b(408|429|500|502|503|504|520|521|522|523|524)\b/.test(e)}function Rs(n){if(typeof n!="object"||n===null)return!1;const e=Reflect.get(n,"code"),t=pe(n).toLowerCase();return e===-32001||t.includes("request timed out")}function Es(n){if(typeof n=="object"&&n!==null){const e=Reflect.get(n,"code");if(typeof e=="string"&&e)return e;const t=Reflect.get(n,"name");if(typeof t=="string"&&t)return t}return"tool_error"}function wt(n,e,t){return JSON.stringify({ok:!1,tool:n.exposedName,error:{type:Es(e),message:pe(e)},...t?{file_snapshot:{path:t.path,bytes:t.bytes,content:t.content}}:{}})}function Is(n){const e=JSON.stringify(n);return e.length>500?`${e.slice(0,500)}\u2026`:e}function kt(n){const e=[n?.reasoning_content,n?.reasoning_text,n?.reasoning];for(const t of e){if(typeof t=="string"&&t)return t;if(M(t)){const o=t.text??t.content;if(typeof o=="string"&&o)return o}}return""}function Mt(n){return n.length===0?"":["Skills are available for this session.","Use the `skill` tool to load specialized skill instructions when a user task matches one of the available skills listed in the tool description.","Do not attempt to follow skill instructions from memory \u2014 always invoke the `skill` tool first to load the full content."].join(" ")}function St(n){return n.length===0?"":["Available slash commands:",...n.map(e=>`- /${e.name}${e.description?`: ${e.description}`:""}`),"When the user invokes a slash command, ACode expands it before model execution."].join(`
6
+ `)}function Ns(n){if(!n||typeof n!="object")return"";const e=n,t=[],o=e.displayName,s=e.roleName,i=e.instanceName,r=e.projectId,a=e.workspacePath,l=e.runtimeMode,u=e.describe;return typeof o=="string"&&o.trim()&&t.push(`Display Name: ${o.trim()}`),typeof s=="string"&&s.trim()&&t.push(`Role: ${s.trim()}`),typeof i=="string"&&i.trim()&&t.push(`Instance: ${i.trim()}`),typeof r=="string"&&r.trim()&&t.push(`Project: ${r.trim()}`),typeof a=="string"&&a.trim()&&t.push(`Workspace: ${a.trim()}`),typeof l=="string"&&l.trim()&&t.push(`Runtime Mode: ${l.trim()}`),typeof u=="string"&&u.trim()&&t.push(`Description: ${u.trim()}`),t.length===0?"":["[User Profile]",...t].join(`
7
+ `)}function vt(n){return n.map(e=>({type:"function",function:{name:e.exposedName,description:e.description||e.toolName,parameters:e.inputSchema}}))}function Ps(n,e){return`${n}__${e}`.replace(/[^a-zA-Z0-9_-]/g,"_").slice(0,64)||"mcp_tool"}function Os(n){const e={"Content-Type":"application/json"};return n.apiKey&&(e.Authorization=`Bearer ${n.apiKey}`),e}function Ls(n){return Object.fromEntries(Object.entries(n).map(([e,t])=>[e,Bs(e)?Ds(t):t]))}function Bs(n){const e=n.trim().toLowerCase();return e==="authorization"||e==="api-key"||e==="x-api-key"||e==="openai-api-key"}function Ds(n){return n.trim().toLowerCase().startsWith("bearer ")?"Bearer ***":"***"}function $t(n){return n.split(/\r?\n/).filter(e=>e.startsWith("data:")).map(e=>e.slice(5).trim()).filter(Boolean)}function Oe(n){if(!M(n))return null;const e=n.error;if(M(e)){const t=typeof e.message=="string"?e.message:"",o=e.code??e.status??e.type,s=o==null?"":String(o);return t||s?[s,t].filter(Boolean).join(" "):null}if(typeof e=="string"&&e)return e;if(n.type==="error"||n.object==="error"){const t=typeof n.message=="string"?n.message:"",o=n.code??n.status,s=o==null?"":String(o);if(t||s)return[s,t].filter(Boolean).join(" ")}return null}const Us=/role 'tool'|tool calls and tool results|tool_call_sequence|\b11148\b/i;let xt=0,he="";function Le(n,e,t){if(!Us.test(t))return null;try{const o=new Map,s=new Map;n.forEach((m,f)=>{if(m.role==="assistant"&&Array.isArray(m.tool_calls))for(const g of m.tool_calls){const T=typeof g?.id=="string"?g.id.trim():"";T&&!o.has(T)&&o.set(T,f)}else if(m.role==="tool"){const g=typeof m.tool_call_id=="string"?m.tool_call_id.trim():"";g&&!s.has(g)&&s.set(g,f)}});const i=[];n.forEach((m,f)=>{if(m.role==="tool"){const g=typeof m.tool_call_id=="string"?m.tool_call_id.trim():"",T=g?o.get(g):void 0;(g===""||T===void 0||T>f)&&i.push(f)}else if(m.role==="assistant"&&Array.isArray(m.tool_calls))for(const g of m.tool_calls){const T=typeof g?.id=="string"?g.id.trim():"";if(T===""||!s.has(T)){i.push(f);break}}});const r=m=>` [\u5DE5\u5177\u5E8F\u5217\u8BC1\u636E] \u53EF\u7591\u6D88\u606F ${i.length}/${n.length} \u6761\uFF08${m?`\u5DF2\u5199\u5165 ${m}`:"\u843D\u76D8\u5931\u8D25"}\uFF09`,a=Date.now();if(a-xt<1e4&&he)return r(he);xt=a;const l=m=>({role:m.role,tool_call_id:m.tool_call_id,tool_calls:Array.isArray(m.tool_calls)?m.tool_calls.map(f=>f?.id??null):void 0,contentPreview:typeof m.content=="string"?m.content.slice(0,300):m.content===null?null:JSON.stringify(m.content).slice(0,300)}),u=`acode-tool-seq-${new Date(a).toISOString().replace(/[:.]/g,"-")}.json`,c=String(process.env.AWS_TEST_HOME||"").trim()||String(process.env.AWS_RUNTIME_HOME_DIR||"").trim(),d=String(process.env.AWS_RUNTIME_ENV||"").trim().toLowerCase()==="development",p=c||(d?z.resolve(process.cwd(),"..",".dev-home"):z.dirname(Yt())),C=z.join(p,".aws-bridge","log"),y={timestamp:new Date(a).toISOString(),status:e,errorBody:t.slice(0,4e3),suspectIndexes:i,messages:n.map((m,f)=>({index:f,role:m.role,tool_call_id:m.tool_call_id,tool_calls:Array.isArray(m.tool_calls)?m.tool_calls.map(g=>g?.id??null):void 0})),suspectWindows:i.map(m=>{const f=Math.max(0,m-6),g=Math.min(n.length,m+7);return{center:m,range:[f,g],messages:n.slice(f,g).map((T,_)=>({index:f+_,...l(T)}))}})};return he=`.aws-bridge/log/${u}`,D.promises.mkdir(C,{recursive:!0}).then(()=>D.promises.writeFile(z.join(C,u),JSON.stringify(y,null,2),"utf-8")).then(()=>D.promises.readdir(C)).then(m=>{const f=m.filter(T=>T.startsWith("acode-tool-seq-")).sort(),g=f.length-20;return g<=0?null:Promise.all(f.slice(0,g).map(T=>D.promises.unlink(z.join(C,T)).catch(()=>{})))}).catch(()=>{he=""}),r(he)}catch{return null}}function Rt(n){const e=new Set,t=Date.now();return n.map((o,s)=>{const i=typeof o?.id=="string"?o.id.trim():"";if(i&&!e.has(i))return e.add(i),o;let r=`call-${t}-${s}`,a=1;for(;e.has(r);)r=`call-${t}-${s}-${a}`,a+=1;return e.add(r),{...o,id:r}})}function qs(n,e){const t=Number.isFinite(e.index)?Number(e.index):0,o=n.get(t)??{id:e.id||`call-${t}`,type:"function",function:{name:"",arguments:""}};e.id&&(o.id=e.id),e.function?.name&&(o.function.name+=e.function.name),e.function?.arguments&&(o.function.arguments+=e.function.arguments),n.set(t,o)}function Fs(n){return Rt([...n.entries()].sort(([e],[t])=>e-t).map(([,e])=>e).filter(e=>e.function.name.trim().length>0))}function zs(){const n=process.env.ACODE_ABORT_FORCE_SETTLE_GRACE_MS;if(n===void 0||n.trim()==="")return 6e4;const e=Number(n.trim());return Number.isFinite(e)&&e>=0?Math.floor(e):6e4}class te extends Et{hasActiveBlockingToolCall(){return this.activeBlockingToolCalls>0}static isLongBlockingMcpToolName(e){return Ao(e)}constructor(e){super(),this.config=e,this.initialConversation=[],this.mcpStderrBuffers=new Map,this.state={started:!1,terminated:!1,configMcpCount:0,skills:[],provider:{model:"acode-default",stream:!1,requestTimeoutMs:st,requestTotalTimeoutMs:nt,requestRetryCount:at,requestFirstByteTimeoutMs:it,requestStreamIdleTimeoutMs:rt,mcpToolTimeoutMs:Ae,mcpPollingToolTimeoutMs:lt,supportsImageInput:!1},permissions:{mode:"default",allow:[],deny:[]},mcpConnections:[],ownsMcpConnections:!0,exposedTools:[],commands:[],commandRegistry:new je([]),conversation:[],accumulatedInputTokens:0,accumulatedOutputTokens:0,accumulatedCacheHitTokens:0,accumulatedCacheMissTokens:0,toolPermissionPolicy:{...Ue}},this.abortController=null,this.exposedToolsInitialized=!1,this.recoveredToolNames=new Set,this.readFileStateTracker=new qt,this.pendingMemorySubAgents=new Map,this.memoryDelegateCooldownUntil=new Map,this.toolGroupManager=null,this.pluginGroupStates=new Map,this.submitQueue=Promise.resolve(),this.activeTurnToken=null,this.forceSettleWaiters=new Map,this.abortForceSettleTimer=null,this.activeTurn=!1,this.activeBlockingToolCalls=0,this.forceMessagePending=!1,this.compactRequested=!1,this.instructionsDirty=!1,this.turnPromptPushed=!1,this.abortRequested=!1,this.toolSettleSlots=new Map,this.toolSettleSeq=0,this.toolResourceLock=Mo(),this.toolConcurrencyScheduler=new So,this.toolReadOnlyLimiter=null,this.toolBashLimiter=null,this.toolConcurrencyEnabled=!0,this.pendingAwaitedSubIds=new Set,this.pendingAwaitedBgTaskIds=new Set,this.sessionCompleteEmitted=!1,this.contextVersion=0,this.stopWaiters=new Set,this.compactionDebugTimer=null,this.skillTool=null,this.skillWatchers=[],this.skillRefreshTimer=null,this.questionWaiters=new Map,this.permissionWaiters=new Map,this.hookBus=new Co({sessionId:e.sessionId,onError:(i,r)=>{this.emitAcodeEvent("error",{message:`ACode hook failed: ${i.name}: ${r instanceof Error?r.message:String(r)}`})}});for(const i of e.hooks??[])this.hookBus.register(i);e.toolPermissionPolicy&&(this.state.toolPermissionPolicy={...Ue,...e.toolPermissionPolicy});const t=e.toolConcurrency;this.toolConcurrencyEnabled=t?.enabled!==!1;const o=t?.maxReadOnly??8;this.toolReadOnlyLimiter=new et(o);const s=t?.maxBash??0;this.toolBashLimiter=s>0?new et(s):null}getAvailableTools(){return this.state.exposedTools.map(e=>e.exposedName)}emitAcodeEvent(e,t){const o={type:e,sessionId:this.config.sessionId,timestamp:Po(),data:t};this.emit("event",o)}emitCompactionPhase(e,t,o,s,i){this.emitAcodeEvent("context_compaction",{action:"phase",compactionId:e,parentId:e,phase:t,phaseLabel:o,phaseDetail:s,...i?{trigger:i}:{}})}handleCompactionPhase(e,t){switch(t.phase){case"prune_start":this.emitCompactionPhase(e,"prune","\u9636\u6BB51: \u88C1\u526A\u5DE5\u5177\u8F93\u51FA",`\u6B63\u5728\u88C1\u526A ${t.messageCount??0} \u6761\u6D88\u606F\u4E2D\u7684\u5DE5\u5177\u8F93\u51FA...`);break;case"prune_end":this.emitCompactionPhase(e,"prune_done","\u9636\u6BB51: \u88C1\u526A\u5DE5\u5177\u8F93\u51FA",`\u88C1\u526A\u4E86 ${t.prunedCount??0} \u6761\u5DE5\u5177\u8F93\u51FA, \u91CA\u653E ${t.freedTokens??0} tokens`);break;case"summarize_start":this.emitCompactionPhase(e,"summarize","\u9636\u6BB52: \u6458\u8981\u5316\u5BF9\u8BDD",`\u6B63\u5728\u6458\u8981 ${t.messageCount??0} \u6761\u65E9\u671F\u5BF9\u8BDD\uFF08\u4FDD\u771F\u7EA7\u522B L${t.level??1}\uFF09...`);break;case"summarize_end":this.emitCompactionPhase(e,"summarize_done","\u9636\u6BB52: \u6458\u8981\u5316\u5BF9\u8BDD",`\u6458\u8981\u5316\u4E86 ${t.summarizedCount??0} \u6761\u6D88\u606F${t.usedLLM?" (LLM \u6458\u8981)":" (\u89C4\u5219\u6458\u8981)"}`);break;case"degrade":this.emitCompactionPhase(e,`degrade_l${t.level??2}`,`\u964D\u7EA7\u5230 L${t.level??2}`,t.reason??"\u4FDD\u771F\u7EA7\u522B\u4E0B\u964D");break}}runMicrocompactPass(e,t){const s=this.state.provider.microcompact;if(!s||s.enabled!==!0)return;const i=go(this.state.conversation,s,{autoCompactThreshold:t});if(i.reason!=="applied"){h(`[ACodeRuntime] \u{1F9F9} Microcompact skipped: reason=${i.reason} estimated=${i.estimatedTokenCount} threshold=${i.thresholdTokens}`);return}h(`[ACodeRuntime] \u{1F9F9} Microcompact applied: cleared=${i.clearedCount} saved=${i.tokensSaved} pre=${i.preTokenCount} post=${i.postTokenCount}`),this.state.accumulatedInputTokens=0,this.state.accumulatedOutputTokens=0}async runCompactionPass(e){const{contextLimit:t,maxOutput:o,effectiveUsed:s,trigger:i,force:r}=e,a=X(this.state.conversation),l=`compaction-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;this.emitAcodeEvent("context_compaction",{action:"start",compactionId:l,sizeKB:a,estimatedTokens:s,actualInputTokens:this.state.accumulatedInputTokens,actualOutputTokens:this.state.accumulatedOutputTokens,messageCount:this.state.conversation.length,model:this.state.provider.model,trigger:i}),this.emitCompactionPhase(l,"detect",e.detectLabel,e.detectDetail);const u=We({contextLimit:t,maxOutput:o,...this.state.provider.inputLimit?{inputLimit:this.state.provider.inputLimit}:{},toolsTokens:K(this.state.exposedTools)});let c;const d=Te(this.state.conversation);try{c=await fe(this.state.conversation,t,o,{llmSummarizer:y=>this.summarizeConversationWithLLM(y),onPhase:y=>this.handleCompactionPhase(l,y),actualUsedTokens:s,force:r,budget:u,allowRuleFallback:!1,retryPolicy:{maxAttempts:Math.max(1,this.state.provider.requestRetryCount??3)},...d.length>0?{prefixMessages:d}:{}})}catch(y){if(!(y instanceof Je))throw y;this.emitAcodeEvent("warning",{message:`LLM \u6458\u8981\u4E0D\u53EF\u7528\uFF0C\u5DF2\u4F7F\u7528\u89C4\u5219\u6458\u8981\u515C\u5E95\uFF1A${y.message}`}),c=await fe(this.state.conversation,t,o,{onPhase:m=>this.handleCompactionPhase(l,m),actualUsedTokens:s,force:r,budget:u})}this.state.accumulatedInputTokens=0,this.state.accumulatedOutputTokens=0,c.summarizedMessages>0&&await this.rebuildRuntimeResourcesMessage(),this.rebuildRuntimeInstructionsMessage();const p=X(this.state.conversation),C=Me(this.state.conversation,K(this.state.exposedTools));return this.emitAcodeEvent("context_compaction",{action:"end",compactionId:l,sizeBeforeKB:a,sizeAfterKB:p,freedKB:Math.round((a-p)*10)/10,strategy:c.strategy,freedTokens:c.freedTokens,tokensBefore:c.tokensBefore,tokensAfter:c.tokensAfter,contextTokensAfter:C,prunedToolMessages:c.prunedToolMessages,summarizedMessages:c.summarizedMessages,messageCountBefore:c.messageCountBefore,messageCountAfter:c.messageCountAfter,level:c.level,...c.levelLabel?{levelLabel:c.levelLabel}:{},...c.ladderStep?{ladderStep:c.ladderStep}:{},...c.summaryChunks?{summaryChunks:c.summaryChunks}:{},...c.downsampleCount!==void 0?{downsampleCount:c.downsampleCount}:{},...c.droppedMessages!==void 0?{droppedMessages:c.droppedMessages}:{},...c.noSummary!==void 0?{noSummary:c.noSummary}:{},...c.reachedTarget!==void 0?{reachedTarget:c.reachedTarget}:{}}),c}compactContext(){if(!this.state.started||this.state.terminated)throw new Error("ACode runtime is not active");return this.compactRequested=!0,h("[ACodeRuntime] \u{1F5DC}\uFE0F Manual compaction requested (\u5148\u884C\u538B\u7F29): unified high-fidelity cascade"),{requested:!0}}async start(){this.emitAcodeEvent("startup_phase",{phase:"loading_config"});const e=await To(this.config.configPath);this.emitAcodeEvent("startup_phase",{phase:"loading_skills"});const{skills:t,skillGroups:o,watchedDirs:s}=await this.loadAllSkills(),i=ss(this.config,e);h(`[ACodeRuntime] \u2605\u2605\u2605 DEBUG \u2605\u2605\u2605 resolveProviderConfig \u7ED3\u679C: config.model=${this.config.model??"(undefined)"}, resolvedModel=${i.model}, baseURL=${i.baseURL??"(none)"}, apiKey=${i.apiKey?"[set]":"(none)"}, configPath=${this.config.configPath??"(none)"}`);const r=Ts(this.config,e),a=this.config.sharedMcpConnections?this.filterSharedMcpConnectionsForSubAgent(this.config.sharedMcpConnections):await this.connectMcpServers(e.mcpServers??{},i.mcpToolTimeoutMs),l=!this.config.sharedMcpConnections;this.emitAcodeEvent("startup_phase",{phase:"fetching_profile"});const u=await this.fetchProfilePrompt(a),c=this.config.agentId||"unknown";Ht(c),le.reconcileOrphans(c);const d=Dt(this.config.workingDirectory,c,this.config.onFileChange,{manager:le,emitCompleted:A=>{this.emitAcodeEvent("background_command_completed",A)}},this.createToolPermissionController(),{tracker:this.readFileStateTracker,enabled:this.config.enableStaleFileGuard!==!1}),p=zt(this.buildAskUserQuestionDeps(),()=>this.contextVersion),C=jt(t);this.skillTool=C;const y=Wt(c),m=Gt(c),f=this.config.subAgentManager?Jt(this.buildSubAgentToolDeps(this.config.subAgentManager)):[],g=Kt(this.buildAwaitCompleteDeps()),T=this.config.terminalManager?Vt(c,{terminalManager:this.config.terminalManager}):null,_=new Map;this.pluginGroupStates=_;const b=new Xt({stateOf:A=>ze(A)?_.get(A)??"disabled":(this.config.capabilityState??(()=>"disabled"))(A)});b.register({key:"pencil",label:"\u8BBE\u8BA1\u753B\u5E03(pencil)",summary:"UI design editor",collapsible:!0}),b.register({key:"draw",label:"\u7ED8\u56FE",summary:"\u7ED8\u5236 draw.io \u6D41\u7A0B\u56FE/\u6CF3\u9053\u56FE",collapsible:!0}),b.register({key:"office",label:"Office \u6587\u4EF6",summary:"\u53EF\u8FDB\u884C\u67E5\u770B/\u521B\u5EFA\u548C\u590D\u6742\u7F16\u8F91 Word/PPT/Excel",collapsible:!0}),b.register({key:"launch",label:"\u542F\u52A8\u9879\u7BA1\u7406",summary:"\u7BA1\u7406\u9879\u76EE\u4E2D\u4E1A\u52A1\u7A0B\u5E8F\u7684\u8D77\u505C\uFF0C\u82E5\u540E\u9762\u9700\u8981\u542F\u52A8\u9879\u76EE\u5E94\u4F7F\u7528\u6B64\u5DE5\u5177",collapsible:!0}),b.register({key:"hire",label:"\u62DB\u8058\u5DE5\u5177",summary:"\u62DB\u8058\u65B0\u7684\u540C\u4E8B Agent",collapsible:!0}),b.register({key:"browser",label:"\u6D4F\u89C8\u5668\u64CD\u4F5C",summary:"\u542F\u52A8\u6D4F\u89C8\u5668\u4F1A\u8BDD\u3001\u5BFC\u822A\u3001\u622A\u56FE\u4E0E\u9875\u9762\u4EA4\u4E92",collapsible:!0}),b.register({key:"desktop",label:"\u684C\u9762\u64CD\u4F5C",summary:"\u622A\u5C4F\u3001\u9F20\u6807\u952E\u76D8\u63A7\u5236\u4E0E UI \u81EA\u52A8\u5316",collapsible:!1}),oo(b),this.toolGroupManager=b;for(const A of a){const O=A.spec??e.mcpServers?.[A.serverName];O&&this.registerMcpCollapsedGroup(A.serverName,O,A)}for(const A of a)this.registerToolGroupsFromMcp(A);if(this.config.pluginBridge)try{const A=await this.config.pluginBridge.listPlugins();this.applyPluginGroups(A,_,b)}catch(A){h(`[ACodeRuntime] \u63D2\u4EF6\u7EC4\u6CE8\u518C\u5931\u8D25\uFF08\u5FFD\u7565\uFF09: ${A instanceof Error?A.message:String(A)}`)}const S=Zt({toolGroupManager:b,getAllTools:()=>this.state.exposedTools,capabilityToolRelay:this.config.capabilityToolRelay,pluginBridge:this.config.pluginBridge}),k=eo({toolGroupManager:b,pluginBridge:this.config.pluginBridge,capabilityToolRelay:this.config.capabilityToolRelay,findTool:A=>{const O=this.state.exposedTools.find(Be=>Be.exposedName===A||Be.toolName===A);if(!O)return;const ae=O.group??b.getGroupForExposedName(O.exposedName);return{kind:O.kind,group:ae,toolName:O.toolName}},dispatchTool:(A,O,ae)=>this.executeSingleToolByName(A,O,ae)}),$=[...d,p,C,y,m,...f,g,...T?[T]:[],S,k,...a.flatMap(A=>A.tools),...Ze(this.config.extraBuiltInTools??[],this.config.agentId??"")];if(this.config.subAgentAllowedTools&&this.config.subAgentAllowedTools.length>0){const A=Ze(this.config.subAgentSuiteTools??[],this.config.agentId??""),O=ge($,A);$.length=0,$.push(...O)}let v=$;const B=this.config.subAgentAllowedTools;B&&B.length>0&&(v=v.filter(A=>Xe(A,B)));const I=this.resolveCommandDirs(e);let L=[...I,...this.discoverPluginCommandDirs()];if(this.config.pluginBridge?.getCommandDirs)try{const A=await this.config.pluginBridge.getCommandDirs();A.length>0&&(L=[...L,...A])}catch(A){h(`[ACodeRuntime] \u63D2\u4EF6\u547D\u4EE4\u76EE\u5F55\u83B7\u53D6\u5931\u8D25\uFF08\u5FFD\u7565\uFF09: ${A instanceof Error?A.message:String(A)}`)}L=[...new Set(L)],this.emitAcodeEvent("startup_phase",{phase:"loading_commands"});const q=await so(L),re=new je(q),oe=Mt(t),w=St(q),x=b.buildCapabilityPrompt(),W=this.config.pluginBridge?["","## \u63D2\u4EF6\u7CFB\u7EDF","\u5DF2\u5B89\u88C5\u63D2\u4EF6\u4EE5\u6536\u7EB3\u7EC4\u5F62\u5F0F\u5217\u51FA\uFF08\u89C1\u4E0A\u65B9\u300C\u53EF\u7528\u80FD\u529B\u300D\u4E2D\u7684 plugin:{\u63D2\u4EF6\u540D} \u6761\u76EE\uFF09\u3002",'\u9700\u8981\u67D0\u63D2\u4EF6\u7684\u5DE5\u5177\u65F6\uFF0C\u5148 expand_tools({ group: "plugin:\u63D2\u4EF6\u540D" }) \u5C55\u5F00\uFF1B','\u5DE5\u5177\u5B9A\u4E49\uFF08\u542B\u53C2\u6570 schema\uFF09\u968F\u5C55\u5F00\u7ED3\u679C\u8FD4\u56DE\uFF0C\u518D\u7528 call_tool({ name: "\u63D2\u4EF6\u540D.\u5DE5\u5177\u540D", arguments: {...} }) \u8C03\u7528\u3002',"\u63D2\u4EF6\u4E8B\u4EF6\u4EE5 [plugin-event] \u6D88\u606F\u51FA\u73B0\uFF0C\u6D88\u606F\u6807\u660E\u6765\u6E90\u63D2\u4EF6\u4E0E\u4E8B\u4EF6\u540D\u5E76\u5E26 toolHints\uFF08\u5EFA\u8BAE\u8C03\u7528\u7684\u5DE5\u5177\uFF09\uFF0C\u6309\u63D0\u793A\u5C55\u5F00\u5E76\u5904\u7406\u3002","\u80FD\u529B\u7BA1\u7406\u5206\u5C5E\u4E24\u4E2A\u72EC\u7ACB\u6388\u6743\u7684\u5DE5\u5177\u7EC4\uFF1A","\u300C\u80FD\u529B\u5E02\u573A\u300D\u7EC4\u8D1F\u8D23\u5B89\u88C5/\u5378\u8F7D MCP / Skill / Plugin\uFF1Alist_ability_market \u6D4F\u89C8\uFF08\u8FD4\u56DE\u73AF\u5883\u53D8\u91CF\u5951\u7EA6 envSchema\uFF0CMCP \u9700\u636E\u6B64\u914D\u7F6E env\uFF0C\u654F\u611F\u503C\u5FC5\u987B\u7531\u7528\u6237\u63D0\u4F9B\uFF09\u3001install_ability_market_item \u5B89\u88C5\u3001uninstall_ability_market_item \u5378\u8F7D\uFF08kind=plugin \u5373\u5B89\u88C5/\u5378\u8F7D\u63D2\u4EF6\uFF09\u3002","\u300C\u80FD\u529B\u5F00\u53D1\u300D\u7EC4\u8D1F\u8D23\u81EA\u7814 MCP / \u63D2\u4EF6 / Skill \u5E76\u7BA1\u7406\u5DF2\u88C5\u63D2\u4EF6\uFF1A","\u7528 ability_dev_ide \u8BFB\u7F16\u5199\u89C4\u8303\uFF08action=guide\uFF0Ckind=plugin|mcp|skill\uFF09\u5E76\u5728\u81EA\u5DF1\u7684\u4F1A\u8BDD\u5DE5\u4F5C\u533A\u5185\u7F16\u5199\uFF1B","MCP/\u63D2\u4EF6\u7528 ability_dev_ide \u4E34\u65F6\u6302\u8F7D\u8C03\u8BD5\uFF08action=mount/unmount/list/logs\uFF1B\u4E0D\u6301\u4E45\u5316\u3001\u91CD\u542F\u5373\u5931\u6548\uFF0C\u6539\u4EE3\u7801\u81EA\u52A8\u91CD\u8F7D\uFF09\uFF0C","mount \u540E\u5DE5\u5177\u540D\u5F62\u5982 <server>__<tool>\uFF08\u53CC\u4E0B\u5212\u7EBF\uFF09\uFF0C\u7528 call_tool \u8C03\u7528\uFF1B","action=list \u67E5\u770B\u6302\u8F7D\u9879\u4E0E\u66B4\u9732\u7684\u5DE5\u5177\u540D\uFF0Caction=logs \u6392\u67E5\u5B50\u8FDB\u7A0B\u62A5\u9519\uFF0Caction=unmount \u6458\u9664\uFF1B","\u8C03\u8BD5\u901A\u8FC7\u540E\u7528 formal_ability \u8F6C\u6B63\uFF08\u7F3A\u7701 scope=global \u4EC5\u767B\u8BB0\u5168\u5C40\u914D\u7F6E\u6A21\u677F\u4E14\u521D\u59CB\u5316\u5173\u95ED\uFF0C\u9700\u7528\u6237\u5728\u9762\u677F\u5F00\u542F\u540E\u751F\u6548\uFF1Bscope=instance \u624D\u7ACB\u5373\u751F\u6548\uFF09\uFF1BSkill \u65E0\u8C03\u8BD5\u6001\uFF0C\u540C\u6837\u53EF\u7ECF formal_ability \u6216\u80FD\u529B\u5E02\u573A\u5B89\u88C5\u3002","\u5DF2\u5B89\u88C5\u63D2\u4EF6\u7684\u542F\u505C/\u91CD\u8F7D\u7531\u7528\u6237\u5728\u9762\u677F\u64CD\u4F5C\uFF1B","\u67E5\u770B\u81EA\u8EAB\u5168\u90E8\u80FD\u529B\uFF08MCP/Skill/Plugin \u542F\u505C\u4E0E\u6765\u6E90\u3001\u5DE5\u5177\u5F00\u5173\u3001\u8C03\u8BD5\u6302\u8F7D\uFF09\u7528 list_my_abilities\u3002","\u672A\u7ECF\u7528\u6237\u660E\u786E\u8981\u6C42\u4E0D\u8981\u5B89\u88C5\u6216\u5378\u8F7D\u63D2\u4EF6\u3002"].join(`
8
+ `):"",N=x+W,P=[qe,i.systemPrompt,oe,w,N].map(A=>A?.trim()).filter(A=>!!A).join(`
9
9
 
10
- `),J=C=>C?.trim()?[{role:"system",content:C.trim()}]:[],F=[this.config.rolePrompt,u].map(C=>C?.trim()).filter(C=>!!C).join(`
10
+ `),Q=A=>A?.trim()?[{role:"system",content:A.trim()}]:[],F=[this.config.rolePrompt,u].map(A=>A?.trim()).filter(A=>!!A).join(`
11
11
 
12
- `),V=[...J(this.config.globalPrompt),...J(F),...J(this.config.memory),...J(this.config.resumeContext),...x?[{role:"system",content:x}]:[],...J(zt())],X=V.map(C=>C.content).filter(Boolean).join(`
12
+ `),Z=[...Q(this.config.globalPrompt),...Q(F),...Q(this.config.memory),...Q(this.config.resumeContext),...P?[{role:"system",content:P}]:[],...Q(Qt())],ee=Z.map(A=>A.content).filter(Boolean).join(`
13
13
 
14
- `);this.initialConversation=ce(V),this.state={started:!0,terminated:!1,configMcpCount:Object.keys(e.mcpServers??{}).length,skills:t,provider:i,permissions:r,mcpConnections:a,ownsMcpConnections:l,exposedTools:M,commands:U,commandRegistry:re,conversation:ce(V),accumulatedInputTokens:0,accumulatedOutputTokens:0,accumulatedCacheHitTokens:0,accumulatedCacheMissTokens:0,toolPermissionPolicy:this.state.toolPermissionPolicy},this.exposedToolsInitialized=!0,this.emitAcodeEvent("startup_phase",{phase:"session_start_hook"}),await this.hookBus.dispatch("SessionStart",{workingDirectory:this.config.workingDirectory,model:i.model,commandCount:U.length});const K=Ae(i);this.emitAcodeEvent("session_started",{workingDirectory:this.config.workingDirectory,model:i.model,commandCount:U.length,estimatedContextTokens:zo(X,M),contextLimit:K.contextLimit,maxOutput:K.maxOutput,...K.inputLimit!==void 0?{inputLimit:K.inputLimit}:{},compactionThreshold:K.threshold}),this.emitAcodeEvent("mcp_status",{configPath:this.config.configPath,installedCount:this.state.configMcpCount,servers:Object.keys(e.mcpServers??{}),connectedCount:a.length,builtInToolCount:d.length,toolCount:M.length,permissionMode:r.mode,allowedToolRules:r.allow,deniedToolRules:r.deny,tools:M.map(C=>({name:C.exposedName,source:C.kind==="mcp"?`${C.serverName}.${C.toolName}`:`builtin.${C.toolName}`,description:C.description||""}))}),this.emitAcodeEvent("skill_status",{skillsDir:this.config.skillsDir,installedCount:t.length,skills:t.map(C=>({name:C.name,description:C.description,directory:C.directory})),skillGroups:o.map(C=>({dir:C.dir,exists:C.exists,skills:C.skills.map(R=>({name:R.name,description:R.description,directory:R.directory}))}))}),this.emitAcodeEvent("command_status",{action:"commands_loaded",installedCommandCount:U.length,commandDirs:E,commands:U.map(C=>({name:C.name,description:C.description}))}),this.config.initialPrompt&&await this.submit(this.config.initialPrompt),this.startCompactionDebugLog(),this.startSkillWatchers(s)}async loadAllSkills(){const e=this.config.skillsDir??"",t=z.join(this.config.workingDirectory,".acode","skills"),o=z.join(this.config.workingDirectory,".agentswork","skills"),s=new Set,i=[],r=[];for(const u of[e,t,o]){if(!u)continue;const c=z.resolve(u);if(!s.has(c)){s.add(c),i.push(await lo(u));try{await D.promises.access(c),r.push(c)}catch{}}}const a=new Map;for(const u of i)for(const c of u.skills)a.set(c.name,c);return{skills:[...a.values()],skillGroups:i,watchedDirs:r}}startSkillWatchers(e){for(const t of e){let o=null;try{o=D.watch(t,{recursive:!0},()=>{this.scheduleSkillRefresh()})}catch{try{o=D.watch(t,()=>{this.scheduleSkillRefresh()})}catch{continue}}o&&(o.on("error",()=>{}),this.skillWatchers.push(o))}}scheduleSkillRefresh(){this.skillRefreshTimer&&clearTimeout(this.skillRefreshTimer),this.skillRefreshTimer=setTimeout(()=>{this.skillRefreshTimer=null,this.refreshSkills()},Z.SKILL_REFRESH_DEBOUNCE_MS)}async refreshSkills(){if(!(!this.state.started||this.state.terminated))try{const{skills:e,skillGroups:t}=await this.loadAllSkills();this.skillTool&&this.skillTool.refresh(e),this.state.skills=e,this.instructionsDirty=!0,this.emitAcodeEvent("skill_status",{skillsDir:this.config.skillsDir,installedCount:e.length,skills:e.map(o=>({name:o.name,description:o.description,directory:o.directory})),skillGroups:t.map(o=>({dir:o.dir,exists:o.exists,skills:o.skills.map(s=>({name:s.name,description:s.description,directory:s.directory}))}))}),f(`[skill-watch] Skills refreshed: ${e.length} skills (${e.map(o=>o.name).join(", ")||"none"})`,{sessionId:this.config.sessionId})}catch(e){console.error("[skill-watch] Failed to refresh skills:",e instanceof Error?e.message:e)}}stopSkillWatchers(){this.skillRefreshTimer&&(clearTimeout(this.skillRefreshTimer),this.skillRefreshTimer=null);for(const e of this.skillWatchers)try{e.close()}catch{}this.skillWatchers=[]}startCompactionDebugLog(){if(!Ce||this.compactionDebugTimer)return;const e=this.state.provider,{contextLimit:t,maxOutput:o,inputLimit:s,threshold:i}=Ae(e);this.compactionDebugTimer=setInterval(()=>{try{const r=this.state.accumulatedInputTokens+this.state.accumulatedOutputTokens,a=j(this.state.conversation)+ie(this.state.exposedTools),l=Math.max(r,a),u=Y(this.state.conversation),c=this.state.started&&!this.state.terminated,d=[`[${new Date().toISOString()}]`,`started=${this.state.started}`,`terminated=${this.state.terminated}`,`activeTurn=${this.activeTurn}`,`conversationSize=${this.state.conversation.length}msgs`,`sizeKB=${u}KB`,`estimation=${a} tokens`,`actualInput=${this.state.accumulatedInputTokens}`,`actualOutput=${this.state.accumulatedOutputTokens}`,`actualUsed=${r}`,`contextLimit=${t}`,`inputLimit=${s??"n/a"}`,`maxOutput=${o}`,`triggerThreshold=${i}`,`remainingToTrigger=${Math.max(0,i-r)}`,`isRunning=${c}`,`shouldCompact=${c?l>=i:!1}`,"---"].join(" | ");D.promises.appendFile(at,d+`
15
- `,"utf-8").catch(()=>{})}catch{}},5e3)}stopCompactionDebugLog(){this.compactionDebugTimer&&(clearInterval(this.compactionDebugTimer),this.compactionDebugTimer=null)}async submit(e,t){const o=this.contextVersion;f(`[ACodeRuntime] \u{1F4EC} submit() queued: contextVersion=${o}, activeTurn=${this.activeTurn}, abortRequested=${this.abortRequested}, terminated=${this.state.terminated}, message.length=${e.length}`);const s=this.submitQueue.then(()=>(f(`[ACodeRuntime] \u25B6\uFE0F executeSubmit dequeued: contextVersion=${o}`),this.executeSubmitGuarded(e,o,t)));return this.submitQueue=s.catch(()=>{f("[ACodeRuntime] \u{1F4EC} submit() queued item rejected (catch swallowed)")}),f("[ACodeRuntime] \u{1F4EC} submit() returning queued promise"),s}executeSubmitGuarded(e,t,o){const s={};this.activeTurnToken=s;const i=this.executeSubmit(e,t,o),r=new Promise(a=>{this.forceSettleWaiters.set(s,a)});return i.finally(()=>{this.forceSettleWaiters.delete(s),this.activeTurnToken===s&&(this.abortForceSettleTimer&&(clearTimeout(this.abortForceSettleTimer),this.abortForceSettleTimer=null),this.activeTurnToken=null)}).catch(()=>{}),Promise.race([i,r])}armAbortForceSettle(){if(!this.activeTurn||!this.activeTurnToken)return;const e=this.activeTurnToken;this.abortForceSettleTimer&&clearTimeout(this.abortForceSettleTimer);const t=xs();this.abortForceSettleTimer=setTimeout(()=>{this.abortForceSettleTimer=null,this.activeTurn&&this.activeTurnToken===e&&this.forceSettleActiveTurn(`turn still unsettled ${t}ms after abort()`)},t),typeof this.abortForceSettleTimer.unref=="function"&&this.abortForceSettleTimer.unref()}forceSettleActiveTurn(e){const t=this.activeTurnToken;console.error(`[ACodeRuntime] \u{1F6A8} FORCE SETTLE: active turn ignored abort() (${e}). Force-settling to unblock submitQueue; late executeSubmit continuation will be superseded.`),this.contextVersion+=1,this.activeTurn=!1,this.abortRequested=!1,this.abortController=null,this.rejectAllQuestionWaiters("aborted"),this.rejectAllPermissionWaiters("aborted"),this.cancelPendingAwaitedSubAgents(),this.cancelPendingAwaitedBgTasks(),this.notifyRuntimeStop(),this.emitAcodeEvent("error",{message:`ACode turn force-settled: ${e}`}),this.emitAcodeEvent("turn_complete",{failed:!0});const o=t?this.forceSettleWaiters.get(t):void 0;t&&this.forceSettleWaiters.delete(t),this.activeTurnToken=null,o?.()}notifyForceMessage(){this.forceMessagePending=!0,f("[ACodeRuntime] \u{1F514} Force message pending flag set")}exportConversation(){return ce(this.state.conversation)}async importTranscript(e){if(!Array.isArray(e)||e.length===0)return console.log("[HIBERNATE-REPLAY][runtime] \u7A7A\u8F93\u5165\uFF0C\u8DF3\u8FC7\u91CD\u653E"),0;if(!this.state.started)return console.log(`[HIBERNATE-REPLAY][runtime] \u4F1A\u8BDD\u672A start()\uFF0C\u8DF3\u8FC7\u91CD\u653E\uFF08${e.length}\u6761\u88AB\u4E22\u5F03\uFF09`),0;const t=e.filter(u=>u.role!=="system");if(t.length===0)return 0;const{contextLimit:o,maxOutput:s,inputLimit:i}=Ae(this.state.provider),r=oo(o,i),a=j(this.state.conversation)+j(t)+ie(this.state.exposedTools);let l=t;if(console.log(`[HIBERNATE-REPLAY][runtime] \u9884\u68C0: \u53EF\u91CD\u653E=${t.length}\u6761 projectedTokens=${a} hardWindow=${r} \u9700\u8981\u9884\u538B\u7F29=${a>=r}`),a>=r){f(`[ACodeRuntime] \u{1F4E6} importTranscript pre-compaction: projected=${a} >= hardWindow=${r}`);try{const u=await pe(t,o,s,{llmSummarizer:c=>this.summarizeConversationWithLLM(c)});if(u.strategy!=="none"){const c=j(t);f(`[ACodeRuntime] \u{1F4E6} importTranscript pre-compaction done: strategy=${u.strategy}, tokensBefore=${a}, tokensAfter=${c}`)}}catch(u){f(`[ACodeRuntime] \u26A0\uFE0F importTranscript pre-compaction failed, replaying raw: ${u instanceof Error?u.message:String(u)}`)}l=t}return this.state.conversation.push(...ce(l)),console.log(`[HIBERNATE-REPLAY][runtime] \u91CD\u653E\u5B8C\u6210: \u62FC\u5165=${l.length}\u6761 conversation\u603B\u957F=${this.state.conversation.length}\u6761 \u603Btoken\u4F30\u7B97=${j(this.state.conversation)+ie(this.state.exposedTools)}`),this.emitAcodeEvent("context_compaction",{action:"end",compactionId:`transcript-replay-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,sizeKB:Y(this.state.conversation),estimatedTokens:j(this.state.conversation)+ie(this.state.exposedTools),actualInputTokens:this.state.accumulatedInputTokens,actualOutputTokens:this.state.accumulatedOutputTokens,messageCount:this.state.conversation.length,replayedMessageCount:l.length,model:this.state.provider.model,trigger:"hibernation_replay"}),l.length}addBuiltInTools(e){if(!this.state||!this.exposedToolsInitialized||!Array.isArray(e))return 0;const t=new Set(this.state.exposedTools.map(s=>s.exposedName)),o=[];for(const s of e)To(s)&&(t.has(s.exposedName)||(t.add(s.exposedName),o.push(s)));return o.length===0?0:(this.state.exposedTools=[...this.state.exposedTools,...o],this.emitExposedToolsStatus(),o.length)}removeBuiltInToolsByPrefix(e){if(!this.state||!this.exposedToolsInitialized||!e)return 0;const t=this.state.exposedTools.length;this.state.exposedTools=this.state.exposedTools.filter(s=>!s.exposedName.startsWith(e));const o=t-this.state.exposedTools.length;return o>0&&this.emitExposedToolsStatus(),o}async addMcpServer(e,t){if(!this.state?.started||this.state.terminated)return{ok:!1,tools:0,error:"ACode runtime is not active"};const o=String(e??"").trim();if(!o)return{ok:!1,tools:0,error:"server name is required"};this.state.mcpConnections.find(u=>u.serverName===o)&&await this.removeMcpServer(o);const i=this.state.provider.mcpToolTimeoutMs;let r;const a=new Map;try{r=await this.connectMcpServers({[o]:t},i,a)}catch(u){return{ok:!1,tools:0,error:u instanceof Error?u.message:String(u)}}const l=r.find(u=>u.serverName===o);if(!l){const u=a.get(o);return{ok:!1,tools:0,error:u?`MCP server ${o} \u8FDE\u63A5\u5931\u8D25: ${u}`:`MCP server ${o} \u8FDE\u63A5\u5931\u8D25`}}return this.state.mcpConnections=[...this.state.mcpConnections,l],this.registerMcpCollapsedGroup(o,t,l),this.registerToolGroupsFromMcp(l),this.exposedToolsInitialized&&(this.state.exposedTools=[...this.state.exposedTools,...l.tools]),this.emitExposedToolsStatus(),{ok:!0,tools:l.tools.length,toolNames:l.tools.map(u=>u.exposedName)}}async removeMcpServer(e){const t=String(e??"").trim();if(!t)return{ok:!1,removed:!1};const o=this.state?.mcpConnections.find(s=>s.serverName===t);return o?(this.state.mcpConnections=this.state.mcpConnections.filter(s=>s.serverName!==t),this.state.exposedTools=this.state.exposedTools.filter(s=>!(s.kind==="mcp"&&s.serverName===t)),this.toolGroupManager?.unregister?.(Be(t)),this.mcpStderrBuffers.delete(t),await se(`ACode MCP server ${t} close`,o.transport.close(),s=>{this.emitAcodeEvent("error",{message:s})},this.state.provider.mcpToolTimeoutMs),this.emitExposedToolsStatus(),{ok:!0,removed:!0}):{ok:!0,removed:!1}}addPluginCommands(e){if(!this.state||e.length===0)return;this.state.commandRegistry.addCommands(e);const t=new Set(this.state.commands.map(o=>o.name));this.state.commands=[...this.state.commands,...e.filter(o=>!t.has(o.name))]}applyPluginGroups(e,t,o){const s=new Map;for(const r of e)s.set(Ht(r.name),{label:r.name,summary:r.description??"",state:r.enabled?"collapsed":"disabled"});let i=!1;for(const r of o.getAllGroups())Ue(r.key)&&(s.has(r.key)||(o.unregister(r.key),t.delete(r.key),i=!0));for(const[r,a]of s){const l=o.getRegistration(r);l?(l.label!==a.label||l.summary!==a.summary)&&o.register({...l,label:a.label,summary:a.summary,collapsible:!0,pluginName:a.label}):(o.register({key:r,label:a.label,summary:a.summary,collapsible:!0,pluginName:a.label}),i=!0);const u=t.get(r);u!==void 0&&u!==a.state&&(i=!0),t.set(r,a.state)}return i}async syncPluginGroups(){if(!this.config.pluginBridge||!this.toolGroupManager||!this.state)return;let e;try{e=await this.config.pluginBridge.listPlugins()}catch(o){f(`[ACodeRuntime] syncPluginGroups \u62C9\u53D6\u63D2\u4EF6\u6E05\u5355\u5931\u8D25\uFF08\u5FFD\u7565\uFF09: ${o instanceof Error?o.message:String(o)}`);return}this.applyPluginGroups(e,this.pluginGroupStates,this.toolGroupManager)&&(this.injectPluginChangeNotice(),this.instructionsDirty=!0)}injectPluginChangeNotice(){const e="[\u63D2\u4EF6\u80FD\u529B\u53D8\u66F4]",t=this.state.conversation;for(let s=t.length-1;s>=0;s--){const i=t[s];i.role==="system"&&typeof i.content=="string"&&i.content.startsWith(e)&&t.splice(s,1)}const o=[...this.pluginGroupStates.entries()].filter(([,s])=>s!=="disabled").map(([s])=>s.slice(7));t.push({role:"system",content:`${e}
16
- \u63D2\u4EF6\u80FD\u529B\u6E05\u5355\u5DF2\u66F4\u65B0\u3002\u5F53\u524D\u53EF\u7528\u63D2\u4EF6\uFF1A`+(o.length?o.map(s=>`plugin:${s}`).join("\u3001"):"\uFF08\u65E0\uFF09")+'\u3002\u9700\u8981\u67D0\u63D2\u4EF6\u7684\u5DE5\u5177\u65F6\uFF0C\u5148 expand_tools({ group:"plugin:\u63D2\u4EF6\u540D" }) \u5C55\u5F00\uFF0C\u518D\u7528 call_tool \u8C03\u7528\u3002'})}emitExposedToolsStatus(){this.emitAcodeEvent("mcp_status",{servers:this.state.mcpConnections.map(e=>e.serverName),connectedCount:this.state.mcpConnections.length,toolCount:this.state.exposedTools.length,tools:this.state.exposedTools.map(e=>({name:e.exposedName,source:e.kind==="mcp"?`${e.serverName}.${e.toolName}`:`builtin.${e.toolName}`,description:e.description||""}))})}async injectForceMessage(){if(!this.forceMessagePending)return!1;this.forceMessagePending=!1;const e=this.state.mcpConnections.find(t=>t.tools.some(o=>o.toolName==="get_message"));if(!e)return f("[ACodeRuntime] injectForceMessage: no connection with get_message found"),!1;try{const t=await $(e.client.callTool({name:"get_message",arguments:{_aws_force_inject:!0}},void 0,{timeout:1e4}),1e4,"injectForceMessage get_message"),o=G(t);let s=[];try{const l=JSON.parse(o);Array.isArray(l?.directMessages)&&(s=l.directMessages.filter(u=>u?.force===!0))}catch{return!1}if(s.length===0)return!1;const i=JSON.stringify({directMessages:s,groupMessages:[]}),r=`forced_get_msg_${Date.now()}`,a=`${e.serverName}__get_message`;return this.state.conversation.push({role:"assistant",content:null,tool_calls:[{id:r,type:"function",function:{name:a,arguments:"{}"}}]}),this.state.conversation.push({role:"tool",tool_call_id:r,content:i}),f(`[ACodeRuntime] injectForceMessage: injected ${s.length} force message(s) into conversation`),!0}catch(t){return f(`[ACodeRuntime] injectForceMessage failed: ${t}`),!1}}async resetContext(){if(!this.state.started||this.state.terminated)throw new Error("ACode runtime is not active");this.contextVersion+=1,this.abortRequested=this.activeTurn,this.abortController?.abort(),this.abortController=null,this.state.conversation=ce(this.initialConversation),this.turnPromptPushed=!1,this.state.accumulatedInputTokens=0,this.state.accumulatedOutputTokens=0}isTurnSuperseded(e){return e!==this.contextVersion}async executeSubmit(e,t,o){const s=Date.now();if(f("[ACodeRuntime] \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"),f("[ACodeRuntime] \u25B6\uFE0F executeSubmit STARTED"),f(`[ACodeRuntime] Message: <redacted, length=${e.length}>`),f(`[ACodeRuntime] \u{1F522} Context version: ${t}`),f("[ACodeRuntime] \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"),!this.state.started||this.state.terminated)throw console.error(`[ACodeRuntime] \u274C Runtime not active (started: ${this.state.started}, terminated: ${this.state.terminated})`),new Error("ACode runtime is not active");this.activeTurn=!0,this.abortRequested=!1;const i=this.activeTurnToken,r=e.trim();let a=!1;const l=o?.resume===!0&&this.turnPromptPushed;l||(this.turnPromptPushed=!1);try{let u;if(l)f("[ACodeRuntime] \u{1F501} resume turn: skip UserPromptSubmit hook (already ran in failed turn)"),u=[];else{f("[ACodeRuntime] \u{1F50D} Dispatching UserPromptSubmit hook...");const y=Date.now();u=await this.hookBus.dispatch("UserPromptSubmit",{prompt:r});const w=Date.now()-y;f(`[ACodeRuntime] \u2705 UserPromptSubmit hook completed in ${w}ms, results: ${u.length}`)}if(this.isTurnSuperseded(t)){f("[ACodeRuntime] \u26A0\uFE0F Turn superseded after hook, aborting");return}const c=je(u);if(c){console.error(`[ACodeRuntime] \u274C Prompt denied by hook: ${c.message}`),this.emitAcodeEvent("error",{message:c.message||"ACode prompt was denied by hook"}),this.emitAcodeEvent("turn_complete",{failed:!0}),a=!0,f("[ACodeRuntime] \u{1F4E4} Emitted turn_complete (failed=true) due to hook deny");return}f("[ACodeRuntime] \u{1F50D} Expanding command if any...");const d=this.state.commandRegistry.expand(r),p=d?.prompt.trim()||r,T=d?.command.allowedTools;if(d&&!l){f(`[ACodeRuntime] \u{1F4CB} Slash command detected: ${d.command.name}`),this.emitAcodeEvent("command_status",{action:"slash_command",command:d.command.name,arguments:d.argumentsText,sourcePath:d.command.sourcePath});const y=d.command.plugin;y&&f(`[ACodeRuntime] \u{1F4CB} Slash command belongs to plugin: ${y}`)}if(!this.state.provider.baseURL){f("[ACodeRuntime] \u26A0\uFE0F No provider baseURL configured, using fallback response");const y=ps(p,this.state);this.emitAcodeEvent("assistant_delta",{text:y}),this.emitAcodeEvent("turn_complete",{usage:{inputTokens:p.length,outputTokens:y.length},usageEstimated:!0}),a=!0,f("[ACodeRuntime] \u{1F4E4} Emitted turn_complete (fallback mode)");return}if(l){if(f("[ACodeRuntime] \u{1F501} resume turn: user message already in conversation, skipping push"),this.isTurnSuperseded(t)){f("[ACodeRuntime] \uFE0F Turn superseded before resume runModelTurn, aborting");return}}else{f("[ACodeRuntime] \u{1F4CE} Parsing attachment message...");const y=Re(p);if(y.hasImages&&!this.state.provider.supportsImageInput)throw console.error("[ACodeRuntime] \u274C Image input not supported by current provider"),new Error("ACode provider/model is not configured for image input. Enable provider.default.models[model].modalities.input including 'image' or options.supportsImageInput=true.");f("[ACodeRuntime] \u{1F5BC}\uFE0F Materializing image content if any...");const w=await mt(y.content);if(this.isTurnSuperseded(t)){f("[ACodeRuntime] \uFE0F Turn superseded after materializing content, aborting");return}f("[ACodeRuntime] \u{1F4AC} Adding user message to conversation"),this.state.conversation.push({role:"user",content:w}),this.turnPromptPushed=!0,f(`[ACodeRuntime] Conversation size: ${this.state.conversation.length} messages`)}f("[ACodeRuntime] Starting runModelTurn...");const _=Date.now(),m=await this.runModelTurn(T,t),h=Date.now()-_;if(f(`[ACodeRuntime] \u2705 runModelTurn completed in ${h}ms`),f(`[ACodeRuntime] \u{1F4DD} Result: text=${m.text?m.text.slice(0,80)+(m.text.length>80?"...":""):"(empty)"}, finishReason=${m.finishReason||"(none)"}`),this.isTurnSuperseded(t)){f("[ACodeRuntime] \uFE0F Turn superseded after runModelTurn, aborting");return}m.text&&!this.state.provider.stream&&(f("[ACodeRuntime] \u{1F4E4} Emitting assistant_delta (non-streaming mode)"),this.emitAcodeEvent("assistant_delta",{text:m.text})),f("[ACodeRuntime] \u{1F4E4} Emitting turn_complete..."),this.emitAcodeEvent("turn_complete",{usage:m.usage??{inputTokens:p.length,outputTokens:m.totalOutputTextLength??m.text.length},usageEstimated:!m.usage,...m.responseBody?{responseBody:m.responseBody}:{},...m.finishReason?{finishReason:m.finishReason}:{}}),oe(`turn_complete emitted: usage=${JSON.stringify(m.usage??{inputTokens:p.length,outputTokens:m.totalOutputTextLength??m.text.length})} (providerUsage=${m.usage?"real":"FALLBACK-text-length"}) textLength=${m.text.length} totalOutputTextLength=${m.totalOutputTextLength}`),f(`[ACodeRuntime] \u{1F4B0} Current context usage: input=${this.state.accumulatedInputTokens}, output=${this.state.accumulatedOutputTokens}`+(m.usage?"":" (estimated, no provider usage)")),a=!0,this.turnPromptPushed=!1;const g=Date.now()-s;f("[ACodeRuntime] \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"),f(`[ACodeRuntime] \u2705 executeSubmit COMPLETED in ${g}ms`),f("[ACodeRuntime] \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\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(u){const c=Date.now()-s;if(console.error(`[ACodeRuntime] \u274C executeSubmit FAILED after ${c}ms:`,u instanceof Error?u.message:String(u)),console.error("[ACodeRuntime] \u{1F50D} Error stack:",u instanceof Error?u.stack:"(no stack)"),this.isTurnSuperseded(t)){f("[ACodeRuntime] \uFE0F Turn superseded in error handler, skipping recovery");return}if(this.abortRequested){f("[ACodeRuntime] \u26A0\uFE0F Abort requested, emitting aborted turn_complete"),this.emitAcodeEvent("turn_complete",{aborted:!0}),a=!0;return}f("[ACodeRuntime] Emitting error and failed turn_complete..."),this.emitAcodeEvent("error",{message:u instanceof Error?u.message:String(u)}),this.emitAcodeEvent("turn_complete",{failed:!0}),a=!0}finally{const u=Date.now()-s;f(`[ACodeRuntime] \u{1F51A} executeSubmit finally block entered after ${u}ms`),f(`[ACodeRuntime] \u{1F50D} turnCompleted=${a}, activeTurn=${this.activeTurn}, abortRequested=${this.abortRequested}, contextVersion=${t}, currentContextVersion=${this.contextVersion}`),this.activeTurnToken===i&&(this.activeTurn=!1,this.abortRequested=!1),!a&&!this.isTurnSuperseded(t)&&(console.error(`[ACodeRuntime] \u{1F6A8} CRITICAL: executeSubmit finally block reached without turn_complete event! Duration: ${u}ms. This indicates a code path that should have emitted turn_complete but didn't. Forcing failed turn_complete to prevent state stuck.`),this.emitAcodeEvent("error",{message:"ACode turn completed without proper completion event (internal error)"}),this.emitAcodeEvent("turn_complete",{failed:!0}),f("[ACodeRuntime] Emergency turn_complete (failed=true) emitted"))}}async abort(){const e=this.abortController!==null,t=this.activeTurn;this.abortRequested=this.activeTurn,this.abortController?(f(`[ACodeRuntime] \u26D4 abort() calling abortController.abort() (activeTurn=${t})`),this.abortController.abort()):console.warn(`[ACodeRuntime] \u26D4 abort() called but abortController is null! activeTurn=${t}, abortRequested will be set to ${t}. This means abort() CANNOT cancel any running fetch/stream \u2014 if a built-in tool is executing, it will NOT be interrupted.`),this.abortController=null,this.rejectAllQuestionWaiters("aborted"),this.rejectAllPermissionWaiters("aborted"),this.cancelPendingAwaitedSubAgents(),this.cancelPendingAwaitedBgTasks(),this.notifyRuntimeStop(),this.armAbortForceSettle()}buildAskUserQuestionDeps(){return{onQuestion:(e,t)=>{this.emitAcodeEvent("question_request",{toolCallId:e,questions:t})},waitForAnswer:(e,t)=>new Promise((o,s)=>{this.questionWaiters.set(e,{resolve:o,reject:s,contextVersion:t})})}}async buildAllocatableToolList(){const e=this.state?.exposedTools??[],t=this.config.subAgentSuiteTools??[];let o=[];if(this.config.subAgentSuiteToolProvider)try{o=await this.config.subAgentSuiteToolProvider([])}catch{o=[]}return he(e,he(t,o))}buildSubAgentToolDeps(e){const t=this.config.agentId??"unknown",o=this.config.sessionId,s=this.config.workingDirectory,i=this.config;return{spawnSubAgent:async r=>{let a=this.config.subAgentSuiteTools;if(r.allowedTools&&r.allowedTools.length>0&&this.config.subAgentSuiteToolProvider)try{const u=await this.config.subAgentSuiteToolProvider(r.allowedTools);u.length>0&&(a=a?he(a,u):u)}catch{}const l=await e.spawn({parentAgentId:t,parentSessionId:o,subagentType:r.subagentType,description:r.description,prompt:r.prompt,...r.allowedTools&&r.allowedTools.length>0?{allowedTools:r.allowedTools}:{},workingDirectory:s,parentConfig:{...i,sharedMcpConnections:this.state?.mcpConnections,...a&&a.length>0?{subAgentSuiteTools:a}:{}}});return await e.start(l),{subId:l}},listSubAgentToolCatalog:async()=>Ge(await this.buildAllocatableToolList()),listSubAgents:async()=>{const r=e.listByParent(t),a=[],l=[];for(const u of r){const c={subId:u.subId,subagentType:u.subagentType,description:u.description,status:u.status,startedAt:u.startedAt,endedAt:u.endedAt,durationMs:u.durationMs};u.status==="pending"||u.status==="running"?a.push(c):l.push(c)}return l.sort((u,c)=>(c.endedAt??0)-(u.endedAt??0)),{running:a,history:l}},getSubAgentStatus:async r=>{const a=e.getSubAgent(r);return a?{subId:a.subId,subagentType:a.subagentType,description:a.description,status:a.status,startedAt:a.startedAt,endedAt:a.endedAt,durationMs:a.durationMs,prompt:a.prompt,result:a.result,errorMessage:a.errorMessage,contextSnapshot:a.contextSnapshot}:null},awaitSubAgents:async(r,a)=>{const l=new Set;for(const u of r)this.pendingAwaitedSubIds.add(u),l.add(u);try{return await e.awaitCompletion(r,a)}finally{for(const u of l)this.pendingAwaitedSubIds.delete(u)}},abortSubAgent:r=>e.abort(r)}}buildAwaitCompleteDeps(){const e=this.config.agentId??"unknown",t=this.config.subAgentManager;return{agentId:e,awaitSubAgents:t?(o,s)=>{for(const i of o)this.pendingAwaitedSubIds.add(i);try{return this.buildSubAgentToolDeps(t).awaitSubAgents(o,s)}finally{for(const i of o)this.pendingAwaitedSubIds.delete(i)}}:null,awaitBgCommands:(o,s)=>{for(const i of o)this.pendingAwaitedBgTaskIds.add(i);try{return le.awaitCompletion(e,o,s)}finally{for(const i of o)this.pendingAwaitedBgTaskIds.delete(i)}}}}submitQuestionAnswer(e,t){return this.settleQuestionWaiter(e,{answers:t})}cancelQuestionAnswer(e,t){const o=String(t||"").trim();return this.settleQuestionWaiter(e,{cancelled:!0,...o?{reason:o}:{}})}settleQuestionWaiter(e,t){const o=this.questionWaiters.get(e);return o?(this.questionWaiters.delete(e),this.isTurnSuperseded(o.contextVersion)?(o.reject(new Error("turn superseded before user answered")),!1):(o.resolve(t),!0)):!1}rejectAllQuestionWaiters(e){if(this.questionWaiters.size!==0){for(const[,t]of this.questionWaiters)t.reject(new Error(`ask_user_question ${e}`));this.questionWaiters.clear()}}createToolPermissionController(){return{getLevel:e=>this.state.toolPermissionPolicy[e]??"allow",requestPermission:(e,t)=>this.requestToolPermission(e,t)}}requestToolPermission(e,t){const o=St();return new Promise(s=>{this.permissionWaiters.set(o,{capability:e,detail:t,resolve:s}),this.emitAcodeEvent("tool_permission_request",{requestId:o,capability:e,agentId:this.config.agentId,...t})})}submitToolPermissionDecision(e,t){const o=this.permissionWaiters.get(e);return o?(this.permissionWaiters.delete(e),o.resolve(t),!0):!1}rejectAllPermissionWaiters(e){if(this.permissionWaiters.size!==0){for(const[,t]of this.permissionWaiters)t.resolve(!1);this.permissionWaiters.clear(),B("tool-permission",`waiters rejected: ${e}`)}}setToolPermissionPolicy(e){this.state.toolPermissionPolicy={...this.state.toolPermissionPolicy,...e}}cancelPendingAwaitedSubAgents(){if(this.pendingAwaitedSubIds.size===0)return;const e=this.config.subAgentManager;if(!e)return;const t=Array.from(this.pendingAwaitedSubIds);f(`[ACodeRuntime] \u26D4 Cancelling ${t.length} pending awaited sub-agent(s): ${t.join(", ")}`);for(const o of t)e.abort(o).catch(s=>{f(`[ACodeRuntime] \u26A0\uFE0F manager.abort(${o}) threw: ${s instanceof Error?s.message:String(s)}`)})}cancelPendingAwaitedBgTasks(){if(this.pendingAwaitedBgTaskIds.size===0)return;const e=this.config.agentId??"unknown",t=Array.from(this.pendingAwaitedBgTaskIds);f(`[ACodeRuntime] \u26D4 Cancelling ${t.length} pending awaited background command(s): ${t.join(", ")}`),le.interruptAwaits(e,t)}detachCurrentToolExecution(e){const t=e?this.toolSettleSlots.get(e):this.pickSettleCandidate();return!t||!t.settlable||t.settled?!1:(t.settled=!0,t.resolveSettle?.(),f(`[ACodeRuntime] \u{1F680} detachCurrentToolExecution: settling tool ${t.toolName} (toolCallId=${t.toolCallId}) to background`),!0)}pickSettleCandidate(){let e=null;for(const t of this.toolSettleSlots.values())!t.settlable||t.settled||(e===null||t.order<e.order)&&(e=t);return e}beginToolSettle(e,t,o){const s=e.toolName==="Bash",i=++this.toolSettleSeq;let r;const a=s?new Promise(l=>{r=l}):void 0;return this.toolSettleSlots.set(o,{seq:i,toolName:e.toolName,toolCallId:o,settlable:s,settled:!1,resolveSettle:r??null,order:i}),{seq:i,signal:a}}clearToolSettle(e,t){if(t!==void 0){this.toolSettleSlots.get(t)?.seq===e&&this.toolSettleSlots.delete(t);return}for(const[o,s]of this.toolSettleSlots)if(s.seq===e){this.toolSettleSlots.delete(o);return}}async stop(){if(this.state.terminated)return;this.state.terminated=!0,this.notifyRuntimeStop(),this.abortRequested=this.activeTurn,this.abortController?.abort(),this.abortController=null,this.armAbortForceSettle(),this.rejectAllQuestionWaiters("session terminated"),this.rejectAllPermissionWaiters("session terminated"),this.readFileStateTracker.clear(),this.cancelPendingAwaitedSubAgents(),this.cancelPendingAwaitedBgTasks(),await se("ACode active turn shutdown",this.submitQueue,t=>{this.emitAcodeEvent("error",{message:t})}),await this.disconnectMcpServers();const e=this.config.agentId||"unknown";if(await se("ACode background commands shutdown",le.disposeAgent(e),t=>{this.emitAcodeEvent("error",{message:t})}),se("ACode agent PTY sessions shutdown",Promise.resolve(this.config.terminalManager?.killByAgent?.(e)),t=>{this.emitAcodeEvent("error",{message:t})}),await se("ACode Stop hooks",this.hookBus.dispatch("Stop",{reason:"session_stop"}),t=>{this.emitAcodeEvent("error",{message:t})}),this.state.terminated=!0,this.sessionCompleteEmitted||(this.sessionCompleteEmitted=!0,this.emitAcodeEvent("session_complete",{exitCode:0})),this.stopCompactionDebugLog(),this.stopSkillWatchers(),Ce)try{D.promises.appendFile(at,`[${new Date().toISOString()}] runtime stopped | ---
17
- `,"utf-8").catch(()=>{})}catch{}}discoverPluginCommandDirs(){const e=this.config.pluginsDir;if(!e)return[];let t;try{t=D.readdirSync(e)}catch{return[]}const o=[];for(const s of t){if(s.startsWith("."))continue;const i=z.join(e,s);let r;try{r=D.statSync(i)}catch{continue}if(!r.isDirectory())continue;const a=z.join(i,"commands");let l;try{D.existsSync(a)&&(l=D.statSync(a))}catch{l=void 0}l?.isDirectory()&&o.push(a)}return o}resolveCommandDirs(e){const t=[...this.config.commandDirs??[],...e.commandDirs??[],...e.commands?.directories??[]];return[...new Set(t.map(o=>o.trim()).filter(Boolean))]}async runModelTurn(e,t=this.contextVersion){let o="",s,i,r,a="",l=0;this.lastIterationUsage=void 0,f(`[ACodeRuntime] \u25B6\uFE0F runModelTurn started (contextVersion: ${t})`);const u=50;for(let c=0;c<u;c+=1){if(f(`[ACodeRuntime] \u{1F504} Iteration ${c+1} starting...`),this.isTurnSuperseded(t))return f(`[ACodeRuntime] \u26A0\uFE0F Turn superseded at iteration ${c+1}, aborting`),{text:"",totalOutputTextLength:a.length};await this.injectForceMessage();const d=Date.now(),p=await this.requestChatCompletion(e),T=Date.now()-d;if(f(`[ACodeRuntime] \u{1F916} AI request completed in ${T}ms, choices: ${p.choices?.length||0}`),this.isTurnSuperseded(t))return f(`[ACodeRuntime] \u26A0\uFE0F Turn superseded after AI response at iteration ${c+1}`),{text:"",totalOutputTextLength:a.length};if(this.state.terminated)throw f(`[ACodeRuntime] Runtime terminated at iteration ${c+1}`),new Error("ACode runtime was stopped during the active turn");const _=p.choices?.[0];i=JSON.stringify(p,null,2),r=typeof _?.finish_reason=="string"?_.finish_reason:void 0;const m=_?.message,h=typeof m?.content=="string"?m.content:"",g=yt(m),y=Array.isArray(m?.tool_calls)?wt(m.tool_calls):[];if(f(`[ACodeRuntime] AI response: content=${h?h.slice(0,100)+(h.length>100?"...":""):"(empty)"}, toolCalls=${y.length}, finishReason=${r||"(none)"}`),p.usage){const k=W(p.usage.prompt_tokens??p.usage.input_tokens),v=W(p.usage.completion_tokens??p.usage.output_tokens),M=k!==void 0,L=v!==void 0;if(oe(`provider usage parsed: raw=${JSON.stringify(p.usage)} input=${k} output=${v} hasInput=${M} hasOutput=${L} iteration=${c+1}`),M||L){const E=wo(p.usage,k),O=s?.outputTokens??a.length+h.length;this.state.accumulatedCacheHitTokens+=E?.cacheHitTokens??0,this.state.accumulatedCacheMissTokens+=E?.cacheMissTokens??0,s={inputTokens:M?k:s?.inputTokens??0,outputTokens:L?v:O,cacheHitTokens:this.state.accumulatedCacheHitTokens,cacheMissTokens:this.state.accumulatedCacheMissTokens},this.lastIterationUsage=s,this.emitAcodeEvent("iteration_usage",{inputTokens:s.inputTokens,outputTokens:s.outputTokens,cacheHitTokens:s.cacheHitTokens,cacheMissTokens:s.cacheMissTokens}),l+=M?k:0,this.state.accumulatedInputTokens=M?k:this.state.accumulatedInputTokens,this.state.accumulatedOutputTokens=L?v:this.state.accumulatedOutputTokens,oe(`finalUsage updated: ${JSON.stringify(s)} (cacheUsage=${JSON.stringify(E??null)})`),f(`[ACodeRuntime] \u{1F4B0} Token usage: input=${s.inputTokens}, output=${s.outputTokens} (turn accumulated cost: input=${l})`),f(E?`[ACodeRuntime] \u{1F4B0} Cache usage (provider reported): hit=${E.cacheHitTokens}, miss=${E.cacheMissTokens}`:'[ACodeRuntime] \u{1F4B0} Cache usage: provider usage \u4E2D\u65E0\u7F13\u5B58\u5B57\u6BB5\uFF08\u9762\u677F\u5C06\u663E\u793A "-"\uFF09')}}else oe(`provider response has NO usage field (fallback to text-length estimate), iteration=${c+1}`);if(this.state.conversation.push({role:"assistant",content:h||null,tool_calls:y.length>0?y:void 0,...g?{reasoning:g.slice(0,$e)}:{}}),h&&(o=h,a+=h,f(`[ACodeRuntime] \u2728 Captured assistant text: ${h.slice(0,80)}...`)),y.length===0)return f(`[ACodeRuntime] \u2705 No tool calls at iteration ${c+1}, completing turn`),{text:o,usage:s,responseBody:i,finishReason:r,totalOutputTextLength:a.length};const w=y.map(k=>k.function.name).join(", ");f(`[ACodeRuntime] \u{1F527} Executing ${y.length} tool(s) at iteration ${c+1}: ${w}`);const A=Date.now();await this.handleToolCalls(y,e,t);const N=Date.now()-A;if(f(`[ACodeRuntime] \u2699\uFE0F Tool execution completed in ${N}ms at iteration ${c+1}`),this.isTurnSuperseded(t))return f(`[ACodeRuntime] \u26A0\uFE0F Turn superseded after tool execution at iteration ${c+1}`),{text:"",totalOutputTextLength:a.length};f(`[ACodeRuntime] \u{1F504} Preparing iteration ${c+2}...`)}return console.error(`[ACodeRuntime] \u{1F6A8} CRITICAL: Reached safety limit of ${u} iterations! This indicates a potential infinite loop. Forcing turn completion.`),{text:o||`ACode \u5DF2\u8FBE\u5230\u5B89\u5168\u8FED\u4EE3\u4E0A\u9650\uFF08${u}\u6B21\uFF09\uFF0C\u5F3A\u5236\u7ED3\u675F\u672C\u8F6E\u5BF9\u8BDD\u3002`,usage:s,responseBody:i,finishReason:r||"safety_iteration_limit_reached",totalOutputTextLength:a.length}}async summarizeConversationWithLLM(e){const t=this.state.provider,o=t.baseURL;if(!o)throw new Error("ACode provider baseURL is not configured for LLM summarization");const s={"Content-Type":"application/json"};t.apiKey&&(s.Authorization=`Bearer ${t.apiKey}`);const i={model:t.model,stream:!0,messages:[{role:"system",content:"You are a helpful AI assistant tasked with summarizing conversations. When asked to summarize, provide a detailed but concise summary of the conversation. Focus on information that would be helpful for continuing the conversation, especially what was in progress and what needs to happen next. Do not respond to any questions in the conversation, only output the summary."},{role:"user",content:`Below is an earlier conversation (${e.messageCount} messages) that needs to be summarized to free context space (current context limit: ${e.contextLimit} tokens).
14
+ `);this.initialConversation=ce(Z),this.state={started:!0,terminated:!1,configMcpCount:Object.keys(e.mcpServers??{}).length,skills:t,provider:i,permissions:r,mcpConnections:a,ownsMcpConnections:l,exposedTools:v,commands:q,commandRegistry:re,conversation:ce(Z),accumulatedInputTokens:0,accumulatedOutputTokens:0,accumulatedCacheHitTokens:0,accumulatedCacheMissTokens:0,toolPermissionPolicy:this.state.toolPermissionPolicy},this.exposedToolsInitialized=!0,this.emitAcodeEvent("startup_phase",{phase:"session_start_hook"}),await this.hookBus.dispatch("SessionStart",{workingDirectory:this.config.workingDirectory,model:i.model,commandCount:q.length});const Y=ue(i);this.emitAcodeEvent("session_started",{workingDirectory:this.config.workingDirectory,model:i.model,commandCount:q.length,estimatedContextTokens:Vo(ee,v),contextLimit:Y.contextLimit,maxOutput:Y.maxOutput,...Y.inputLimit!==void 0?{inputLimit:Y.inputLimit}:{},compactionThreshold:Y.threshold}),this.emitAcodeEvent("mcp_status",{configPath:this.config.configPath,installedCount:this.state.configMcpCount,servers:Object.keys(e.mcpServers??{}),connectedCount:a.length,builtInToolCount:d.length,toolCount:v.length,permissionMode:r.mode,allowedToolRules:r.allow,deniedToolRules:r.deny,tools:v.map(A=>({name:A.exposedName,source:A.kind==="mcp"?`${A.serverName}.${A.toolName}`:`builtin.${A.toolName}`,description:A.description||""}))}),this.emitAcodeEvent("skill_status",{skillsDir:this.config.skillsDir,installedCount:t.length,skills:t.map(A=>({name:A.name,description:A.description,directory:A.directory})),skillGroups:o.map(A=>({dir:A.dir,exists:A.exists,skills:A.skills.map(O=>({name:O.name,description:O.description,directory:O.directory}))}))}),this.emitAcodeEvent("command_status",{action:"commands_loaded",installedCommandCount:q.length,commandDirs:I,commands:q.map(A=>({name:A.name,description:A.description}))}),this.config.initialPrompt&&await this.submit(this.config.initialPrompt),this.startCompactionDebugLog(),this.startSkillWatchers(s)}async loadAllSkills(){const e=this.config.skillsDir??"",t=z.join(this.config.workingDirectory,".acode","skills"),o=z.join(this.config.workingDirectory,".agentswork","skills"),s=new Set,i=[],r=[];for(const u of[e,t,o]){if(!u)continue;const c=z.resolve(u);if(!s.has(c)){s.add(c),i.push(await yo(u));try{await D.promises.access(c),r.push(c)}catch{}}}const a=new Map;for(const u of i)for(const c of u.skills)a.set(c.name,c);return{skills:[...a.values()],skillGroups:i,watchedDirs:r}}startSkillWatchers(e){for(const t of e){let o=null;try{o=D.watch(t,{recursive:!0},()=>{this.scheduleSkillRefresh()})}catch{try{o=D.watch(t,()=>{this.scheduleSkillRefresh()})}catch{continue}}o&&(o.on("error",()=>{}),this.skillWatchers.push(o))}}scheduleSkillRefresh(){this.skillRefreshTimer&&clearTimeout(this.skillRefreshTimer),this.skillRefreshTimer=setTimeout(()=>{this.skillRefreshTimer=null,this.refreshSkills()},te.SKILL_REFRESH_DEBOUNCE_MS)}async refreshSkills(){if(!(!this.state.started||this.state.terminated))try{const{skills:e,skillGroups:t}=await this.loadAllSkills();this.skillTool&&this.skillTool.refresh(e),this.state.skills=e,this.instructionsDirty=!0,this.emitAcodeEvent("skill_status",{skillsDir:this.config.skillsDir,installedCount:e.length,skills:e.map(o=>({name:o.name,description:o.description,directory:o.directory})),skillGroups:t.map(o=>({dir:o.dir,exists:o.exists,skills:o.skills.map(s=>({name:s.name,description:s.description,directory:s.directory}))}))}),h(`[skill-watch] Skills refreshed: ${e.length} skills (${e.map(o=>o.name).join(", ")||"none"})`,{sessionId:this.config.sessionId})}catch(e){console.error("[skill-watch] Failed to refresh skills:",e instanceof Error?e.message:e)}}stopSkillWatchers(){this.skillRefreshTimer&&(clearTimeout(this.skillRefreshTimer),this.skillRefreshTimer=null);for(const e of this.skillWatchers)try{e.close()}catch{}this.skillWatchers=[]}startCompactionDebugLog(){if(!be||this.compactionDebugTimer)return;const e=this.state.provider,{contextLimit:t,maxOutput:o,inputLimit:s,threshold:i}=ue(e);this.compactionDebugTimer=setInterval(()=>{try{const r=this.state.accumulatedInputTokens+this.state.accumulatedOutputTokens,a=G(this.state.conversation)+K(this.state.exposedTools),l=Math.max(r,a),u=X(this.state.conversation),c=this.state.started&&!this.state.terminated,d=[`[${new Date().toISOString()}]`,`started=${this.state.started}`,`terminated=${this.state.terminated}`,`activeTurn=${this.activeTurn}`,`conversationSize=${this.state.conversation.length}msgs`,`sizeKB=${u}KB`,`estimation=${a} tokens`,`actualInput=${this.state.accumulatedInputTokens}`,`actualOutput=${this.state.accumulatedOutputTokens}`,`actualUsed=${r}`,`contextLimit=${t}`,`inputLimit=${s??"n/a"}`,`maxOutput=${o}`,`triggerThreshold=${i}`,`remainingToTrigger=${Math.max(0,i-r)}`,`isRunning=${c}`,`shouldCompact=${c?l>=i:!1}`,"---"].join(" | ");D.promises.appendFile(pt,d+`
15
+ `,"utf-8").catch(()=>{})}catch{}},5e3)}stopCompactionDebugLog(){this.compactionDebugTimer&&(clearInterval(this.compactionDebugTimer),this.compactionDebugTimer=null)}async submit(e,t){const o=this.contextVersion;h(`[ACodeRuntime] \u{1F4EC} submit() queued: contextVersion=${o}, activeTurn=${this.activeTurn}, abortRequested=${this.abortRequested}, terminated=${this.state.terminated}, message.length=${e.length}`);const s=this.submitQueue.then(()=>(h(`[ACodeRuntime] \u25B6\uFE0F executeSubmit dequeued: contextVersion=${o}`),this.executeSubmitGuarded(e,o,t)));return this.submitQueue=s.catch(()=>{h("[ACodeRuntime] \u{1F4EC} submit() queued item rejected (catch swallowed)")}),h("[ACodeRuntime] \u{1F4EC} submit() returning queued promise"),s}executeSubmitGuarded(e,t,o){const s={};this.activeTurnToken=s;const i=this.executeSubmit(e,t,o),r=new Promise(a=>{this.forceSettleWaiters.set(s,a)});return i.finally(()=>{this.forceSettleWaiters.delete(s),this.activeTurnToken===s&&(this.abortForceSettleTimer&&(clearTimeout(this.abortForceSettleTimer),this.abortForceSettleTimer=null),this.activeTurnToken=null)}).catch(()=>{}),Promise.race([i,r])}armAbortForceSettle(){if(!this.activeTurn||!this.activeTurnToken)return;const e=this.activeTurnToken;this.abortForceSettleTimer&&clearTimeout(this.abortForceSettleTimer);const t=zs();this.abortForceSettleTimer=setTimeout(()=>{this.abortForceSettleTimer=null,this.activeTurn&&this.activeTurnToken===e&&this.forceSettleActiveTurn(`turn still unsettled ${t}ms after abort()`)},t),typeof this.abortForceSettleTimer.unref=="function"&&this.abortForceSettleTimer.unref()}forceSettleActiveTurn(e){const t=this.activeTurnToken;console.error(`[ACodeRuntime] \u{1F6A8} FORCE SETTLE: active turn ignored abort() (${e}). Force-settling to unblock submitQueue; late executeSubmit continuation will be superseded.`),this.contextVersion+=1,this.activeTurn=!1,this.abortRequested=!1,this.abortController=null,this.rejectAllQuestionWaiters("aborted"),this.rejectAllPermissionWaiters("aborted"),this.cancelPendingAwaitedSubAgents(),this.cancelPendingAwaitedBgTasks(),this.notifyRuntimeStop(),this.emitAcodeEvent("error",{message:`ACode turn force-settled: ${e}`}),this.emitAcodeEvent("turn_complete",{failed:!0});const o=t?this.forceSettleWaiters.get(t):void 0;t&&this.forceSettleWaiters.delete(t),this.activeTurnToken=null,o?.()}notifyForceMessage(){this.forceMessagePending=!0,h("[ACodeRuntime] \u{1F514} Force message pending flag set")}exportConversation(){return ce(this.state.conversation)}async importTranscript(e){if(!Array.isArray(e)||e.length===0)return console.log("[HIBERNATE-REPLAY][runtime] \u7A7A\u8F93\u5165\uFF0C\u8DF3\u8FC7\u91CD\u653E"),0;if(!this.state.started)return console.log(`[HIBERNATE-REPLAY][runtime] \u4F1A\u8BDD\u672A start()\uFF0C\u8DF3\u8FC7\u91CD\u653E\uFF08${e.length}\u6761\u88AB\u4E22\u5F03\uFF09`),0;const t=e.filter(u=>u.role!=="system");if(t.length===0)return 0;const{contextLimit:o,maxOutput:s,inputLimit:i}=ue(this.state.provider),r=mo(o,i),a=G(this.state.conversation)+G(t)+K(this.state.exposedTools);let l=t;if(console.log(`[HIBERNATE-REPLAY][runtime] \u9884\u68C0: \u53EF\u91CD\u653E=${t.length}\u6761 projectedTokens=${a} hardWindow=${r} \u9700\u8981\u9884\u538B\u7F29=${a>=r}`),a>=r){h(`[ACodeRuntime] \u{1F4E6} importTranscript pre-compaction: projected=${a} >= hardWindow=${r}`);try{const u=Te(t),c=await fe(t,o,s,{llmSummarizer:d=>this.summarizeConversationWithLLM(d),...u.length>0?{prefixMessages:u}:{}});if(c.strategy!=="none"){const d=G(t);h(`[ACodeRuntime] \u{1F4E6} importTranscript pre-compaction done: strategy=${c.strategy}, tokensBefore=${a}, tokensAfter=${d}`)}}catch(u){h(`[ACodeRuntime] \u26A0\uFE0F importTranscript pre-compaction failed, replaying raw: ${u instanceof Error?u.message:String(u)}`)}l=t}return this.state.conversation.push(...ce(l)),console.log(`[HIBERNATE-REPLAY][runtime] \u91CD\u653E\u5B8C\u6210: \u62FC\u5165=${l.length}\u6761 conversation\u603B\u957F=${this.state.conversation.length}\u6761 \u603Btoken\u4F30\u7B97=${G(this.state.conversation)+K(this.state.exposedTools)}`),await this.rebuildRuntimeResourcesMessage(),this.emitAcodeEvent("context_compaction",{action:"end",compactionId:`transcript-replay-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,sizeKB:X(this.state.conversation),estimatedTokens:G(this.state.conversation)+K(this.state.exposedTools),actualInputTokens:this.state.accumulatedInputTokens,actualOutputTokens:this.state.accumulatedOutputTokens,messageCount:this.state.conversation.length,replayedMessageCount:l.length,model:this.state.provider.model,trigger:"hibernation_replay"}),l.length}addBuiltInTools(e){if(!this.state||!this.exposedToolsInitialized||!Array.isArray(e))return 0;const t=new Set(this.state.exposedTools.map(s=>s.exposedName)),o=[];for(const s of e)vo(s)&&(t.has(s.exposedName)||(t.add(s.exposedName),o.push(s)));return o.length===0?0:(this.state.exposedTools=[...this.state.exposedTools,...o],this.emitExposedToolsStatus(),o.length)}removeBuiltInToolsByPrefix(e){if(!this.state||!this.exposedToolsInitialized||!e)return 0;const t=this.state.exposedTools.length;this.state.exposedTools=this.state.exposedTools.filter(s=>!s.exposedName.startsWith(e));const o=t-this.state.exposedTools.length;return o>0&&this.emitExposedToolsStatus(),o}async addMcpServer(e,t){if(!this.state?.started||this.state.terminated)return{ok:!1,tools:0,error:"ACode runtime is not active"};const o=String(e??"").trim();if(!o)return{ok:!1,tools:0,error:"server name is required"};this.state.mcpConnections.find(u=>u.serverName===o)&&await this.removeMcpServer(o);const i=this.state.provider.mcpToolTimeoutMs;let r;const a=new Map;try{r=await this.connectMcpServers({[o]:t},i,a)}catch(u){return{ok:!1,tools:0,error:u instanceof Error?u.message:String(u)}}const l=r.find(u=>u.serverName===o);if(!l){const u=a.get(o);return{ok:!1,tools:0,error:u?`MCP server ${o} \u8FDE\u63A5\u5931\u8D25: ${u}`:`MCP server ${o} \u8FDE\u63A5\u5931\u8D25`}}return this.state.mcpConnections=[...this.state.mcpConnections,l],this.registerMcpCollapsedGroup(o,t,l),this.registerToolGroupsFromMcp(l),this.exposedToolsInitialized&&(this.state.exposedTools=[...this.state.exposedTools,...l.tools]),this.emitExposedToolsStatus(),{ok:!0,tools:l.tools.length,toolNames:l.tools.map(u=>u.exposedName)}}async removeMcpServer(e){const t=String(e??"").trim();if(!t)return{ok:!1,removed:!1};const o=this.state?.mcpConnections.find(s=>s.serverName===t);return o?(this.state.mcpConnections=this.state.mcpConnections.filter(s=>s.serverName!==t),this.state.exposedTools=this.state.exposedTools.filter(s=>!(s.kind==="mcp"&&s.serverName===t)),this.toolGroupManager?.unregister?.(Fe(t)),this.mcpStderrBuffers.delete(t),await ie(`ACode MCP server ${t} close`,o.transport.close(),s=>{this.emitAcodeEvent("error",{message:s})},this.state.provider.mcpToolTimeoutMs),this.emitExposedToolsStatus(),{ok:!0,removed:!0}):{ok:!0,removed:!1}}addPluginCommands(e){if(!this.state||e.length===0)return;this.state.commandRegistry.addCommands(e);const t=new Set(this.state.commands.map(o=>o.name));this.state.commands=[...this.state.commands,...e.filter(o=>!t.has(o.name))]}applyPluginGroups(e,t,o){const s=new Map;for(const r of e)s.set(to(r.name),{label:r.name,summary:r.description??"",state:r.enabled?"collapsed":"disabled"});let i=!1;for(const r of o.getAllGroups())ze(r.key)&&(s.has(r.key)||(o.unregister(r.key),t.delete(r.key),i=!0));for(const[r,a]of s){const l=o.getRegistration(r);l?(l.label!==a.label||l.summary!==a.summary)&&o.register({...l,label:a.label,summary:a.summary,collapsible:!0,pluginName:a.label}):(o.register({key:r,label:a.label,summary:a.summary,collapsible:!0,pluginName:a.label}),i=!0);const u=t.get(r);u!==void 0&&u!==a.state&&(i=!0),t.set(r,a.state)}return i}async syncPluginGroups(){if(!this.config.pluginBridge||!this.toolGroupManager||!this.state)return;let e;try{e=await this.config.pluginBridge.listPlugins()}catch(o){h(`[ACodeRuntime] syncPluginGroups \u62C9\u53D6\u63D2\u4EF6\u6E05\u5355\u5931\u8D25\uFF08\u5FFD\u7565\uFF09: ${o instanceof Error?o.message:String(o)}`);return}this.applyPluginGroups(e,this.pluginGroupStates,this.toolGroupManager)&&(this.injectPluginChangeNotice(),this.instructionsDirty=!0)}injectPluginChangeNotice(){const e="[\u63D2\u4EF6\u80FD\u529B\u53D8\u66F4]",t=this.state.conversation;for(let s=t.length-1;s>=0;s--){const i=t[s];i.role==="system"&&typeof i.content=="string"&&i.content.startsWith(e)&&t.splice(s,1)}const o=[...this.pluginGroupStates.entries()].filter(([,s])=>s!=="disabled").map(([s])=>s.slice(7));t.push({role:"system",content:`${e}
16
+ \u63D2\u4EF6\u80FD\u529B\u6E05\u5355\u5DF2\u66F4\u65B0\u3002\u5F53\u524D\u53EF\u7528\u63D2\u4EF6\uFF1A`+(o.length?o.map(s=>`plugin:${s}`).join("\u3001"):"\uFF08\u65E0\uFF09")+'\u3002\u9700\u8981\u67D0\u63D2\u4EF6\u7684\u5DE5\u5177\u65F6\uFF0C\u5148 expand_tools({ group:"plugin:\u63D2\u4EF6\u540D" }) \u5C55\u5F00\uFF0C\u518D\u7528 call_tool \u8C03\u7528\u3002'})}emitExposedToolsStatus(){this.emitAcodeEvent("mcp_status",{servers:this.state.mcpConnections.map(e=>e.serverName),connectedCount:this.state.mcpConnections.length,toolCount:this.state.exposedTools.length,tools:this.state.exposedTools.map(e=>({name:e.exposedName,source:e.kind==="mcp"?`${e.serverName}.${e.toolName}`:`builtin.${e.toolName}`,description:e.description||""}))})}async injectForceMessage(){if(!this.forceMessagePending)return!1;this.forceMessagePending=!1;const e=this.state.mcpConnections.find(t=>t.tools.some(o=>o.toolName==="get_message"));if(!e)return h("[ACodeRuntime] injectForceMessage: no connection with get_message found"),!1;try{const t=await E(e.client.callTool({name:"get_message",arguments:{_aws_force_inject:!0}},void 0,{timeout:1e4}),1e4,"injectForceMessage get_message"),o=H(t);let s=[];try{const l=JSON.parse(o);Array.isArray(l?.directMessages)&&(s=l.directMessages.filter(u=>u?.force===!0))}catch{return!1}if(s.length===0)return!1;const i=JSON.stringify({directMessages:s,groupMessages:[]}),r=`forced_get_msg_${Date.now()}`,a=`${e.serverName}__get_message`;return this.state.conversation.push({role:"assistant",content:null,tool_calls:[{id:r,type:"function",function:{name:a,arguments:"{}"}}]}),this.state.conversation.push({role:"tool",tool_call_id:r,content:i}),h(`[ACodeRuntime] injectForceMessage: injected ${s.length} force message(s) into conversation`),!0}catch(t){return h(`[ACodeRuntime] injectForceMessage failed: ${t}`),!1}}async resetContext(){if(!this.state.started||this.state.terminated)throw new Error("ACode runtime is not active");this.contextVersion+=1,this.abortRequested=this.activeTurn,this.abortController?.abort(),this.abortController=null,this.state.conversation=ce(this.initialConversation),this.turnPromptPushed=!1,this.state.accumulatedInputTokens=0,this.state.accumulatedOutputTokens=0,await this.rebuildRuntimeResourcesMessage()}isTurnSuperseded(e){return e!==this.contextVersion}async executeSubmit(e,t,o){const s=Date.now();if(h("[ACodeRuntime] \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"),h("[ACodeRuntime] \u25B6\uFE0F executeSubmit STARTED"),h(`[ACodeRuntime] Message: <redacted, length=${e.length}>`),h(`[ACodeRuntime] \u{1F522} Context version: ${t}`),h("[ACodeRuntime] \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"),!this.state.started||this.state.terminated)throw console.error(`[ACodeRuntime] \u274C Runtime not active (started: ${this.state.started}, terminated: ${this.state.terminated})`),new Error("ACode runtime is not active");this.activeTurn=!0,this.abortRequested=!1;const i=this.activeTurnToken,r=e.trim();let a=!1;const l=o?.resume===!0&&this.turnPromptPushed;l||(this.turnPromptPushed=!1);try{let u;if(l)h("[ACodeRuntime] \u{1F501} resume turn: skip UserPromptSubmit hook (already ran in failed turn)"),u=[];else{h("[ACodeRuntime] \u{1F50D} Dispatching UserPromptSubmit hook...");const T=Date.now();u=await this.hookBus.dispatch("UserPromptSubmit",{prompt:r});const _=Date.now()-T;h(`[ACodeRuntime] \u2705 UserPromptSubmit hook completed in ${_}ms, results: ${u.length}`)}if(this.isTurnSuperseded(t)){h("[ACodeRuntime] \u26A0\uFE0F Turn superseded after hook, aborting");return}const c=Qe(u);if(c){console.error(`[ACodeRuntime] \u274C Prompt denied by hook: ${c.message}`),this.emitAcodeEvent("error",{message:c.message||"ACode prompt was denied by hook"}),this.emitAcodeEvent("turn_complete",{failed:!0}),a=!0,h("[ACodeRuntime] \u{1F4E4} Emitted turn_complete (failed=true) due to hook deny");return}h("[ACodeRuntime] \u{1F50D} Expanding command if any...");const d=this.state.commandRegistry.expand(r),p=d?.prompt.trim()||r,C=d?.command.allowedTools;if(d&&!l){h(`[ACodeRuntime] \u{1F4CB} Slash command detected: ${d.command.name}`),this.emitAcodeEvent("command_status",{action:"slash_command",command:d.command.name,arguments:d.argumentsText,sourcePath:d.command.sourcePath});const T=d.command.plugin;T&&h(`[ACodeRuntime] \u{1F4CB} Slash command belongs to plugin: ${T}`)}if(!this.state.provider.baseURL){h("[ACodeRuntime] \u26A0\uFE0F No provider baseURL configured, using fallback response");const T=Ms(p,this.state);this.emitAcodeEvent("assistant_delta",{text:T}),this.emitAcodeEvent("turn_complete",{usage:{inputTokens:p.length,outputTokens:T.length},usageEstimated:!0}),a=!0,h("[ACodeRuntime] \u{1F4E4} Emitted turn_complete (fallback mode)");return}if(l){if(h("[ACodeRuntime] \u{1F501} resume turn: user message already in conversation, skipping push"),this.isTurnSuperseded(t)){h("[ACodeRuntime] \uFE0F Turn superseded before resume runModelTurn, aborting");return}}else{h("[ACodeRuntime] \u{1F4CE} Parsing attachment message...");const T=Pe(p);if(T.hasImages&&!this.state.provider.supportsImageInput)throw console.error("[ACodeRuntime] \u274C Image input not supported by current provider"),new Error("ACode provider/model is not configured for image input. Enable provider.default.models[model].modalities.input including 'image' or options.supportsImageInput=true.");h("[ACodeRuntime] \u{1F5BC}\uFE0F Materializing image content if any...");const _=await yt(T.content);if(this.isTurnSuperseded(t)){h("[ACodeRuntime] \uFE0F Turn superseded after materializing content, aborting");return}h("[ACodeRuntime] \u{1F4AC} Adding user message to conversation"),this.state.conversation.push({role:"user",content:_}),this.turnPromptPushed=!0,h(`[ACodeRuntime] Conversation size: ${this.state.conversation.length} messages`)}h("[ACodeRuntime] Starting runModelTurn...");const y=Date.now(),m=await this.runModelTurn(C,t),f=Date.now()-y;if(h(`[ACodeRuntime] \u2705 runModelTurn completed in ${f}ms`),h(`[ACodeRuntime] \u{1F4DD} Result: text=${m.text?m.text.slice(0,80)+(m.text.length>80?"...":""):"(empty)"}, finishReason=${m.finishReason||"(none)"}`),this.isTurnSuperseded(t)){h("[ACodeRuntime] \uFE0F Turn superseded after runModelTurn, aborting");return}m.text&&!this.state.provider.stream&&(h("[ACodeRuntime] \u{1F4E4} Emitting assistant_delta (non-streaming mode)"),this.emitAcodeEvent("assistant_delta",{text:m.text})),h("[ACodeRuntime] \u{1F4E4} Emitting turn_complete..."),this.emitAcodeEvent("turn_complete",{usage:m.usage??{inputTokens:p.length,outputTokens:m.totalOutputTextLength??m.text.length},usageEstimated:!m.usage,...m.responseBody?{responseBody:m.responseBody}:{},...m.finishReason?{finishReason:m.finishReason}:{}}),ne(`turn_complete emitted: usage=${JSON.stringify(m.usage??{inputTokens:p.length,outputTokens:m.totalOutputTextLength??m.text.length})} (providerUsage=${m.usage?"real":"FALLBACK-text-length"}) textLength=${m.text.length} totalOutputTextLength=${m.totalOutputTextLength}`),h(`[ACodeRuntime] \u{1F4B0} Current context usage: input=${this.state.accumulatedInputTokens}, output=${this.state.accumulatedOutputTokens}`+(m.usage?"":" (estimated, no provider usage)")),a=!0,this.turnPromptPushed=!1;const g=Date.now()-s;h("[ACodeRuntime] \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"),h(`[ACodeRuntime] \u2705 executeSubmit COMPLETED in ${g}ms`),h("[ACodeRuntime] \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\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(u){const c=Date.now()-s;if(console.error(`[ACodeRuntime] \u274C executeSubmit FAILED after ${c}ms:`,u instanceof Error?u.message:String(u)),console.error("[ACodeRuntime] \u{1F50D} Error stack:",u instanceof Error?u.stack:"(no stack)"),this.isTurnSuperseded(t)){h("[ACodeRuntime] \uFE0F Turn superseded in error handler, skipping recovery");return}if(this.abortRequested){h("[ACodeRuntime] \u26A0\uFE0F Abort requested, emitting aborted turn_complete"),this.emitAcodeEvent("turn_complete",{aborted:!0}),a=!0;return}h("[ACodeRuntime] Emitting error and failed turn_complete..."),this.emitAcodeEvent("error",{message:u instanceof Error?u.message:String(u)}),this.emitAcodeEvent("turn_complete",{failed:!0}),a=!0}finally{const u=Date.now()-s;h(`[ACodeRuntime] \u{1F51A} executeSubmit finally block entered after ${u}ms`),h(`[ACodeRuntime] \u{1F50D} turnCompleted=${a}, activeTurn=${this.activeTurn}, abortRequested=${this.abortRequested}, contextVersion=${t}, currentContextVersion=${this.contextVersion}`),this.activeTurnToken===i&&(this.activeTurn=!1,this.abortRequested=!1),!a&&!this.isTurnSuperseded(t)&&(console.error(`[ACodeRuntime] \u{1F6A8} CRITICAL: executeSubmit finally block reached without turn_complete event! Duration: ${u}ms. This indicates a code path that should have emitted turn_complete but didn't. Forcing failed turn_complete to prevent state stuck.`),this.emitAcodeEvent("error",{message:"ACode turn completed without proper completion event (internal error)"}),this.emitAcodeEvent("turn_complete",{failed:!0}),h("[ACodeRuntime] Emergency turn_complete (failed=true) emitted"))}}async abort(){const e=this.abortController!==null,t=this.activeTurn;this.abortRequested=this.activeTurn,this.abortController?(h(`[ACodeRuntime] \u26D4 abort() calling abortController.abort() (activeTurn=${t})`),this.abortController.abort()):console.warn(`[ACodeRuntime] \u26D4 abort() called but abortController is null! activeTurn=${t}, abortRequested will be set to ${t}. This means abort() CANNOT cancel any running fetch/stream \u2014 if a built-in tool is executing, it will NOT be interrupted.`),this.abortController=null,this.rejectAllQuestionWaiters("aborted"),this.rejectAllPermissionWaiters("aborted"),this.cancelPendingAwaitedSubAgents(),this.cancelPendingAwaitedBgTasks(),this.notifyRuntimeStop(),this.armAbortForceSettle()}buildAskUserQuestionDeps(){return{onQuestion:(e,t)=>{this.emitAcodeEvent("question_request",{toolCallId:e,questions:t})},waitForAnswer:(e,t)=>new Promise((o,s)=>{this.questionWaiters.set(e,{resolve:o,reject:s,contextVersion:t})})}}async buildAllocatableToolList(){const e=this.state?.exposedTools??[],t=this.config.subAgentSuiteTools??[];let o=[];if(this.config.subAgentSuiteToolProvider)try{o=await this.config.subAgentSuiteToolProvider([])}catch{o=[]}return ge(e,ge(t,o))}buildSubAgentToolDeps(e){const t=this.config.agentId??"unknown",o=this.config.sessionId,s=this.config.workingDirectory,i=this.config;return{spawnSubAgent:async r=>{let a=this.config.subAgentSuiteTools;if(r.allowedTools&&r.allowedTools.length>0&&this.config.subAgentSuiteToolProvider)try{const u=await this.config.subAgentSuiteToolProvider(r.allowedTools);u.length>0&&(a=a?ge(a,u):u)}catch{}const l=await e.spawn({parentAgentId:t,parentSessionId:o,subagentType:r.subagentType,description:r.description,prompt:r.prompt,...r.allowedTools&&r.allowedTools.length>0?{allowedTools:r.allowedTools}:{},workingDirectory:s,parentConfig:{...i,sharedMcpConnections:this.state?.mcpConnections,...a&&a.length>0?{subAgentSuiteTools:a}:{}}});return await e.start(l),{subId:l}},listSubAgentToolCatalog:async()=>Ve(await this.buildAllocatableToolList()),listSubAgents:async()=>{const r=e.listByParent(t),a=[],l=[];for(const u of r){const c={subId:u.subId,subagentType:u.subagentType,description:u.description,status:u.status,startedAt:u.startedAt,endedAt:u.endedAt,durationMs:u.durationMs};u.status==="pending"||u.status==="running"?a.push(c):l.push(c)}return l.sort((u,c)=>(c.endedAt??0)-(u.endedAt??0)),{running:a,history:l}},getSubAgentStatus:async r=>{const a=e.getSubAgent(r);return a?{subId:a.subId,subagentType:a.subagentType,description:a.description,status:a.status,startedAt:a.startedAt,endedAt:a.endedAt,durationMs:a.durationMs,prompt:a.prompt,result:a.result,errorMessage:a.errorMessage,contextSnapshot:a.contextSnapshot}:null},awaitSubAgents:async(r,a)=>{const l=new Set;for(const u of r)this.pendingAwaitedSubIds.add(u),l.add(u);try{return await e.awaitCompletion(r,a)}finally{for(const u of l)this.pendingAwaitedSubIds.delete(u)}},abortSubAgent:r=>e.abort(r)}}buildAwaitCompleteDeps(){const e=this.config.agentId??"unknown",t=this.config.subAgentManager;return{agentId:e,awaitSubAgents:t?(o,s)=>{for(const i of o)this.pendingAwaitedSubIds.add(i);try{return this.buildSubAgentToolDeps(t).awaitSubAgents(o,s)}finally{for(const i of o)this.pendingAwaitedSubIds.delete(i)}}:null,awaitBgCommands:(o,s)=>{for(const i of o)this.pendingAwaitedBgTaskIds.add(i);try{return le.awaitCompletion(e,o,s)}finally{for(const i of o)this.pendingAwaitedBgTaskIds.delete(i)}}}}submitQuestionAnswer(e,t){return this.settleQuestionWaiter(e,{answers:t})}cancelQuestionAnswer(e,t){const o=String(t||"").trim();return this.settleQuestionWaiter(e,{cancelled:!0,...o?{reason:o}:{}})}settleQuestionWaiter(e,t){const o=this.questionWaiters.get(e);return o?(this.questionWaiters.delete(e),this.isTurnSuperseded(o.contextVersion)?(o.reject(new Error("turn superseded before user answered")),!1):(o.resolve(t),!0)):!1}rejectAllQuestionWaiters(e){if(this.questionWaiters.size!==0){for(const[,t]of this.questionWaiters)t.reject(new Error(`ask_user_question ${e}`));this.questionWaiters.clear()}}createToolPermissionController(){return{getLevel:e=>this.state.toolPermissionPolicy[e]??"allow",requestPermission:(e,t)=>this.requestToolPermission(e,t)}}requestToolPermission(e,t){const o=It();return new Promise(s=>{this.permissionWaiters.set(o,{capability:e,detail:t,resolve:s}),this.emitAcodeEvent("tool_permission_request",{requestId:o,capability:e,agentId:this.config.agentId,...t})})}submitToolPermissionDecision(e,t){const o=this.permissionWaiters.get(e);return o?(this.permissionWaiters.delete(e),o.resolve(t),!0):!1}rejectAllPermissionWaiters(e){if(this.permissionWaiters.size!==0){for(const[,t]of this.permissionWaiters)t.resolve(!1);this.permissionWaiters.clear(),U("tool-permission",`waiters rejected: ${e}`)}}setToolPermissionPolicy(e){this.state.toolPermissionPolicy={...this.state.toolPermissionPolicy,...e}}cancelPendingAwaitedSubAgents(){if(this.pendingAwaitedSubIds.size===0)return;const e=this.config.subAgentManager;if(!e)return;const t=Array.from(this.pendingAwaitedSubIds);h(`[ACodeRuntime] \u26D4 Cancelling ${t.length} pending awaited sub-agent(s): ${t.join(", ")}`);for(const o of t)e.abort(o).catch(s=>{h(`[ACodeRuntime] \u26A0\uFE0F manager.abort(${o}) threw: ${s instanceof Error?s.message:String(s)}`)})}cancelPendingAwaitedBgTasks(){if(this.pendingAwaitedBgTaskIds.size===0)return;const e=this.config.agentId??"unknown",t=Array.from(this.pendingAwaitedBgTaskIds);h(`[ACodeRuntime] \u26D4 Cancelling ${t.length} pending awaited background command(s): ${t.join(", ")}`),le.interruptAwaits(e,t)}detachCurrentToolExecution(e){const t=e?this.toolSettleSlots.get(e):this.pickSettleCandidate();return!t||!t.settlable||t.settled?!1:(t.settled=!0,t.resolveSettle?.(),h(`[ACodeRuntime] \u{1F680} detachCurrentToolExecution: settling tool ${t.toolName} (toolCallId=${t.toolCallId}) to background`),!0)}pickSettleCandidate(){let e=null;for(const t of this.toolSettleSlots.values())!t.settlable||t.settled||(e===null||t.order<e.order)&&(e=t);return e}beginToolSettle(e,t,o){const s=e.toolName==="Bash",i=++this.toolSettleSeq;let r;const a=s?new Promise(l=>{r=l}):void 0;return this.toolSettleSlots.set(o,{seq:i,toolName:e.toolName,toolCallId:o,settlable:s,settled:!1,resolveSettle:r??null,order:i}),{seq:i,signal:a}}clearToolSettle(e,t){if(t!==void 0){this.toolSettleSlots.get(t)?.seq===e&&this.toolSettleSlots.delete(t);return}for(const[o,s]of this.toolSettleSlots)if(s.seq===e){this.toolSettleSlots.delete(o);return}}async stop(){if(this.state.terminated)return;this.state.terminated=!0,this.notifyRuntimeStop(),this.abortRequested=this.activeTurn,this.abortController?.abort(),this.abortController=null,this.armAbortForceSettle(),this.rejectAllQuestionWaiters("session terminated"),this.rejectAllPermissionWaiters("session terminated"),this.readFileStateTracker.clear(),this.cancelPendingAwaitedSubAgents(),this.cancelPendingAwaitedBgTasks(),await ie("ACode active turn shutdown",this.submitQueue,t=>{this.emitAcodeEvent("error",{message:t})}),await this.disconnectMcpServers();const e=this.config.agentId||"unknown";if(await ie("ACode background commands shutdown",le.disposeAgent(e),t=>{this.emitAcodeEvent("error",{message:t})}),ie("ACode agent PTY sessions shutdown",Promise.resolve(this.config.terminalManager?.killByAgent?.(e)),t=>{this.emitAcodeEvent("error",{message:t})}),await ie("ACode Stop hooks",this.hookBus.dispatch("Stop",{reason:"session_stop"}),t=>{this.emitAcodeEvent("error",{message:t})}),this.state.terminated=!0,this.sessionCompleteEmitted||(this.sessionCompleteEmitted=!0,this.emitAcodeEvent("session_complete",{exitCode:0})),this.stopCompactionDebugLog(),this.stopSkillWatchers(),be)try{D.promises.appendFile(pt,`[${new Date().toISOString()}] runtime stopped | ---
17
+ `,"utf-8").catch(()=>{})}catch{}}discoverPluginCommandDirs(){const e=this.config.pluginsDir;if(!e)return[];let t;try{t=D.readdirSync(e)}catch{return[]}const o=[];for(const s of t){if(s.startsWith("."))continue;const i=z.join(e,s);let r;try{r=D.statSync(i)}catch{continue}if(!r.isDirectory())continue;const a=z.join(i,"commands");let l;try{D.existsSync(a)&&(l=D.statSync(a))}catch{l=void 0}l?.isDirectory()&&o.push(a)}return o}resolveCommandDirs(e){const t=[...this.config.commandDirs??[],...e.commandDirs??[],...e.commands?.directories??[]];return[...new Set(t.map(o=>o.trim()).filter(Boolean))]}async runModelTurn(e,t=this.contextVersion){let o="",s,i,r,a="",l=0;this.lastIterationUsage=void 0,h(`[ACodeRuntime] \u25B6\uFE0F runModelTurn started (contextVersion: ${t})`);const u=50;for(let c=0;c<u;c+=1){if(h(`[ACodeRuntime] \u{1F504} Iteration ${c+1} starting...`),this.isTurnSuperseded(t))return h(`[ACodeRuntime] \u26A0\uFE0F Turn superseded at iteration ${c+1}, aborting`),{text:"",totalOutputTextLength:a.length};await this.injectForceMessage();const d=Date.now(),p=await this.requestChatCompletion(e),C=Date.now()-d;if(h(`[ACodeRuntime] \u{1F916} AI request completed in ${C}ms, choices: ${p.choices?.length||0}`),this.isTurnSuperseded(t))return h(`[ACodeRuntime] \u26A0\uFE0F Turn superseded after AI response at iteration ${c+1}`),{text:"",totalOutputTextLength:a.length};if(this.state.terminated)throw h(`[ACodeRuntime] Runtime terminated at iteration ${c+1}`),new Error("ACode runtime was stopped during the active turn");const y=p.choices?.[0];i=JSON.stringify(p,null,2),r=typeof y?.finish_reason=="string"?y.finish_reason:void 0;const m=y?.message,f=typeof m?.content=="string"?m.content:"",g=kt(m),T=Array.isArray(m?.tool_calls)?Rt(m.tool_calls):[];if(h(`[ACodeRuntime] AI response: content=${f?f.slice(0,100)+(f.length>100?"...":""):"(empty)"}, toolCalls=${T.length}, finishReason=${r||"(none)"}`),p.usage){const k=J(p.usage.prompt_tokens??p.usage.input_tokens),$=J(p.usage.completion_tokens??p.usage.output_tokens),v=k!==void 0,B=$!==void 0;if(ne(`provider usage parsed: raw=${JSON.stringify(p.usage)} input=${k} output=${$} hasInput=${v} hasOutput=${B} iteration=${c+1}`),v||B){const I=Io(p.usage,k),L=s?.outputTokens??a.length+f.length;this.state.accumulatedCacheHitTokens+=I?.cacheHitTokens??0,this.state.accumulatedCacheMissTokens+=I?.cacheMissTokens??0,s={inputTokens:v?k:s?.inputTokens??0,outputTokens:B?$:L,cacheHitTokens:this.state.accumulatedCacheHitTokens,cacheMissTokens:this.state.accumulatedCacheMissTokens},this.lastIterationUsage=s,this.emitAcodeEvent("iteration_usage",{inputTokens:s.inputTokens,outputTokens:s.outputTokens,cacheHitTokens:s.cacheHitTokens,cacheMissTokens:s.cacheMissTokens}),l+=v?k:0,this.state.accumulatedInputTokens=v?k:this.state.accumulatedInputTokens,this.state.accumulatedOutputTokens=B?$:this.state.accumulatedOutputTokens,ne(`finalUsage updated: ${JSON.stringify(s)} (cacheUsage=${JSON.stringify(I??null)})`),h(`[ACodeRuntime] \u{1F4B0} Token usage: input=${s.inputTokens}, output=${s.outputTokens} (turn accumulated cost: input=${l})`),h(I?`[ACodeRuntime] \u{1F4B0} Cache usage (provider reported): hit=${I.cacheHitTokens}, miss=${I.cacheMissTokens}`:'[ACodeRuntime] \u{1F4B0} Cache usage: provider usage \u4E2D\u65E0\u7F13\u5B58\u5B57\u6BB5\uFF08\u9762\u677F\u5C06\u663E\u793A "-"\uFF09')}}else ne(`provider response has NO usage field (fallback to text-length estimate), iteration=${c+1}`);if(this.state.conversation.push({role:"assistant",content:f||null,tool_calls:T.length>0?T:void 0,...g?{reasoning:g.slice(0,Ie)}:{}}),f&&(o=f,a+=f,h(`[ACodeRuntime] \u2728 Captured assistant text: ${f.slice(0,80)}...`)),T.length===0)return h(`[ACodeRuntime] \u2705 No tool calls at iteration ${c+1}, completing turn`),{text:o,usage:s,responseBody:i,finishReason:r,totalOutputTextLength:a.length};const _=T.map(k=>k.function.name).join(", ");h(`[ACodeRuntime] \u{1F527} Executing ${T.length} tool(s) at iteration ${c+1}: ${_}`);const b=Date.now();await this.handleToolCalls(T,e,t);const S=Date.now()-b;if(h(`[ACodeRuntime] \u2699\uFE0F Tool execution completed in ${S}ms at iteration ${c+1}`),this.isTurnSuperseded(t))return h(`[ACodeRuntime] \u26A0\uFE0F Turn superseded after tool execution at iteration ${c+1}`),{text:"",totalOutputTextLength:a.length};h(`[ACodeRuntime] \u{1F504} Preparing iteration ${c+2}...`)}return console.error(`[ACodeRuntime] \u{1F6A8} CRITICAL: Reached safety limit of ${u} iterations! This indicates a potential infinite loop. Forcing turn completion.`),{text:o||`ACode \u5DF2\u8FBE\u5230\u5B89\u5168\u8FED\u4EE3\u4E0A\u9650\uFF08${u}\u6B21\uFF09\uFF0C\u5F3A\u5236\u7ED3\u675F\u672C\u8F6E\u5BF9\u8BDD\u3002`,usage:s,responseBody:i,finishReason:r||"safety_iteration_limit_reached",totalOutputTextLength:a.length}}async summarizeConversationWithLLM(e){const t=this.state.provider,o=t.baseURL;if(!o)throw new Error("ACode provider baseURL is not configured for LLM summarization");const s={"Content-Type":"application/json"};t.apiKey&&(s.Authorization=`Bearer ${t.apiKey}`);const i=[];if(e.prefixMessages?.length)for(const c of e.prefixMessages)i.push(c);for(const c of e.messages)i.push(c);const r=[];if(e.previousSummary&&r.push(`Summary of an even earlier part of this conversation (already compacted once):
18
18
 
19
- --- Conversation Start ---
20
- ${e.conversationText}
21
- --- Conversation End ---
19
+ `+e.previousSummary),e.anchors&&!ao(e.anchors)&&r.push(uo(e.anchors)),e.reasoningText&&r.push(`The assistant's internal reasoning during the conversation above is provided below for context. Use it only to understand what was being attempted; do not mention it explicitly.
22
20
 
23
- `+Xt}]},r=new AbortController;this.abortController=r;let a=!1;try{return await $((async()=>{const l=await $(fetch(be(o),{method:"POST",headers:s,body:JSON.stringify(i),signal:r.signal}),t.requestTimeoutMs,"ACode LLM summarization",()=>{a=!0,r.abort()});if(!l.ok){const m=await $(l.text(),t.requestTimeoutMs,"ACode LLM summarization error response body",()=>{a=!0,r.abort()}),h=m.length>500?`${m.slice(0,500)}...(truncated, total ${m.length} chars)`:m;throw new Error(`ACode LLM summarization request failed: ${l.status} ${h}`)}if(!l.body)throw new Error("ACode LLM summarization stream response has no body");const u=l.body.getReader(),c=new TextDecoder;let d="",p="";const T=m=>{for(const h of At(m)){if(h==="[DONE]")continue;let g;try{g=JSON.parse(h)}catch{continue}if(!S(g))continue;const y=Ie(g);if(y)throw new Error(`ACode LLM summarization failed: ${y}`);const w=g.choices?.[0]?.delta?.content,A=typeof w=="string"?w:"";A&&(d+=A,this.emitAcodeEvent("compaction_summary",{text:A}))}};for(;;){const{done:m,value:h}=await $(u.read(),t.requestTimeoutMs,"ACode LLM summarization idle",()=>r.abort());if(m)break;p+=c.decode(h,{stream:!0});const g=p.split(/\r?\n\r?\n/);p=g.pop()??"";for(const y of g)T(y)}p+=c.decode(),p.trim()&&T(p);const _=d;if(!_||_.trim().length===0)throw new Error("ACode LLM summarization returned empty content");return _})(),t.requestTotalTimeoutMs,"ACode LLM summarization total",()=>{r.abort()})}catch(l){throw l instanceof Error&&l.name==="AbortError"?a?new Error(`ACode LLM summarization timed out after ${t.requestTimeoutMs}ms`):new Error("ACode LLM summarization aborted"):l}finally{this.abortController===r&&(this.abortController=null)}}async requestChatCompletion(e){const t=this.state.provider,o=t.baseURL;if(!o)throw new Error("ACode provider baseURL is not configured");this.instructionsDirty&&(this.instructionsDirty=!1,this.rebuildRuntimeInstructionsMessage());const{contextLimit:s,maxOutput:i,inputLimit:r,threshold:a}=Ae(t),l=this.state.accumulatedInputTokens+this.state.accumulatedOutputTokens,u=j(this.state.conversation)+ie(this.state.exposedTools),c=Math.max(l,u),d=c>=a,p=this.compactRequested;this.compactRequested=!1,f(`[ACodeRuntime] \u{1F50D} Compaction check: actualUsed=${l}, estimation=${u}, effectiveUsed=${c}, contextLimit=${s}, inputLimit=${r??"n/a"}, maxOutput=${i}, triggerThreshold=${a}, shouldCompact=${d}, manualCompact=${p}`),p?await this.runCompactionPass({contextLimit:s,maxOutput:i,effectiveUsed:c,trigger:"manual",force:!0,detectLabel:"\u624B\u52A8\u89E6\u53D1\u4E0A\u4E0B\u6587\u538B\u7F29",detectDetail:`\u7528\u6237\u8BF7\u6C42\u5148\u884C\u538B\u7F29\uFF0C\u5F53\u524D\u4F30\u7B97\u7528\u91CF: ${c} tokens`}):d&&await this.runCompactionPass({contextLimit:s,maxOutput:i,effectiveUsed:c,trigger:l>=a?"actual_usage":"estimated_overflow",force:!1,detectLabel:"\u68C0\u6D4B\u5230\u4E0A\u4E0B\u6587\u6EA2\u51FA",detectDetail:`\u6709\u6548\u7528\u91CF: ${c} tokens, \u9608\u503C: ${a}, \u89E6\u53D1: ${l>=a?"\u5B9E\u9645\u7528\u91CF":"\u4F30\u7B97\u6EA2\u51FA"}`});const T=Do(s);let _=Lo()||d;if(!_){const b=Fe(this.state.conversation);b>it?_=!0:b>T&&f(`[ACodeRuntime] \u23ED\uFE0F Byte-cap truncation skipped: body ${b}B > cap ${T}B, but effectiveUsed ${c} < threshold ${a} (aligned with frontend compression marker; rely on provider 413/overflow fallback)`)}let m=ft,h=0,g=0,y=0;if(_&&(h=Y(this.state.conversation),g=j(this.state.conversation),y=this.state.conversation.length,m=await fs(this.state.conversation,T,s,i,b=>this.summarizeConversationWithLLM(b),()=>this.rebuildRuntimeResourcesMessage())),m.truncatedCount>0){const b=`compaction-bytes-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;this.emitAcodeEvent("context_compaction",{action:"start",compactionId:b,sizeKB:h,estimatedTokens:g,actualInputTokens:this.state.accumulatedInputTokens,actualOutputTokens:this.state.accumulatedOutputTokens,messageCount:y,model:t.model,trigger:"request_body_byte_limit"}),this.emitCompactionPhase(b,"byte_limit_detect","\u68C0\u6D4B\u5230\u8BF7\u6C42\u4F53\u8D85\u9650",`\u8BF7\u6C42\u4F53\u8D85\u8FC7 ${T} \u5B57\u8282\u4E0A\u9650\uFF0C\u5373\u5C06\u88C1\u526A\u5386\u53F2`,"request_body_byte_limit");const P=Y(this.state.conversation),Q=j(this.state.conversation);this.emitAcodeEvent("context_compaction",{action:"end",compactionId:b,sizeBeforeKB:h,sizeAfterKB:P,freedKB:Math.round((h-P)*10)/10,strategy:m.strategy,freedTokens:m.freedTokens,tokensBefore:g,tokensAfter:Q,prunedToolMessages:m.prunedToolMessages,summarizedMessages:m.summarizedMessages,messageCountBefore:y,messageCountAfter:this.state.conversation.length,trigger:"request_body_byte_limit"}),this.emitAcodeEvent("warning",{message:`Conversation truncated: removed ${m.truncatedCount} older messages to fit within ${T} byte request size limit`}),this.state.accumulatedInputTokens=0,this.state.accumulatedOutputTokens=0}const w=()=>{const b=hs(this.state.conversation);(b.orphanToolMessages>0||b.repairedToolCalls>0||b.downgradedAssistants>0||b.relocatedInterruptions>0||b.reorderedToolResults>0)&&(f(`[ACodeRuntime] \u{1FA79} sanitizeToolCallSequence: orphanTools=${b.orphanToolMessages} repairedCalls=${b.repairedToolCalls} downgradedAssistants=${b.downgradedAssistants} relocatedInterruptions=${b.relocatedInterruptions} reorderedToolResults=${b.reorderedToolResults}`),this.emitAcodeEvent("warning",{message:`\u68C0\u6D4B\u5230\u5DE5\u5177\u8C03\u7528\u5E8F\u5217\u4E0D\u5B8C\u6574\uFF0C\u5DF2\u81EA\u52A8\u4FEE\u590D\uFF08\u5B64\u513F\u5DE5\u5177\u7ED3\u679C ${b.orphanToolMessages} \u6761\u3001\u8865\u5360\u4F4D\u7ED3\u679C ${b.repairedToolCalls} \u4E2A\u3001\u964D\u7EA7 assistant \u6D88\u606F ${b.downgradedAssistants} \u6761\u3001\u56DE\u6B63\u7A7F\u63D2\u6D88\u606F ${b.relocatedInterruptions} \u6761\u3001\u56DE\u6B63\u9519\u5E8F\u7ED3\u679C ${b.reorderedToolResults} \u6761\uFF09\uFF0C\u907F\u514D provider 400 (tool_call_sequence_broken) \u6B7B\u5FAA\u73AF\u3002`}))};w();const A=this.state.exposedTools.filter(b=>this.toolGroupManager&&!this.toolGroupManager.shouldShowToLLMByName(b.exposedName)?!1:ls(b,this.state.permissions,e)),N=()=>{const b={model:t.model,messages:bo(this.state.conversation),stream:t.stream};return t.effort&&(b.reasoning_effort=t.effort),t.stream&&(b.stream_options={include_usage:!0}),A.length>0&&(b.tools=_t(A),b.tool_choice="auto"),b},k="POST",v=cs(o),M=ws(t),L=ks(M),E=b=>{const P=JSON.stringify(b,null,2);f(`[ACodeRuntime] \u2605\u2605\u2605 DEBUG \u2605\u2605\u2605 emitAiRequest: \u53D1\u9001\u8BF7\u6C42 model=${t.model}, endpoint=${v}, messageCount=${this.state.conversation.length}`),this.emitAcodeEvent("ai_request",{model:t.model,endpoint:v,requestMethod:k,requestUrl:v,requestHeaders:L,stream:t.stream,messageCount:this.state.conversation.length,toolCount:A.length,lastUserMessagePreview:us(this.state.conversation),estimatedContextTokens:Ee(P),...this.lastIterationUsage?{lastUsage:this.lastIterationUsage}:{}}),oe(`ai_request emitted: model=${t.model} stream=${t.stream} messageCount=${this.state.conversation.length} toolCount=${A.length} estimatedContextTokens=${Ee(P)} lastUsage=${JSON.stringify(this.lastIterationUsage??null)}`)};let O=N();E(O);const U=t.requestRetryCount===ve,re=U?1/0:t.requestRetryCount+1;let ee=!1;for(let b=1;U||b<=re;b+=1){this.state.terminated||(this.abortRequested=!1),b>1&&E(O);const P=new AbortController;this.abortController=P;let Q=!1;try{const q=await $((async()=>{const J=t.stream?t.requestFirstByteTimeoutMs:t.requestTotalTimeoutMs,F=await $(fetch(be(o),{method:k,headers:M,body:JSON.stringify(O),signal:P.signal}),J,"ACode provider request",()=>{Q=!0,P.abort()});if(!F.ok){const C=await $(F.text(),t.requestStreamIdleTimeoutMs,"ACode provider error response body",()=>{Q=!0,P.abort()}),R=C.length>500?`${C.slice(0,500)}...(truncated, total ${C.length} chars)`:C,ae=Ne(this.state.conversation,F.status,C)??"";throw new Error(`ACode provider request failed: ${F.status} ${R}${ae}`)}const V=F.headers?.get?.("content-type")||"";if(t.stream&&V.toLowerCase().includes("text/event-stream"))return await this.readChatCompletionStream(F,t.requestStreamIdleTimeoutMs,P,t.requestFirstByteTimeoutMs);const X=await $(F.json(),t.requestStreamIdleTimeoutMs,"ACode provider response body",()=>{Q=!0,P.abort()});if(!S(X))return this.emitAcodeEvent("warning",{message:`ACode provider returned invalid response format (expected object, got ${typeof X}); treating as empty response`}),{};const K=Ie(X);if(K){const C=Ne(this.state.conversation,F.status,K)??"";throw new Error(`ACode provider request failed: ${K}${C}`)}return X})(),t.requestTotalTimeoutMs,"ACode provider request total",()=>{P.abort()}),x=ro({finishReason:q.choices?.[0]?.finish_reason,stopReason:q.choices?.[0]?.stop_reason});if(x.kind==="context_overflow"){if(!ee&&await this.compactForContextOverflow({contextLimit:s,trigger:"finish_reason_context_overflow",warningMessage:`ACode provider reported context overflow via ${x.source} (${x.marker}); summarized older messages and rebuilt the request instead of accepting the truncated payload`})>0){ee=!0,w(),O=N(),E(O),b-=1;continue}this.emitAcodeEvent("warning",{message:`ACode provider reported context overflow via ${x.source} (${x.marker}), but no further compaction was possible`})}return q}catch(q){let x;if(q instanceof Error&&q.name==="AbortError"?Q?x=new Error(`ACode provider request timed out (firstByte=${t.requestFirstByteTimeoutMs}ms, idle=${t.requestStreamIdleTimeoutMs}ms)`):this.state.terminated?x=new Error("ACode provider request aborted by user"):x=new Error(`ACode provider request timed out (watchdog abort, firstByte=${t.requestFirstByteTimeoutMs}ms, idle=${t.requestStreamIdleTimeoutMs}ms)`):x=q instanceof Error?q:new Error(String(q)),!ee&&!this.abortRequested&&!this.state.terminated&&(we(q)||we(x))){if(await this.compactForContextOverflow({contextLimit:s,trigger:"provider_overflow_error",warningMessage:"ACode provider context limit exceeded; summarized older messages and rebuilt the request instead of retrying the same oversized payload"})===0)throw x;ee=!0,w(),O=N(),E(O),b-=1;continue}if(!((U||b<re)&&!this.abortRequested&&!this.state.terminated&&ys(x)))throw x;this.emitAcodeEvent("error",{message:`ACode provider request attempt ${b}${U?"":`/${re}`} failed; retrying: ${x.message}`,nonFatal:!0});const F=Math.min(Eo,$o*Math.pow(2,b-1)),V=Math.random()*1e3;await jo(F+V)}finally{this.abortController===P&&(this.abortController=null)}}throw new Error("ACode provider request failed after all retries")}async compactForContextOverflow(e){const{contextLimit:t,trigger:o,warningMessage:s}=e,i=Y(this.state.conversation),r=j(this.state.conversation),a=this.state.conversation.length,l=`compaction-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;this.emitAcodeEvent("context_compaction",{action:"start",compactionId:l,sizeKB:i,estimatedTokens:r,messageCount:a,model:this.state.provider.model,trigger:o}),this.emitCompactionPhase(l,"detect","\u68C0\u6D4B\u5230\u4E0A\u4E0B\u6587\u6EA2\u51FA",`\u6D88\u606F: ${a}\u6761, \u5927\u5C0F: ${i}KB`),this.emitCompactionPhase(l,"prune","\u9636\u6BB51: \u88C1\u526A\u5DE5\u5177\u8F93\u51FA","\u6B63\u5728\u88C1\u526A...");const u=so(this.state.conversation,t);this.emitCompactionPhase(l,"prune_done","\u9636\u6BB51: \u88C1\u526A\u5DE5\u5177\u8F93\u51FA",`\u88C1\u526A\u4E86 ${u.prunedCount} \u6761\u5DE5\u5177\u8F93\u51FA, \u91CA\u653E ${u.freedTokens} tokens`),this.emitCompactionPhase(l,"summarize","\u9636\u6BB52: \u6458\u8981\u5316\u5BF9\u8BDD","\u6B63\u5728\u6458\u8981...");const c=await ze(this.state.conversation,{llmSummarizer:m=>this.summarizeConversationWithLLM(m),contextLimit:t});this.emitCompactionPhase(l,"summarize_done","\u9636\u6BB52: \u6458\u8981\u5316\u5BF9\u8BDD",`\u6458\u8981\u5316\u4E86 ${c} \u6761\u6D88\u606F`);const d=Y(this.state.conversation),p=j(this.state.conversation),T=this.state.conversation.length,_=u.prunedCount+c;return this.emitAcodeEvent("context_compaction",{action:"end",compactionId:l,sizeBeforeKB:i,sizeAfterKB:d,freedKB:Math.round((i-d)*10)/10,tokensBefore:r,tokensAfter:p,messageCountBefore:a,messageCountAfter:T,strategy:c>0?"summarize":"prune",freedTokens:u.freedTokens,prunedToolMessages:u.prunedCount,summarizedMessages:c,trigger:o}),_===0?0:(this.state.accumulatedInputTokens=0,this.state.accumulatedOutputTokens=0,c>0&&await this.rebuildRuntimeResourcesMessage(),this.rebuildRuntimeInstructionsMessage(),this.emitAcodeEvent("warning",{message:s}),_)}async rebuildRuntimeResourcesMessage(){const e=this.config.runtimeResourcesProvider;if(!e)return;const t=this.state.conversation;for(let l=t.length-1;l>=0;l--)eo(t[l])&&t.splice(l,1);let o;try{o=await e()}catch(l){f(`[ACodeRuntime] runtime resources provider failed, snapshot skipped: ${me(l)}`);return}const s=typeof o=="string"?o.trim():"";if(!s)return;let i=0,r=-1;for(let l=0;l<t.length;l++){const u=t[l];if(u.role!=="system")break;Zt(u)&&(r=l),i=l+1}const a=r>=0?r+1:i;t.splice(a,0,{role:"system",content:`${no}
24
- ${s}`})}rebuildRuntimeInstructionsMessage(){if(!this.state?.started||this.state.terminated)return;const e=this.state.conversation;for(let i=e.length-1;i>=0;i--)to(e[i])&&e.splice(i,1);const t=this.buildRuntimeInstructionsContent();if(!t)return;const o=(()=>{for(let i=0;i<e.length;i++)if(e[i].role!=="system")return i;return e.length})();let s=o;for(let i=0;i<o;i++){const r=e[i];if(r.role==="system"&&typeof r.content=="string"&&r.content.startsWith("[Runtime Environment]")){s=i;break}}e.splice(s,0,{role:"system",content:t})}buildRuntimeInstructionsContent(){const e=this.state.provider,t=this.state.skills??[],o=this.state.commands??[],s=Tt(t),i=Ct(o),r=this.toolGroupManager?.buildCapabilityPrompt()??"",a=this.config.pluginBridge?["","## \u63D2\u4EF6\u7CFB\u7EDF","\u5DF2\u5B89\u88C5\u63D2\u4EF6\u4EE5\u6536\u7EB3\u7EC4\u5F62\u5F0F\u5217\u51FA\uFF08\u89C1\u4E0A\u65B9\u300C\u53EF\u7528\u80FD\u529B\u300D\u4E2D\u7684 plugin:{\u63D2\u4EF6\u540D} \u6761\u76EE\uFF09\u3002",'\u9700\u8981\u67D0\u63D2\u4EF6\u7684\u5DE5\u5177\u65F6\uFF0C\u5148 expand_tools({ group: "plugin:\u63D2\u4EF6\u540D" }) \u5C55\u5F00\uFF1B','\u5DE5\u5177\u5B9A\u4E49\uFF08\u542B\u53C2\u6570 schema\uFF09\u968F\u5C55\u5F00\u7ED3\u679C\u8FD4\u56DE\uFF0C\u518D\u7528 call_tool({ name: "\u63D2\u4EF6\u540D.\u5DE5\u5177\u540D", arguments: {...} }) \u8C03\u7528\u3002'].join(`
25
- `):"";return[De,e.systemPrompt,s,i,r+a].map(l=>l?.trim()).filter(l=>!!l).join(`
21
+ `+e.reasoningText),i.push({role:"user",content:(r.length>0?`${r.join(`
26
22
 
27
- `)}async readChatCompletionStream(e,t,o,s){if(!e.body)throw new Error("ACode provider stream response has no body");const i=e.body.getReader(),r=new TextDecoder,a=new Map;let l="",u="",c="",d,p,T;const _=h=>{for(const g of At(h)){if(g==="[DONE]")continue;const y=JSON.parse(g);if(!S(y))continue;const w=Ie(y);if(w){o?.abort();const E=Ne(this.state.conversation,200,w)??"";throw new Error(`ACode provider request failed: ${w}${E}`)}const A=y.usage;A&&(d=ko(d,A),oe(`stream usage chunk received: ${JSON.stringify(A)} -> merged: ${JSON.stringify(d)}`));const N=y.choices?.[0];typeof N?.finish_reason=="string"&&N.finish_reason&&(p=N.finish_reason),typeof N?.stop_reason=="string"&&N.stop_reason&&(T=N.stop_reason);const k=N?.delta,v=yt(k);v&&(u.length<$e&&(u+=v.slice(0,$e-u.length)),this.emitAcodeEvent("thinking_delta",{text:v}));const M=typeof k?.content=="string"?k.content:"";M&&(l+=M,this.emitAcodeEvent("assistant_delta",{text:M}));const L=Array.isArray(k?.tool_calls)?k.tool_calls:[];for(const E of L)$s(a,E)}};let m=!0;for(;;){const h=m&&s?s:t,{done:g,value:y}=await $(i.read(),h,m?"ACode provider stream first byte":"ACode provider stream idle",()=>o?.abort());if(m=!1,g)break;c+=r.decode(y,{stream:!0});const w=c.split(/\r?\n\r?\n/);c=w.pop()??"";for(const A of w)_(A)}return c+=r.decode(),c.trim()&&_(c),{choices:[{message:{content:l||null,tool_calls:Es(a),...u?{reasoning:u}:{}},...p?{finish_reason:p}:{},...T?{stop_reason:T}:{}}],...d?{usage:d}:{}}}async handleToolCalls(e,t,o=this.contextVersion){f(`[ACodeRuntime] handleToolCalls started with ${e.length} tool(s)`);const s=e.filter(l=>!Se(l.function.name)),i=l=>!Se(l.function.name),r=this.toolConcurrencyEnabled&&s.length>1?{batchId:lt(),toolCount:s.length}:void 0;r&&!this.isTurnSuperseded(o)&&this.emitToolBatchStart(r,s);const a=[];for(const l of e){if(this.isTurnSuperseded(o))break;a.push(await this.prepareToolCall(l,t,o,i(l)?r:void 0))}for(let l=a.length;l<e.length;l++){const u=e[l];a.push({toolCall:u,batchId:i(u)?r?.batchId:void 0,tool:void 0,arguments:{},mode:"blocking",scope:"unknown",access:"exclusive",claims:[],immediateError:void 0})}this.toolConcurrencyEnabled&&a.length>1?await this.executePreparedToolCallsConcurrently(a,o,r):await this.executePreparedToolCallsSerially(a,o),f(`[ACodeRuntime] handleToolCalls completed for all ${e.length} tool(s)`)}emitToolBatchStart(e,t){const o=t.map(s=>s.function.name);f(`[ACodeRuntime] \u{1F9E9} Tool batch ${e.batchId} started: tools=${e.toolCount} [${o.join(", ")}]`),this.emitAcodeEvent("mcp_status",{action:"tool_batch_start",server:"builtin",batchId:e.batchId,toolCount:e.toolCount,toolNames:o})}async executePreparedToolCallsConcurrently(e,t,o){const s=e.map(p=>({toolCallId:p.toolCall.id,toolName:p.tool?.exposedName??p.toolCall.function.name,mode:p.mode,scope:p.scope,claims:p.claims})),i=this.toolConcurrencyScheduler.schedule(s),r=o?.batchId??lt(),a=new Qe(r),l=new Set(e.filter(p=>!Se(p.toolCall.function.name)).map(p=>p.toolCall.id));for(const p of e)l.has(p.toolCall.id)&&a.register({toolCallId:p.toolCall.id,toolName:p.tool?.exposedName??p.toolCall.function.name,mode:p.mode,resourceKeys:(i.plans.get(p.toolCall.id)?.claims??[]).map(T=>T.key)});const u=new Map,c=new Map(e.map(p=>[p.toolCall.id,p]));for(const p of i.waves){if(this.isTurnSuperseded(t))break;const T=p.planIds.map(m=>c.get(m)).filter(m=>m!==void 0);if(T.length===0)continue;(await Promise.allSettled(T.map(m=>this.executeOnePreparedTool(m,a,t)))).forEach((m,h)=>{const g=T[h];u.set(g.toolCall.id,m.status==="fulfilled"?m.value:{toolCallId:g.toolCall.id,status:"failed",error:m.reason})})}if(await this.commitPreparedToolOutcomes(e,u,a,t),!o)return;const d=a.finalize();f(`[ACodeRuntime] \u26A1 Tool batch ${r}: tools=${d.toolCount} speedup=${d.speedup}x parallelism=${d.parallelism}x wall=${d.wallClockMs}ms contentions=${d.contentionCount} failures=${d.failureCount}`),this.emitAcodeEvent("mcp_status",{action:"tool_batch_metrics",server:"builtin",batchId:r,toolCount:d.toolCount,parallelism:d.parallelism,speedup:d.speedup,wallClockMs:d.wallClockMs,totalWaitMs:d.totalWaitMs,contentionCount:d.contentionCount,failureCount:d.failureCount,maxConcurrentObserved:d.maxConcurrentObserved,traces:d.traces.map(p=>({toolCallId:p.toolCallId,toolName:p.toolName,mode:p.mode,resourceKeys:p.resourceKeys,waitMs:p.waitDurationMs,runMs:p.executionDurationMs,status:p.status}))})}async executePreparedToolCallsSerially(e,t){const o=new Qe(`toolbatch-serial-${Date.now().toString(36)}`),s=new Map;for(const i of e)o.register({toolCallId:i.toolCall.id,toolName:i.tool?.exposedName??i.toolCall.function.name,mode:i.mode,resourceKeys:i.claims.map(r=>r.key)}),!this.isTurnSuperseded(t)&&s.set(i.toolCall.id,await this.executeOnePreparedTool(i,o,t));await this.commitPreparedToolOutcomes(e,s,o,t)}async commitPreparedToolOutcomes(e,t,o,s){const i=[];for(const r of e){if(this.isTurnSuperseded(s)){this.commitSupersededToolResult(r),o.transition(r.toolCall.id,"superseded");continue}const a=t.get(r.toolCall.id);if(!a){await this.commitToolOutcome(r,{toolCallId:r.toolCall.id,status:"failed",error:r.immediateError??new Error("Tool was not executed")},s,i),o.transition(r.toolCall.id,"committed");continue}o.transition(r.toolCall.id,"committing"),await this.commitToolOutcome(r,a,s,i),o.transition(r.toolCall.id,"committed")}i.length>0&&this.state.conversation.push(...i)}async executeOnePreparedTool(e,t,o){if(e.immediateError!==void 0||!e.tool){t.transition(e.toolCall.id,"failed");const a=e.immediateError??new Error("Tool not found");return t.setError(e.toolCall.id,a instanceof Error?a.message:String(a)),{toolCallId:e.toolCall.id,status:"failed",error:a}}t.transition(e.toolCall.id,"waiting_resource");const s=await this.toolResourceLock.acquire(e.claims,e.access),i=this.resolveToolLimiter(e),r=i?await i.acquire():()=>{};try{if(this.isTurnSuperseded(o))return{toolCallId:e.toolCall.id,status:"superseded"};t.transition(e.toolCall.id,"running");const a=e.tool.kind==="builtin"?await this.runBuiltInToolCall(e,o):await this.runMcpToolCall(e,o);return t.transition(e.toolCall.id,a.status),a.error!==void 0&&t.setError(e.toolCall.id,a.error instanceof Error?a.error.message:String(a.error)),a}catch(a){const l=a instanceof Error?a.message:String(a);return f(`[ACodeRuntime] \u274C Tool ${e.tool.exposedName} threw unexpectedly: ${l}`),t.transition(e.toolCall.id,"failed"),t.setError(e.toolCall.id,l),{toolCallId:e.toolCall.id,status:"failed",error:a}}finally{r(),s()}}resolveToolLimiter(e){return e.tool?.kind!=="builtin"?null:e.mode==="read"?this.toolReadOnlyLimiter:e.tool.toolName==="Bash"?this.toolBashLimiter:null}async prepareToolCall(e,t,o,s){const i=e.function.name;let r=this.state.exposedTools.find(c=>c.exposedName===i);r||(r=this.state.exposedTools.find(c=>c.toolName===i),r&&f(`[ACodeRuntime] \u21A9\uFE0F \u88F8\u540D\u56DE\u9000\u5339\u914D: ${i} -> ${r.exposedName}`));const a=ms(e.function.arguments),l={toolCall:e,batchId:s?.batchId,tool:r,arguments:a,mode:"exclusive",scope:"exact",access:"exclusive",claims:[],immediateError:void 0};if(r||await this.recoverHiddenMcpTool(i)&&(r=this.state.exposedTools.find(c=>c.exposedName===i)??this.state.exposedTools.find(c=>c.toolName===i),l.tool=r),!r){const c=this.state.exposedTools.map(p=>p.exposedName);console.error(`[ACodeRuntime] \u274C Tool not found: ${i}, available tools: ${c.join(", ")}`);const d=c.slice(0,40).join(", ")+(c.length>40?` \u2026(+${c.length-40} more)`:"");return l.immediateError=`ACode MCP tool not found: ${i}. Available tools: ${d}`,l}if(r.kind==="mcp"&&!this.state.mcpConnections.find(d=>d.serverName===r.serverName))return console.error(`[ACodeRuntime] \u274C MCP server not connected: ${r.serverName}, connected servers: ${this.state.mcpConnections.map(d=>d.serverName).join(", ")}`),l.immediateError=`ACode MCP server not connected: ${r.serverName}`,l;try{ht(r,this.state.permissions,t);const c=await this.hookBus.dispatch("PreToolUse",{source:r.kind==="mcp"?"mcp":"builtin",...r.kind==="mcp"?{serverName:r.serverName}:{},toolName:r.toolName,exposedName:r.exposedName,arguments:a}),d=je(c);if(d)throw console.error(`[ACodeRuntime] \u274C Tool denied by hook: ${r.exposedName}: ${d.message}`),new Error(d.message||`ACode tool denied by hook: ${r.exposedName}`)}catch(c){return l.immediateError=c,l}if(this.isTurnSuperseded(o))return l;const u=this.resolveToolConcurrencyDeclaration(r,a);return l.mode=u.mode,l.scope=u.scope,l.access=u.access,l.claims=u.claims,this.emitAcodeEvent("mcp_status",{action:"call_tool",server:r.kind==="mcp"?r.serverName:"builtin",tool:r.toolName,exposedName:r.exposedName,toolUseId:e.id,arguments:a,argumentsPreview:_s(a),...l.batchId?{batchId:l.batchId}:{}}),l}resolveToolConcurrencyDeclaration(e,t){if(e.kind!=="builtin")return Me(e.toolName)==="poll_message"||ke(e.toolName)?{mode:"blocking",scope:"unknown",access:"exclusive",claims:[]}:{mode:"exclusive",scope:"unknown",access:"exclusive",claims:[]};const o=e.concurrencyMode,s=e.resourceScope??"exact";if(!o)return{mode:"exclusive",scope:s,access:"exclusive",claims:[]};if(o==="blocking")return{mode:"blocking",scope:s,access:"exclusive",claims:[]};const i=o;let r=[];if(e.resourceKeys)try{r=e.resourceKeys(t)??[]}catch(a){f(`[ACodeRuntime] \u26A0\uFE0F resourceKeys() threw for ${e.exposedName}, falling back to exclusive: ${a instanceof Error?a.message:String(a)}`),r=[]}return r.length===0&&s==="unknown"?{mode:"exclusive",scope:s,access:"exclusive",claims:[]}:{mode:o,scope:s,access:i,claims:r}}async runBuiltInToolCall(e,t){const o=e.tool;if(o.kind!=="builtin")return{toolCallId:e.toolCall.id,status:"failed",error:new Error("not builtin")};const s=e.arguments,i=ds(o,s,this.state.provider.mcpToolTimeoutMs);i<=0&&console.warn(`[ACodeRuntime] \u26A0\uFE0F Built-in tool ${o.exposedName} has NO timeout (timeoutMs=${i})!`);const r=this.beginToolSettle(o,s,e.toolCall.id);try{const a=await $(o.execute(s,{onOutput:l=>{this.emitAcodeEvent("command_output",{server:"builtin",tool:o.toolName,exposedName:o.exposedName,toolUseId:e.toolCall.id,stream:l.stream,text:l.text,sequence:l.sequence,cwd:l.cwd,commandLineCount:l.commandLineCount,...l.commandFilePath?{commandFilePath:l.commandFilePath}:{}})},toolCallId:e.toolCall.id,...r.signal?{settleSignal:r.signal}:{}}),i,`ACode built-in tool ${o.toolName}`);return{toolCallId:e.toolCall.id,status:"completed",resultText:G(a)}}catch(a){return this.classifyToolError(e,a)}finally{this.clearToolSettle(r.seq,e.toolCall.id)}}async runMcpToolCall(e,t){const o=e.tool;if(o.kind!=="mcp")return{toolCallId:e.toolCall.id,status:"failed",error:new Error("not mcp")};const s=this.state.mcpConnections.find(u=>u.serverName===o.serverName);if(!s)return{toolCallId:e.toolCall.id,status:"failed",error:new Error(`ACode MCP server not connected: ${o.serverName}`)};const i=e.arguments,r=We(o.toolName),a=ke(o.toolName),l=r?this.state.provider.mcpPollingToolTimeoutMs:a?0:this.state.provider.mcpToolTimeoutMs;try{const u=await this.withBlockingToolCallTracking(o.toolName,()=>r&&Me(o.toolName)==="poll_message"?this.callPollMessageWithSubAgentRace(s,o,i,l):this.callMcpToolWithTimeout(s,o,i,l,r));let c=G(u);return r&&(c=this.expandCommandsInPolledResult(c)),{toolCallId:e.toolCall.id,status:"completed",resultText:c}}catch(u){return this.classifyToolError(e,u)}}async withBlockingToolCallTracking(e,t){if(!Z.isLongBlockingMcpToolName(e))return await t();this.activeBlockingToolCalls+=1;try{return await t()}finally{this.activeBlockingToolCalls-=1}}classifyToolError(e,t){const s=(t instanceof Error?t.message:String(t)).includes("timed out after")?"timeout":t instanceof Error&&t.name==="AbortError"?"aborted":"failed";return{toolCallId:e.toolCall.id,status:s,error:t}}async commitToolOutcome(e,t,o,s=[]){const i=e.tool,r=i?.kind==="mcp"?i.serverName:"builtin",a=i?.toolName??e.toolCall.function.name;if(t.status==="completed"&&t.resultText!==void 0){const c=t.resultText;i&&await this.hookBus.dispatch("PostToolUse",{source:i.kind==="mcp"?"mcp":"builtin",...i.kind==="mcp"?{serverName:i.serverName}:{},toolName:i.toolName,exposedName:i.exposedName,result:c}),this.emitAcodeEvent("mcp_status",{action:"tool_result",server:r,tool:a,toolUseId:e.toolCall.id,result:c,...e.batchId?{batchId:e.batchId}:{}}),this.state.conversation.push({role:"tool",tool_call_id:e.toolCall.id,content:c});const d=await this.appendSyntheticMultimodalUserMessage(c,e.toolCall.id,o);d&&s.push(d);return}if(t.status==="superseded"){this.commitSupersededToolResult(e);return}const l=t.error??new Error("Tool execution failed"),u=l instanceof Error?l.message:String(l);if(this.abortRequested||this.state.terminated){this.emitAcodeEvent("mcp_status",{action:"tool_result",server:r,tool:a,toolUseId:e.toolCall.id,result:`[aborted] ${u}`,failed:!0,aborted:!0,...e.batchId?{batchId:e.batchId}:{}}),this.state.conversation.push({role:"tool",tool_call_id:e.toolCall.id,content:`[aborted] ${u}`});return}if(!i){this.state.conversation.push({role:"tool",tool_call_id:e.toolCall.id,content:u}),this.emitAcodeEvent("mcp_status",{action:"tool_result",server:r,tool:a,toolUseId:e.toolCall.id,result:u,failed:!0,...e.batchId?{batchId:e.batchId}:{}});return}this.appendToolFailureResult(e.toolCall,i,l,e.batchId)}commitSupersededToolResult(e){const t=e.immediateError!==void 0?`[cancelled] ${e.immediateError instanceof Error?e.immediateError.message:String(e.immediateError)}`:"[cancelled] Tool execution was superseded by a newer turn.";this.state.conversation.push({role:"tool",tool_call_id:e.toolCall.id,content:t}),this.emitAcodeEvent("mcp_status",{action:"tool_result",server:e.tool?.kind==="mcp"?e.tool.serverName:"builtin",tool:e.tool?.toolName??e.toolCall.function.name,toolUseId:e.toolCall.id,result:t,failed:!0,aborted:!0,...e.batchId?{batchId:e.batchId}:{}})}async executeSingleToolByName(e,t,o){let s=this.state.exposedTools.find(l=>l.exposedName===e);if(s||(s=this.state.exposedTools.find(l=>l.toolName===e)),!s)throw new Error(`Tool not found: ${e}`);if(s.kind==="builtin")return s.execute(t,{toolCallId:o?.toolCallId});const i=this.state.mcpConnections.find(l=>l.serverName===s.serverName);if(!i)throw new Error(`MCP server not found: ${s.serverName}`);const r=We(s.toolName),a=r?this.state.provider.mcpPollingToolTimeoutMs:ke(s.toolName)?0:this.state.provider.mcpToolTimeoutMs;if(r&&Me(s.toolName)==="poll_message"){const l=await this.withBlockingToolCallTracking(s.toolName,()=>this.callPollMessageWithSubAgentRace(i,s,t,a,{allowRepoll:!1}));return this.expandCommandsInPolledResult(G(l))}return this.withBlockingToolCallTracking(s.toolName,()=>this.callMcpToolWithTimeout(i,s,t,a,r))}async callMcpToolWithTimeout(e,t,o,s,i,r){const a=s>0?s:xo,u=!!this.config.sharedMcpConnections?{...o,_aws_sub_agent:!0}:o;for(;;){const c=this.createRuntimeStopWaiter(`ACode MCP tool ${t.serverName}/${t.toolName}`);try{return await $(Promise.race([e.client.callTool({name:t.toolName,arguments:u},void 0,{timeout:a,...r?{signal:r}:{}}),c.promise]),s,`ACode MCP tool ${t.serverName}/${t.toolName}`)}catch(d){if(r?.aborted||!i||s>0||!Ts(d))throw d;this.emitAcodeEvent("warning",{message:`ACode MCP polling tool ${t.serverName}/${t.toolName} reached the MCP SDK timeout window and will continue polling.`})}finally{c.cancel()}}}static formatSubAgentCompletionAsPollResult(e){const t=e.map(o=>{const s=o.error?`Sub-agent ${o.subId} [${o.status}]: ${o.description}
23
+ `)}
24
+
25
+ ---
26
+
27
+ `:"")+`The conversation above (${e.messageCount} messages) needs to be summarized to free context space (current context limit: ${e.contextLimit} tokens).
28
+
29
+ `+io}),t.cacheControlMode&&t.cacheControlMode!=="off"){const c=Ke(i),d=He(c,t.cacheControlMode,{skipCacheWrite:!0});d&&(c[d.index]=d.message)}const a={model:t.model,stream:!0,messages:i},l=new AbortController;this.abortController=l;let u=!1;try{return await E((async()=>{const c=await E(fetch(ke(o),{method:"POST",headers:s,body:JSON.stringify(a),signal:l.signal}),t.requestTimeoutMs,"ACode LLM summarization",()=>{u=!0,l.abort()});if(!c.ok){const g=await E(c.text(),t.requestTimeoutMs,"ACode LLM summarization error response body",()=>{u=!0,l.abort()}),T=g.length>500?`${g.slice(0,500)}...(truncated, total ${g.length} chars)`:g;throw new Error(`ACode LLM summarization request failed: ${c.status} ${T}`)}if(!c.body)throw new Error("ACode LLM summarization stream response has no body");const d=c.body.getReader(),p=new TextDecoder;let C="",y="";const m=g=>{for(const T of $t(g)){if(T==="[DONE]")continue;let _;try{_=JSON.parse(T)}catch{continue}if(!M(_))continue;const b=Oe(_);if(b)throw new Error(`ACode LLM summarization failed: ${b}`);const S=_.choices?.[0]?.delta?.content,k=typeof S=="string"?S:"";k&&(C+=k,this.emitAcodeEvent("compaction_summary",{text:k}))}};for(;;){const{done:g,value:T}=await E(d.read(),t.requestTimeoutMs,"ACode LLM summarization idle",()=>l.abort());if(g)break;y+=p.decode(T,{stream:!0});const _=y.split(/\r?\n\r?\n/);y=_.pop()??"";for(const b of _)m(b)}y+=p.decode(),y.trim()&&m(y);const f=C;if(!f||f.trim().length===0)throw new Error("ACode LLM summarization returned empty content");return f})(),t.requestTotalTimeoutMs,"ACode LLM summarization total",()=>{l.abort()})}catch(c){throw c instanceof Error&&c.name==="AbortError"?u?new Error(`ACode LLM summarization timed out after ${t.requestTimeoutMs}ms`):new Error("ACode LLM summarization aborted"):c}finally{this.abortController===l&&(this.abortController=null)}}async requestChatCompletion(e){const t=this.state.provider,o=t.baseURL;if(!o)throw new Error("ACode provider baseURL is not configured");this.instructionsDirty&&(this.instructionsDirty=!1,this.rebuildRuntimeInstructionsMessage());const{contextLimit:s,maxOutput:i,inputLimit:r,threshold:a}=ue(t);this.runMicrocompactPass(s,a);const l=this.state.accumulatedInputTokens+this.state.accumulatedOutputTokens,u=G(this.state.conversation)+K(this.state.exposedTools),c=Math.max(l,u),d=c>=a,p=this.compactRequested;this.compactRequested=!1,h(`[ACodeRuntime] \u{1F50D} Compaction check: actualUsed=${l}, estimation=${u}, effectiveUsed=${c}, contextLimit=${s}, inputLimit=${r??"n/a"}, maxOutput=${i}, triggerThreshold=${a}, shouldCompact=${d}, manualCompact=${p}`),p?await this.runCompactionPass({contextLimit:s,maxOutput:i,effectiveUsed:c,trigger:"manual",force:!0,detectLabel:"\u624B\u52A8\u89E6\u53D1\u4E0A\u4E0B\u6587\u538B\u7F29",detectDetail:`\u7528\u6237\u8BF7\u6C42\u5148\u884C\u538B\u7F29\uFF0C\u5F53\u524D\u4F30\u7B97\u7528\u91CF: ${c} tokens`}):d&&await this.runCompactionPass({contextLimit:s,maxOutput:i,effectiveUsed:c,trigger:l>=a?"actual_usage":"estimated_overflow",force:!1,detectLabel:"\u68C0\u6D4B\u5230\u4E0A\u4E0B\u6587\u6EA2\u51FA",detectDetail:`\u6709\u6548\u7528\u91CF: ${c} tokens, \u9608\u503C: ${a}, \u89E6\u53D1: ${l>=a?"\u5B9E\u9645\u7528\u91CF":"\u4F30\u7B97\u6EA2\u51FA"}`});const C=Jo(s);let y=Go()||d;if(!y){const w=Ge(this.state.conversation);w>dt?y=!0:w>C&&h(`[ACodeRuntime] \u23ED\uFE0F Byte-cap truncation skipped: body ${w}B > cap ${C}B, but effectiveUsed ${c} < threshold ${a} (aligned with frontend compression marker; rely on provider 413/overflow fallback)`)}let m=bt,f=0,g=0,T=0;if(y&&(f=X(this.state.conversation),g=G(this.state.conversation),T=this.state.conversation.length,m=await vs(this.state.conversation,C,s,i,w=>this.summarizeConversationWithLLM(w),()=>this.rebuildRuntimeResourcesMessage())),m.truncatedCount>0){this.rebuildRuntimeInstructionsMessage();const w=`compaction-bytes-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;this.emitAcodeEvent("context_compaction",{action:"start",compactionId:w,sizeKB:f,estimatedTokens:g,actualInputTokens:this.state.accumulatedInputTokens,actualOutputTokens:this.state.accumulatedOutputTokens,messageCount:T,model:t.model,trigger:"request_body_byte_limit"}),this.emitCompactionPhase(w,"byte_limit_detect","\u68C0\u6D4B\u5230\u8BF7\u6C42\u4F53\u8D85\u9650",`\u8BF7\u6C42\u4F53\u8D85\u8FC7 ${C} \u5B57\u8282\u4E0A\u9650\uFF0C\u5373\u5C06\u88C1\u526A\u5386\u53F2`,"request_body_byte_limit");const x=X(this.state.conversation),W=G(this.state.conversation),N=Me(this.state.conversation,K(this.state.exposedTools));this.emitAcodeEvent("context_compaction",{action:"end",compactionId:w,sizeBeforeKB:f,sizeAfterKB:x,freedKB:Math.round((f-x)*10)/10,strategy:m.strategy,freedTokens:m.freedTokens,tokensBefore:g,tokensAfter:W,contextTokensAfter:N,prunedToolMessages:m.prunedToolMessages,summarizedMessages:m.summarizedMessages,messageCountBefore:T,messageCountAfter:this.state.conversation.length,trigger:"request_body_byte_limit"}),this.emitAcodeEvent("warning",{message:`Conversation truncated: removed ${m.truncatedCount} older messages to fit within ${C} byte request size limit`}),this.state.accumulatedInputTokens=0,this.state.accumulatedOutputTokens=0}const _=()=>{const w=Ss(this.state.conversation);(w.orphanToolMessages>0||w.repairedToolCalls>0||w.downgradedAssistants>0||w.relocatedInterruptions>0||w.reorderedToolResults>0)&&(h(`[ACodeRuntime] \u{1FA79} sanitizeToolCallSequence: orphanTools=${w.orphanToolMessages} repairedCalls=${w.repairedToolCalls} downgradedAssistants=${w.downgradedAssistants} relocatedInterruptions=${w.relocatedInterruptions} reorderedToolResults=${w.reorderedToolResults}`),this.emitAcodeEvent("warning",{message:`\u68C0\u6D4B\u5230\u5DE5\u5177\u8C03\u7528\u5E8F\u5217\u4E0D\u5B8C\u6574\uFF0C\u5DF2\u81EA\u52A8\u4FEE\u590D\uFF08\u5B64\u513F\u5DE5\u5177\u7ED3\u679C ${w.orphanToolMessages} \u6761\u3001\u8865\u5360\u4F4D\u7ED3\u679C ${w.repairedToolCalls} \u4E2A\u3001\u964D\u7EA7 assistant \u6D88\u606F ${w.downgradedAssistants} \u6761\u3001\u56DE\u6B63\u7A7F\u63D2\u6D88\u606F ${w.relocatedInterruptions} \u6761\u3001\u56DE\u6B63\u9519\u5E8F\u7ED3\u679C ${w.reorderedToolResults} \u6761\uFF09\uFF0C\u907F\u514D provider 400 (tool_call_sequence_broken) \u6B7B\u5FAA\u73AF\u3002`}))};_();const b=this.state.exposedTools.filter(w=>this.toolGroupManager&&!this.toolGroupManager.shouldShowToLLMByName(w.exposedName)?!1:As(w,this.state.permissions,e)),S=()=>{const w=Eo(this.state.conversation);if(t.cacheControlMode&&t.cacheControlMode!=="off"){const W=Ke(w),N=He(W,t.cacheControlMode);N&&(W[N.index]=N.message)}const x={model:t.model,messages:w,stream:t.stream};return t.effort&&(x.reasoning_effort=t.effort),t.stream&&(x.stream_options={include_usage:!0}),b.length>0&&(x.tools=vt(b),x.tool_choice="auto"),x},k="POST",$=_s(o),v=Os(t),B=Ls(v),I=w=>{const x=JSON.stringify(w,null,2);h(`[ACodeRuntime] \u2605\u2605\u2605 DEBUG \u2605\u2605\u2605 emitAiRequest: \u53D1\u9001\u8BF7\u6C42 model=${t.model}, endpoint=${$}, messageCount=${this.state.conversation.length}`),this.emitAcodeEvent("ai_request",{model:t.model,endpoint:$,requestMethod:k,requestUrl:$,requestHeaders:B,stream:t.stream,messageCount:this.state.conversation.length,toolCount:b.length,lastUserMessagePreview:bs(this.state.conversation),estimatedContextTokens:Ne(x),...this.lastIterationUsage?{lastUsage:this.lastIterationUsage}:{}}),ne(`ai_request emitted: model=${t.model} stream=${t.stream} messageCount=${this.state.conversation.length} toolCount=${b.length} estimatedContextTokens=${Ne(x)} lastUsage=${JSON.stringify(this.lastIterationUsage??null)}`)};let L=S();I(L);const q=t.requestRetryCount===Ee,re=q?1/0:t.requestRetryCount+1;let oe=!1;for(let w=1;q||w<=re;w+=1){this.state.terminated||(this.abortRequested=!1),w>1&&I(L);const x=new AbortController;this.abortController=x;let W=!1;try{const N=await E((async()=>{const Q=t.stream?t.requestFirstByteTimeoutMs:t.requestTotalTimeoutMs,F=await E(fetch(ke(o),{method:k,headers:v,body:JSON.stringify(L),signal:x.signal}),Q,"ACode provider request",()=>{W=!0,x.abort()});if(!F.ok){const A=await E(F.text(),t.requestStreamIdleTimeoutMs,"ACode provider error response body",()=>{W=!0,x.abort()}),O=A.length>500?`${A.slice(0,500)}...(truncated, total ${A.length} chars)`:A,ae=Le(this.state.conversation,F.status,A)??"";throw new Error(`ACode provider request failed: ${F.status} ${O}${ae}`)}const Z=F.headers?.get?.("content-type")||"";if(t.stream&&Z.toLowerCase().includes("text/event-stream"))return await this.readChatCompletionStream(F,t.requestStreamIdleTimeoutMs,x,t.requestFirstByteTimeoutMs);const ee=await E(F.json(),t.requestStreamIdleTimeoutMs,"ACode provider response body",()=>{W=!0,x.abort()});if(!M(ee))return this.emitAcodeEvent("warning",{message:`ACode provider returned invalid response format (expected object, got ${typeof ee}); treating as empty response`}),{};const Y=Oe(ee);if(Y){const A=Le(this.state.conversation,F.status,Y)??"";throw new Error(`ACode provider request failed: ${Y}${A}`)}return ee})(),t.requestTotalTimeoutMs,"ACode provider request total",()=>{x.abort()}),P=fo({finishReason:N.choices?.[0]?.finish_reason,stopReason:N.choices?.[0]?.stop_reason});if(P.kind==="context_overflow"){if(!oe&&await this.compactForContextOverflow({contextLimit:s,trigger:"finish_reason_context_overflow",warningMessage:`ACode provider reported context overflow via ${P.source} (${P.marker}); summarized older messages and rebuilt the request instead of accepting the truncated payload`})>0){oe=!0,_(),L=S(),I(L),w-=1;continue}this.emitAcodeEvent("warning",{message:`ACode provider reported context overflow via ${P.source} (${P.marker}), but no further compaction was possible`})}return N}catch(N){let P;if(N instanceof Error&&N.name==="AbortError"?W?P=new Error(`ACode provider request timed out (firstByte=${t.requestFirstByteTimeoutMs}ms, idle=${t.requestStreamIdleTimeoutMs}ms)`):this.state.terminated?P=new Error("ACode provider request aborted by user"):P=new Error(`ACode provider request timed out (watchdog abort, firstByte=${t.requestFirstByteTimeoutMs}ms, idle=${t.requestStreamIdleTimeoutMs}ms)`):P=N instanceof Error?N:new Error(String(N)),!oe&&!this.abortRequested&&!this.state.terminated&&(ve(N)||ve(P))){if(await this.compactForContextOverflow({contextLimit:s,trigger:"provider_overflow_error",warningMessage:"ACode provider context limit exceeded; summarized older messages and rebuilt the request instead of retrying the same oversized payload"})===0)throw P;oe=!0,_(),L=S(),I(L),w-=1;continue}if(!((q||w<re)&&!this.abortRequested&&!this.state.terminated&&xs(P)))throw P;this.emitAcodeEvent("error",{message:`ACode provider request attempt ${w}${q?"":`/${re}`} failed; retrying: ${P.message}`,nonFatal:!0});const F=Math.min(Do,Bo*Math.pow(2,w-1)),Z=Math.random()*1e3;await Xo(F+Z)}finally{this.abortController===x&&(this.abortController=null)}}throw new Error("ACode provider request failed after all retries")}async compactForContextOverflow(e){const{contextLimit:t,trigger:o,warningMessage:s}=e,i=ue(this.state.provider),r=i.maxOutput,a=i.inputLimit,l=X(this.state.conversation),u=G(this.state.conversation),c=this.state.conversation.length,d=`compaction-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;this.emitAcodeEvent("context_compaction",{action:"start",compactionId:d,sizeKB:l,estimatedTokens:u,messageCount:c,model:this.state.provider.model,trigger:o}),this.emitCompactionPhase(d,"detect","\u68C0\u6D4B\u5230\u4E0A\u4E0B\u6587\u6EA2\u51FA",`\u6D88\u606F: ${c}\u6761, \u5927\u5C0F: ${l}KB`),this.emitCompactionPhase(d,"prune","\u9636\u6BB51: \u88C1\u526A\u5DE5\u5177\u8F93\u51FA","\u6B63\u5728\u88C1\u526A...");const p=po(this.state.conversation,t,{ignoreMinimumGain:!0});this.emitCompactionPhase(d,"prune_done","\u9636\u6BB51: \u88C1\u526A\u5DE5\u5177\u8F93\u51FA",`\u88C1\u526A\u4E86 ${p.prunedCount} \u6761\u5DE5\u5177\u8F93\u51FA, \u91CA\u653E ${p.freedTokens} tokens`),this.emitCompactionPhase(d,"summarize","\u9636\u6BB52: \u6458\u8981\u5316\u5BF9\u8BDD","\u6B63\u5728\u6458\u8981...");const C=We({contextLimit:t,maxOutput:r,...a?{inputLimit:a}:{},toolsTokens:K(this.state.exposedTools)});let y=0;const m=Te(this.state.conversation);try{y=await Se(this.state.conversation,{llmSummarizer:S=>this.summarizeConversationWithLLM(S),contextLimit:t,budget:C,allowRuleFallback:!1,...m.length>0?{prefixMessages:m}:{}})}catch(S){if(!(S instanceof Je))throw S;this.emitAcodeEvent("warning",{message:`LLM \u6458\u8981\u4E0D\u53EF\u7528\uFF0C\u5DF2\u4F7F\u7528\u89C4\u5219\u6458\u8981\u515C\u5E95\uFF1A${S.message}`}),y=await Se(this.state.conversation,{contextLimit:t,budget:C})}this.emitCompactionPhase(d,"summarize_done","\u9636\u6BB52: \u6458\u8981\u5316\u5BF9\u8BDD",`\u6458\u8981\u5316\u4E86 ${y} \u6761\u6D88\u606F`);const f=p.prunedCount+y;if(f===0)return 0;this.state.accumulatedInputTokens=0,this.state.accumulatedOutputTokens=0,y>0&&await this.rebuildRuntimeResourcesMessage(),this.rebuildRuntimeInstructionsMessage();const g=X(this.state.conversation),T=G(this.state.conversation),_=Me(this.state.conversation,K(this.state.exposedTools)),b=this.state.conversation.length;return this.emitAcodeEvent("context_compaction",{action:"end",compactionId:d,sizeBeforeKB:l,sizeAfterKB:g,freedKB:Math.round((l-g)*10)/10,tokensBefore:u,tokensAfter:T,contextTokensAfter:_,messageCountBefore:c,messageCountAfter:b,strategy:y>0?"summarize":"prune",freedTokens:p.freedTokens,prunedToolMessages:p.prunedCount,summarizedMessages:y,trigger:o}),this.emitAcodeEvent("warning",{message:s}),f}async rebuildRuntimeResourcesMessage(){const e=this.config.runtimeResourcesProvider;if(!e)return;const t=this.state.conversation;for(let l=t.length-1;l>=0;l--)lo(t[l])&&t.splice(l,1);let o;try{o=await e()}catch(l){h(`[ACodeRuntime] runtime resources provider failed, snapshot skipped: ${pe(l)}`);return}const s=typeof o=="string"?o.trim():"";if(!s)return;let i=0,r=-1;for(let l=0;l<t.length;l++){const u=t[l];if(u.role!=="system")break;ro(u)&&(r=l),i=l+1}const a=r>=0?r+1:i;t.splice(a,0,{role:"system",content:`${ho}
30
+ ${s}`})}rebuildRuntimeInstructionsMessage(){if(!this.state?.started||this.state.terminated)return;const e=this.state.conversation;for(let i=e.length-1;i>=0;i--)co(e[i])&&e.splice(i,1);const t=this.buildRuntimeInstructionsContent();if(!t)return;const o=(()=>{for(let i=0;i<e.length;i++)if(e[i].role!=="system")return i;return e.length})();let s=o;for(let i=0;i<o;i++){const r=e[i];if(r.role==="system"&&typeof r.content=="string"&&r.content.startsWith("[Runtime Environment]")){s=i;break}}e.splice(s,0,{role:"system",content:t})}buildRuntimeInstructionsContent(){const e=this.state.provider,t=this.state.skills??[],o=this.state.commands??[],s=Mt(t),i=St(o),r=this.toolGroupManager?.buildCapabilityPrompt()??"",a=this.config.pluginBridge?["","## \u63D2\u4EF6\u7CFB\u7EDF","\u5DF2\u5B89\u88C5\u63D2\u4EF6\u4EE5\u6536\u7EB3\u7EC4\u5F62\u5F0F\u5217\u51FA\uFF08\u89C1\u4E0A\u65B9\u300C\u53EF\u7528\u80FD\u529B\u300D\u4E2D\u7684 plugin:{\u63D2\u4EF6\u540D} \u6761\u76EE\uFF09\u3002",'\u9700\u8981\u67D0\u63D2\u4EF6\u7684\u5DE5\u5177\u65F6\uFF0C\u5148 expand_tools({ group: "plugin:\u63D2\u4EF6\u540D" }) \u5C55\u5F00\uFF1B','\u5DE5\u5177\u5B9A\u4E49\uFF08\u542B\u53C2\u6570 schema\uFF09\u968F\u5C55\u5F00\u7ED3\u679C\u8FD4\u56DE\uFF0C\u518D\u7528 call_tool({ name: "\u63D2\u4EF6\u540D.\u5DE5\u5177\u540D", arguments: {...} }) \u8C03\u7528\u3002'].join(`
31
+ `):"";return[qe,e.systemPrompt,s,i,r+a].map(l=>l?.trim()).filter(l=>!!l).join(`
32
+
33
+ `)}async readChatCompletionStream(e,t,o,s){if(!e.body)throw new Error("ACode provider stream response has no body");const i=e.body.getReader(),r=new TextDecoder,a=new Map;let l="",u="",c="",d,p,C;const y=f=>{for(const g of $t(f)){if(g==="[DONE]")continue;const T=JSON.parse(g);if(!M(T))continue;const _=Oe(T);if(_){o?.abort();const I=Le(this.state.conversation,200,_)??"";throw new Error(`ACode provider request failed: ${_}${I}`)}const b=T.usage;b&&(d=No(d,b),ne(`stream usage chunk received: ${JSON.stringify(b)} -> merged: ${JSON.stringify(d)}`));const S=T.choices?.[0];typeof S?.finish_reason=="string"&&S.finish_reason&&(p=S.finish_reason),typeof S?.stop_reason=="string"&&S.stop_reason&&(C=S.stop_reason);const k=S?.delta,$=kt(k);$&&(u.length<Ie&&(u+=$.slice(0,Ie-u.length)),this.emitAcodeEvent("thinking_delta",{text:$}));const v=typeof k?.content=="string"?k.content:"";v&&(l+=v,this.emitAcodeEvent("assistant_delta",{text:v}));const B=Array.isArray(k?.tool_calls)?k.tool_calls:[];for(const I of B)qs(a,I)}};let m=!0;for(;;){const f=m&&s?s:t,{done:g,value:T}=await E(i.read(),f,m?"ACode provider stream first byte":"ACode provider stream idle",()=>o?.abort());if(m=!1,g)break;c+=r.decode(T,{stream:!0});const _=c.split(/\r?\n\r?\n/);c=_.pop()??"";for(const b of _)y(b)}return c+=r.decode(),c.trim()&&y(c),{choices:[{message:{content:l||null,tool_calls:Fs(a),...u?{reasoning:u}:{}},...p?{finish_reason:p}:{},...C?{stop_reason:C}:{}}],...d?{usage:d}:{}}}async handleToolCalls(e,t,o=this.contextVersion){h(`[ACodeRuntime] handleToolCalls started with ${e.length} tool(s)`);const s=e.filter(l=>!xe(l.function.name)),i=l=>!xe(l.function.name),r=this.toolConcurrencyEnabled&&s.length>1?{batchId:ht(),toolCount:s.length}:void 0;r&&!this.isTurnSuperseded(o)&&this.emitToolBatchStart(r,s);const a=[];for(const l of e){if(this.isTurnSuperseded(o))break;a.push(await this.prepareToolCall(l,t,o,i(l)?r:void 0))}for(let l=a.length;l<e.length;l++){const u=e[l];a.push({toolCall:u,batchId:i(u)?r?.batchId:void 0,tool:void 0,arguments:{},mode:"blocking",scope:"unknown",access:"exclusive",claims:[],immediateError:void 0})}this.toolConcurrencyEnabled&&a.length>1?await this.executePreparedToolCallsConcurrently(a,o,r):await this.executePreparedToolCallsSerially(a,o),h(`[ACodeRuntime] handleToolCalls completed for all ${e.length} tool(s)`)}emitToolBatchStart(e,t){const o=t.map(s=>s.function.name);h(`[ACodeRuntime] \u{1F9E9} Tool batch ${e.batchId} started: tools=${e.toolCount} [${o.join(", ")}]`),this.emitAcodeEvent("mcp_status",{action:"tool_batch_start",server:"builtin",batchId:e.batchId,toolCount:e.toolCount,toolNames:o})}async executePreparedToolCallsConcurrently(e,t,o){const s=e.map(p=>({toolCallId:p.toolCall.id,toolName:p.tool?.exposedName??p.toolCall.function.name,mode:p.mode,scope:p.scope,claims:p.claims})),i=this.toolConcurrencyScheduler.schedule(s),r=o?.batchId??ht(),a=new tt(r),l=new Set(e.filter(p=>!xe(p.toolCall.function.name)).map(p=>p.toolCall.id));for(const p of e)l.has(p.toolCall.id)&&a.register({toolCallId:p.toolCall.id,toolName:p.tool?.exposedName??p.toolCall.function.name,mode:p.mode,resourceKeys:(i.plans.get(p.toolCall.id)?.claims??[]).map(C=>C.key)});const u=new Map,c=new Map(e.map(p=>[p.toolCall.id,p]));for(const p of i.waves){if(this.isTurnSuperseded(t))break;const C=p.planIds.map(m=>c.get(m)).filter(m=>m!==void 0);if(C.length===0)continue;(await Promise.allSettled(C.map(m=>this.executeOnePreparedTool(m,a,t)))).forEach((m,f)=>{const g=C[f];u.set(g.toolCall.id,m.status==="fulfilled"?m.value:{toolCallId:g.toolCall.id,status:"failed",error:m.reason})})}if(await this.commitPreparedToolOutcomes(e,u,a,t),!o)return;const d=a.finalize();h(`[ACodeRuntime] \u26A1 Tool batch ${r}: tools=${d.toolCount} speedup=${d.speedup}x parallelism=${d.parallelism}x wall=${d.wallClockMs}ms contentions=${d.contentionCount} failures=${d.failureCount}`),this.emitAcodeEvent("mcp_status",{action:"tool_batch_metrics",server:"builtin",batchId:r,toolCount:d.toolCount,parallelism:d.parallelism,speedup:d.speedup,wallClockMs:d.wallClockMs,totalWaitMs:d.totalWaitMs,contentionCount:d.contentionCount,failureCount:d.failureCount,maxConcurrentObserved:d.maxConcurrentObserved,traces:d.traces.map(p=>({toolCallId:p.toolCallId,toolName:p.toolName,mode:p.mode,resourceKeys:p.resourceKeys,waitMs:p.waitDurationMs,runMs:p.executionDurationMs,status:p.status}))})}async executePreparedToolCallsSerially(e,t){const o=new tt(`toolbatch-serial-${Date.now().toString(36)}`),s=new Map;for(const i of e)o.register({toolCallId:i.toolCall.id,toolName:i.tool?.exposedName??i.toolCall.function.name,mode:i.mode,resourceKeys:i.claims.map(r=>r.key)}),!this.isTurnSuperseded(t)&&s.set(i.toolCall.id,await this.executeOnePreparedTool(i,o,t));await this.commitPreparedToolOutcomes(e,s,o,t)}async commitPreparedToolOutcomes(e,t,o,s){const i=[];for(const r of e){if(this.isTurnSuperseded(s)){this.emitCallToolEvent(r),this.commitSupersededToolResult(r),o.transition(r.toolCall.id,"superseded");continue}const a=t.get(r.toolCall.id);if(!a){this.emitCallToolEvent(r),await this.commitToolOutcome(r,{toolCallId:r.toolCall.id,status:"failed",error:r.immediateError??new Error("Tool was not executed")},s,i),o.transition(r.toolCall.id,"committed");continue}o.transition(r.toolCall.id,"committing"),await this.commitToolOutcome(r,a,s,i),o.transition(r.toolCall.id,"committed")}i.length>0&&this.state.conversation.push(...i)}async executeOnePreparedTool(e,t,o){if(e.immediateError!==void 0||!e.tool){t.transition(e.toolCall.id,"failed");const a=e.immediateError??new Error("Tool not found");return t.setError(e.toolCall.id,a instanceof Error?a.message:String(a)),{toolCallId:e.toolCall.id,status:"failed",error:a}}this.emitCallToolEvent(e),t.transition(e.toolCall.id,"waiting_resource");const s=await this.toolResourceLock.acquire(e.claims,e.access),i=this.resolveToolLimiter(e),r=i?await i.acquire():()=>{};try{if(this.isTurnSuperseded(o))return{toolCallId:e.toolCall.id,status:"superseded"};t.transition(e.toolCall.id,"running");const a=e.tool.kind==="builtin"?await this.runBuiltInToolCall(e,o):await this.runMcpToolCall(e,o);return t.transition(e.toolCall.id,a.status),a.error!==void 0&&t.setError(e.toolCall.id,a.error instanceof Error?a.error.message:String(a.error)),a}catch(a){const l=a instanceof Error?a.message:String(a);return h(`[ACodeRuntime] \u274C Tool ${e.tool.exposedName} threw unexpectedly: ${l}`),t.transition(e.toolCall.id,"failed"),t.setError(e.toolCall.id,l),{toolCallId:e.toolCall.id,status:"failed",error:a}}finally{r(),s()}}resolveToolLimiter(e){return e.tool?.kind!=="builtin"?null:e.mode==="read"?this.toolReadOnlyLimiter:e.tool.toolName==="Bash"?this.toolBashLimiter:null}async prepareToolCall(e,t,o,s){const i=e.function.name;let r=this.state.exposedTools.find(c=>c.exposedName===i);r||(r=this.state.exposedTools.find(c=>c.toolName===i),r&&h(`[ACodeRuntime] \u21A9\uFE0F \u88F8\u540D\u56DE\u9000\u5339\u914D: ${i} -> ${r.exposedName}`));const a=ws(e.function.arguments),l={toolCall:e,batchId:s?.batchId,tool:r,arguments:a,mode:"exclusive",scope:"exact",access:"exclusive",claims:[],immediateError:void 0};if(r||await this.recoverHiddenMcpTool(i)&&(r=this.state.exposedTools.find(c=>c.exposedName===i)??this.state.exposedTools.find(c=>c.toolName===i),l.tool=r),!r){const c=this.state.exposedTools.map(p=>p.exposedName);console.error(`[ACodeRuntime] \u274C Tool not found: ${i}, available tools: ${c.join(", ")}`);const d=c.slice(0,40).join(", ")+(c.length>40?` \u2026(+${c.length-40} more)`:"");return l.immediateError=`ACode MCP tool not found: ${i}. Available tools: ${d}`,l}if(r.kind==="mcp"&&!this.state.mcpConnections.find(d=>d.serverName===r.serverName))return console.error(`[ACodeRuntime] \u274C MCP server not connected: ${r.serverName}, connected servers: ${this.state.mcpConnections.map(d=>d.serverName).join(", ")}`),l.immediateError=`ACode MCP server not connected: ${r.serverName}`,l;try{_t(r,this.state.permissions,t);const c=await this.hookBus.dispatch("PreToolUse",{source:r.kind==="mcp"?"mcp":"builtin",...r.kind==="mcp"?{serverName:r.serverName}:{},toolName:r.toolName,exposedName:r.exposedName,arguments:a}),d=Qe(c);if(d)throw console.error(`[ACodeRuntime] \u274C Tool denied by hook: ${r.exposedName}: ${d.message}`),new Error(d.message||`ACode tool denied by hook: ${r.exposedName}`)}catch(c){return l.immediateError=c,l}if(this.isTurnSuperseded(o))return l;const u=this.resolveToolConcurrencyDeclaration(r,a);return l.mode=u.mode,l.scope=u.scope,l.access=u.access,l.claims=u.claims,l}emitCallToolEvent(e){if(e.callToolEventEmitted)return;const t=e.tool;t&&(e.callToolEventEmitted=!0,this.emitAcodeEvent("mcp_status",{action:"call_tool",server:t.kind==="mcp"?t.serverName:"builtin",tool:t.toolName,exposedName:t.exposedName,toolUseId:e.toolCall.id,arguments:e.arguments,argumentsPreview:Is(e.arguments),...e.batchId?{batchId:e.batchId}:{}}))}resolveToolConcurrencyDeclaration(e,t){if(e.kind!=="builtin")return Re(e.toolName)==="poll_message"||$e(e.toolName)?{mode:"blocking",scope:"unknown",access:"exclusive",claims:[]}:{mode:"exclusive",scope:"unknown",access:"exclusive",claims:[]};const o=e.concurrencyMode,s=e.resourceScope??"exact";if(!o)return{mode:"exclusive",scope:s,access:"exclusive",claims:[]};if(o==="blocking")return{mode:"blocking",scope:s,access:"exclusive",claims:[]};const i=o;let r=[];if(e.resourceKeys)try{r=e.resourceKeys(t)??[]}catch(a){h(`[ACodeRuntime] \u26A0\uFE0F resourceKeys() threw for ${e.exposedName}, falling back to exclusive: ${a instanceof Error?a.message:String(a)}`),r=[]}return r.length===0&&s==="unknown"?{mode:"exclusive",scope:s,access:"exclusive",claims:[]}:{mode:o,scope:s,access:i,claims:r}}async runBuiltInToolCall(e,t){const o=e.tool;if(o.kind!=="builtin")return{toolCallId:e.toolCall.id,status:"failed",error:new Error("not builtin")};const s=e.arguments,i=ks(o,s,this.state.provider.mcpToolTimeoutMs);i<=0&&console.warn(`[ACodeRuntime] \u26A0\uFE0F Built-in tool ${o.exposedName} has NO timeout (timeoutMs=${i})!`);const r=this.beginToolSettle(o,s,e.toolCall.id);try{const a=await E(o.execute(s,{onOutput:l=>{this.emitAcodeEvent("command_output",{server:"builtin",tool:o.toolName,exposedName:o.exposedName,toolUseId:e.toolCall.id,stream:l.stream,text:l.text,sequence:l.sequence,cwd:l.cwd,commandLineCount:l.commandLineCount,...l.commandFilePath?{commandFilePath:l.commandFilePath}:{}})},toolCallId:e.toolCall.id,...r.signal?{settleSignal:r.signal}:{}}),i,`ACode built-in tool ${o.toolName}`);return{toolCallId:e.toolCall.id,status:"completed",resultText:H(a)}}catch(a){return this.classifyToolError(e,a)}finally{this.clearToolSettle(r.seq,e.toolCall.id)}}async runMcpToolCall(e,t){const o=e.tool;if(o.kind!=="mcp")return{toolCallId:e.toolCall.id,status:"failed",error:new Error("not mcp")};const s=this.state.mcpConnections.find(u=>u.serverName===o.serverName);if(!s)return{toolCallId:e.toolCall.id,status:"failed",error:new Error(`ACode MCP server not connected: ${o.serverName}`)};const i=e.arguments,r=Ye(o.toolName),a=$e(o.toolName),l=r?this.state.provider.mcpPollingToolTimeoutMs:a?0:this.state.provider.mcpToolTimeoutMs;try{const u=await this.withBlockingToolCallTracking(o.toolName,()=>r&&Re(o.toolName)==="poll_message"?this.callPollMessageWithSubAgentRace(s,o,i,l):this.callMcpToolWithTimeout(s,o,i,l,r));let c=H(u);return r&&(c=this.expandCommandsInPolledResult(c)),{toolCallId:e.toolCall.id,status:"completed",resultText:c}}catch(u){return this.classifyToolError(e,u)}}async withBlockingToolCallTracking(e,t){if(!te.isLongBlockingMcpToolName(e))return await t();this.activeBlockingToolCalls+=1;try{return await t()}finally{this.activeBlockingToolCalls-=1}}classifyToolError(e,t){const s=(t instanceof Error?t.message:String(t)).includes("timed out after")?"timeout":t instanceof Error&&t.name==="AbortError"?"aborted":"failed";return{toolCallId:e.toolCall.id,status:s,error:t}}async commitToolOutcome(e,t,o,s=[]){const i=e.tool,r=i?.kind==="mcp"?i.serverName:"builtin",a=i?.toolName??e.toolCall.function.name;if(t.status==="completed"&&t.resultText!==void 0){const c=t.resultText;i&&await this.hookBus.dispatch("PostToolUse",{source:i.kind==="mcp"?"mcp":"builtin",...i.kind==="mcp"?{serverName:i.serverName}:{},toolName:i.toolName,exposedName:i.exposedName,result:c}),this.emitAcodeEvent("mcp_status",{action:"tool_result",server:r,tool:a,toolUseId:e.toolCall.id,result:c,...e.batchId?{batchId:e.batchId}:{}}),this.state.conversation.push({role:"tool",tool_call_id:e.toolCall.id,content:c});const d=await this.appendSyntheticMultimodalUserMessage(c,e.toolCall.id,o);d&&s.push(d);return}if(t.status==="superseded"){this.commitSupersededToolResult(e);return}const l=t.error??new Error("Tool execution failed"),u=l instanceof Error?l.message:String(l);if(this.abortRequested||this.state.terminated){this.emitAcodeEvent("mcp_status",{action:"tool_result",server:r,tool:a,toolUseId:e.toolCall.id,result:`[aborted] ${u}`,failed:!0,aborted:!0,...e.batchId?{batchId:e.batchId}:{}}),this.state.conversation.push({role:"tool",tool_call_id:e.toolCall.id,content:`[aborted] ${u}`});return}if(!i){this.state.conversation.push({role:"tool",tool_call_id:e.toolCall.id,content:u}),this.emitAcodeEvent("mcp_status",{action:"tool_result",server:r,tool:a,toolUseId:e.toolCall.id,result:u,failed:!0,...e.batchId?{batchId:e.batchId}:{}});return}this.appendToolFailureResult(e.toolCall,i,l,e.batchId)}commitSupersededToolResult(e){const t=e.immediateError!==void 0?`[cancelled] ${e.immediateError instanceof Error?e.immediateError.message:String(e.immediateError)}`:"[cancelled] Tool execution was superseded by a newer turn.";this.state.conversation.push({role:"tool",tool_call_id:e.toolCall.id,content:t}),this.emitAcodeEvent("mcp_status",{action:"tool_result",server:e.tool?.kind==="mcp"?e.tool.serverName:"builtin",tool:e.tool?.toolName??e.toolCall.function.name,toolUseId:e.toolCall.id,result:t,failed:!0,aborted:!0,...e.batchId?{batchId:e.batchId}:{}})}async executeSingleToolByName(e,t,o){let s=this.state.exposedTools.find(l=>l.exposedName===e);if(s||(s=this.state.exposedTools.find(l=>l.toolName===e)),!s)throw new Error(`Tool not found: ${e}`);if(s.kind==="builtin")return s.execute(t,{toolCallId:o?.toolCallId});const i=this.state.mcpConnections.find(l=>l.serverName===s.serverName);if(!i)throw new Error(`MCP server not found: ${s.serverName}`);const r=Ye(s.toolName),a=r?this.state.provider.mcpPollingToolTimeoutMs:$e(s.toolName)?0:this.state.provider.mcpToolTimeoutMs;if(r&&Re(s.toolName)==="poll_message"){const l=await this.withBlockingToolCallTracking(s.toolName,()=>this.callPollMessageWithSubAgentRace(i,s,t,a,{allowRepoll:!1}));return this.expandCommandsInPolledResult(H(l))}return this.withBlockingToolCallTracking(s.toolName,()=>this.callMcpToolWithTimeout(i,s,t,a,r))}async callMcpToolWithTimeout(e,t,o,s,i,r){const a=s>0?s:Uo,u=!!this.config.sharedMcpConnections?{...o,_aws_sub_agent:!0}:o;for(;;){const c=this.createRuntimeStopWaiter(`ACode MCP tool ${t.serverName}/${t.toolName}`);try{return await E(Promise.race([e.client.callTool({name:t.toolName,arguments:u},void 0,{timeout:a,...r?{signal:r}:{}}),c.promise]),s,`ACode MCP tool ${t.serverName}/${t.toolName}`)}catch(d){if(r?.aborted||!i||s>0||!Rs(d))throw d;this.emitAcodeEvent("warning",{message:`ACode MCP polling tool ${t.serverName}/${t.toolName} reached the MCP SDK timeout window and will continue polling.`})}finally{c.cancel()}}}static formatSubAgentCompletionAsPollResult(e){const t=e.map(o=>{const s=o.error?`Sub-agent ${o.subId} [${o.status}]: ${o.description}
28
34
  Error: ${o.error}`:`Sub-agent ${o.subId} [${o.status}]: ${o.description}
29
- Output: ${o.output.length>500?o.output.slice(0,500)+"... (truncated)":o.output}`;return{msgId:`subagent-completion-${o.subId}-${Date.now()}`,senderId:"ACode-Runtime",senderName:"\u7CFB\u7EDF",content:s,requireReply:!1,prompt:`Sub-agent ${o.subId} (${o.description}) has reached terminal state: ${o.status}. Review its output and decide next steps.`,timestamp:new Date().toISOString()}});return{content:[{type:"text",text:JSON.stringify({directMessages:t,groupMessages:[],fromBuffer:!1,systemMessages:[]},null,2)}]}}static mergeSubAgentCompletionsIntoMcpResult(e,t){if(t.length===0)return e;const o=G(e);let s;try{s=JSON.parse(o)}catch{return e}const r=[...t.map(a=>{const l=a.error?`Sub-agent ${a.subId} [${a.status}]: ${a.description}
35
+ Output: ${o.output.length>500?o.output.slice(0,500)+"... (truncated)":o.output}`;return{msgId:`subagent-completion-${o.subId}-${Date.now()}`,senderId:"ACode-Runtime",senderName:"\u7CFB\u7EDF",content:s,requireReply:!1,prompt:`Sub-agent ${o.subId} (${o.description}) has reached terminal state: ${o.status}. Review its output and decide next steps.`,timestamp:new Date().toISOString()}});return{content:[{type:"text",text:JSON.stringify({directMessages:t,groupMessages:[],fromBuffer:!1,systemMessages:[]},null,2)}]}}static mergeSubAgentCompletionsIntoMcpResult(e,t){if(t.length===0)return e;const o=H(e);let s;try{s=JSON.parse(o)}catch{return e}const r=[...t.map(a=>{const l=a.error?`Sub-agent ${a.subId} [${a.status}]: ${a.description}
30
36
  Error: ${a.error}`:`Sub-agent ${a.subId} [${a.status}]: ${a.description}
31
- Output: ${a.output.length>500?a.output.slice(0,500)+"... (truncated)":a.output}`;return{msgId:`subagent-completion-${a.subId}-${Date.now()}`,senderId:"ACode-Runtime",senderName:"\u7CFB\u7EDF",content:l,requireReply:!1,prompt:`Sub-agent ${a.subId} (${a.description}) has reached terminal state: ${a.status}. Review its output and decide next steps.`,timestamp:new Date().toISOString()}}),...s.directMessages??[]];return{content:[{type:"text",text:JSON.stringify({...s,directMessages:r},null,2)}]}}async recheckMemoryDelegate(e,t,o,s){const i=this.state.mcpConnections.find(r=>r.serverName==="aws-client-agent-mcp");if(!i)return f("[ACodeRuntime] recheckMemoryDelegate: aws-client-agent-mcp connection not found, treating as done"),{done:!0};try{return e==="memory_file_change"?await this.recheckMemoryFileChange(i,t):e==="memory_expiration"?await this.recheckMemoryExpiration(i,t):await this.recheckMemoryCleanup(i,t)}catch(r){return f(`[ACodeRuntime] recheckMemoryDelegate failed (type=${e}, turn=${s}): ${r instanceof Error?r.message:String(r)}, treating as NOT done (retry via recheck loop)`),{done:!1,continueMessage:`\u7ECF\u68C0\u67E5\uFF0C\u65E0\u6CD5\u786E\u8BA4\u4EE5\u4E0B memory \u662F\u5426\u5DF2\u5904\u7406\uFF08\u6821\u9A8C\u5F02\u5E38\uFF1A${r instanceof Error?r.message:String(r)}\uFF09\u3002\u8BF7\u91CD\u65B0\u6267\u884C\u9A8C\u8BC1\u6B65\u9AA4\uFF08read_memory / get_memory_stats\uFF09\u786E\u8BA4\u771F\u5B9E\u72B6\u6001\u540E\u518D\u7EE7\u7EED\u3002`}}}async readMemoryViaMcp(e,t){try{const o=await $(e.client.callTool({name:"read_memory",arguments:{uri:t,_aws_sub_agent:!0}},void 0,{timeout:3e4}),3e4,`recheck read_memory ${t}`),s=G(o),i=JSON.parse(s);return i==null||typeof i!="object"||Array.isArray(i)?null:i}catch(o){throw o}}async recheckMemoryFileChange(e,t){const o=[];if(await Promise.all(t.map(async i=>{const r=await this.readMemoryViaMcp(e,i);r&&r.memory_status==="updating"&&o.push(i)})),o.length===0)return f(`[ACodeRuntime] recheck memory_file_change: all ${t.length} URIs done (memory_status=normal or deleted)`),{done:!0};const s=o.map(i=>`- ${i}`).join(`
32
- `);return f(`[ACodeRuntime] recheck memory_file_change: ${o.length}/${t.length} URIs still updating`),{done:!1,continueMessage:`\u7ECF\u68C0\u67E5\uFF0C\u672A\u5B8C\u6210\u5BF9\u4EE5\u4E0B memory \u7684\u66F4\u65B0\uFF0C\u8BF7\u7EE7\u7EED\uFF1A
37
+ Output: ${a.output.length>500?a.output.slice(0,500)+"... (truncated)":a.output}`;return{msgId:`subagent-completion-${a.subId}-${Date.now()}`,senderId:"ACode-Runtime",senderName:"\u7CFB\u7EDF",content:l,requireReply:!1,prompt:`Sub-agent ${a.subId} (${a.description}) has reached terminal state: ${a.status}. Review its output and decide next steps.`,timestamp:new Date().toISOString()}}),...s.directMessages??[]];return{content:[{type:"text",text:JSON.stringify({...s,directMessages:r},null,2)}]}}async recheckMemoryDelegate(e,t,o,s){const i=this.state.mcpConnections.find(r=>r.serverName==="aws-client-agent-mcp");if(!i)return h("[ACodeRuntime] recheckMemoryDelegate: aws-client-agent-mcp connection not found, treating as done"),{done:!0};try{return e==="memory_file_change"?await this.recheckMemoryFileChange(i,t):e==="memory_expiration"?await this.recheckMemoryExpiration(i,t):await this.recheckMemoryCleanup(i,t)}catch(r){return h(`[ACodeRuntime] recheckMemoryDelegate failed (type=${e}, turn=${s}): ${r instanceof Error?r.message:String(r)}, treating as NOT done (retry via recheck loop)`),{done:!1,continueMessage:`\u7ECF\u68C0\u67E5\uFF0C\u65E0\u6CD5\u786E\u8BA4\u4EE5\u4E0B memory \u662F\u5426\u5DF2\u5904\u7406\uFF08\u6821\u9A8C\u5F02\u5E38\uFF1A${r instanceof Error?r.message:String(r)}\uFF09\u3002\u8BF7\u91CD\u65B0\u6267\u884C\u9A8C\u8BC1\u6B65\u9AA4\uFF08read_memory / get_memory_stats\uFF09\u786E\u8BA4\u771F\u5B9E\u72B6\u6001\u540E\u518D\u7EE7\u7EED\u3002`}}}async readMemoryViaMcp(e,t){try{const o=await E(e.client.callTool({name:"read_memory",arguments:{uri:t,_aws_sub_agent:!0}},void 0,{timeout:3e4}),3e4,`recheck read_memory ${t}`),s=H(o),i=JSON.parse(s);return i==null||typeof i!="object"||Array.isArray(i)?null:i}catch(o){throw o}}async recheckMemoryFileChange(e,t){const o=[];if(await Promise.all(t.map(async i=>{const r=await this.readMemoryViaMcp(e,i);r&&r.memory_status==="updating"&&o.push(i)})),o.length===0)return h(`[ACodeRuntime] recheck memory_file_change: all ${t.length} URIs done (memory_status=normal or deleted)`),{done:!0};const s=o.map(i=>`- ${i}`).join(`
38
+ `);return h(`[ACodeRuntime] recheck memory_file_change: ${o.length}/${t.length} URIs still updating`),{done:!1,continueMessage:`\u7ECF\u68C0\u67E5\uFF0C\u672A\u5B8C\u6210\u5BF9\u4EE5\u4E0B memory \u7684\u66F4\u65B0\uFF0C\u8BF7\u7EE7\u7EED\uFF1A
33
39
  ${s}
34
40
 
35
- \u8FD9\u4E9B memory \u7684 memory_status \u4ECD\u4E3A "updating"\u3002\u8BF7\u91CD\u65B0 read_memory \u67E5\u770B\u5185\u5BB9\uFF0C\u67E5\u770B\u7ED1\u5B9A\u6587\u4EF6\u6700\u65B0\u5185\u5BB9\uFF0C\u5E76\u8C03\u7528 update_memory \u5B8C\u6210\u66F4\u65B0\u3002`}}async recheckMemoryExpiration(e,t){const o=[],s=Date.now();if(await Promise.all(t.map(async r=>{const a=await this.readMemoryViaMcp(e,r);if(!a)return;const l=a.expiresAt??a.expires_at,u=a.memory_status==="recalling",c=typeof l=="string"&&new Date(l).getTime()<s;(u||c)&&o.push(r)})),o.length===0)return f(`[ACodeRuntime] recheck memory_expiration: all ${t.length} URIs done (renewed, cleaned, or no longer expired)`),{done:!0};const i=o.map(r=>`- ${r}`).join(`
36
- `);return f(`[ACodeRuntime] recheck memory_expiration: ${o.length}/${t.length} URIs still expired or recalling`),{done:!1,continueMessage:`\u7ECF\u68C0\u67E5\uFF0C\u672A\u5B8C\u6210\u5BF9\u4EE5\u4E0B memory \u7684\u5904\u7406\uFF0C\u8BF7\u7EE7\u7EED\uFF1A
41
+ \u8FD9\u4E9B memory \u7684 memory_status \u4ECD\u4E3A "updating"\u3002\u8BF7\u91CD\u65B0 read_memory \u67E5\u770B\u5185\u5BB9\uFF0C\u67E5\u770B\u7ED1\u5B9A\u6587\u4EF6\u6700\u65B0\u5185\u5BB9\uFF0C\u5E76\u8C03\u7528 update_memory \u5B8C\u6210\u66F4\u65B0\u3002`}}async recheckMemoryExpiration(e,t){const o=[],s=Date.now();if(await Promise.all(t.map(async r=>{const a=await this.readMemoryViaMcp(e,r);if(!a)return;const l=a.expiresAt??a.expires_at,u=a.memory_status==="recalling",c=typeof l=="string"&&new Date(l).getTime()<s;(u||c)&&o.push(r)})),o.length===0)return h(`[ACodeRuntime] recheck memory_expiration: all ${t.length} URIs done (renewed, cleaned, or no longer expired)`),{done:!0};const i=o.map(r=>`- ${r}`).join(`
42
+ `);return h(`[ACodeRuntime] recheck memory_expiration: ${o.length}/${t.length} URIs still expired or recalling`),{done:!1,continueMessage:`\u7ECF\u68C0\u67E5\uFF0C\u672A\u5B8C\u6210\u5BF9\u4EE5\u4E0B memory \u7684\u5904\u7406\uFF0C\u8BF7\u7EE7\u7EED\uFF1A
37
43
  ${i}
38
44
 
39
- \u8FD9\u4E9B memory \u4ECD\u5904\u4E8E\u8FC7\u671F\u6216\u56DE\u5FC6\u4E2D\u72B6\u6001\u3002\u8BF7\u8C03\u7528 memory_recurrence \u83B7\u53D6\u5185\u5BB9\uFF0C\u5BF9\u9700\u8981\u4FDD\u7559\u7684\u8C03\u7528 update_memory \u7EED\u671F\uFF0C\u5BF9\u65E0\u4EF7\u503C\u7684\u8C03\u7528 memory_recurrence_complete \u6E05\u7406\u3002`}}async recheckMemoryCleanup(e,t){let o;try{const a=await $(e.client.callTool({name:"get_memory_stats",arguments:{_aws_sub_agent:!0}},void 0,{timeout:3e4}),3e4,"recheck get_memory_stats"),l=G(a);o=JSON.parse(l)}catch{return{done:!1,continueMessage:"get_memory_stats \u67E5\u8BE2\u5931\u8D25\uFF0C\u65E0\u6CD5\u786E\u8BA4\u5BB9\u91CF\u662F\u5426\u5DF2\u8FBE\u6807\uFF0C\u8BF7\u91CD\u65B0\u9A8C\u8BC1\u540E\u518D\u7EE7\u7EED\u3002"}}const s=o.by_type??{},i=[];for(const a of t){const l=a.indexOf("/");if(l<0)continue;const u=a.slice(0,l),c=a.slice(l+1),p=s[u]?.by_domain?.[c];p?.exceeded&&i.push(`${u}/${c} (\u5F53\u524D ${p.count??"?"} \u6761\uFF0C\u5EFA\u8BAE\u4E0A\u9650 ${p.limit??"?"})`)}if(i.length===0)return f(`[ACodeRuntime] recheck memory_cleanup: all ${t.length} type/domain pairs within limits`),{done:!0};const r=i.map(a=>`- ${a}`).join(`
40
- `);return f(`[ACodeRuntime] recheck memory_cleanup: ${i.length}/${t.length} type/domain pairs still exceeded`),{done:!1,continueMessage:`\u7ECF\u68C0\u67E5\uFF0C\u4EE5\u4E0B\u7C7B\u578B/\u57DF\u5C1A\u672A\u6574\u7406\u5B8C\u6210\uFF0C\u8BF7\u7EE7\u7EED\uFF1A
45
+ \u8FD9\u4E9B memory \u4ECD\u5904\u4E8E\u8FC7\u671F\u6216\u56DE\u5FC6\u4E2D\u72B6\u6001\u3002\u8BF7\u8C03\u7528 memory_recurrence \u83B7\u53D6\u5185\u5BB9\uFF0C\u5BF9\u9700\u8981\u4FDD\u7559\u7684\u8C03\u7528 update_memory \u7EED\u671F\uFF0C\u5BF9\u65E0\u4EF7\u503C\u7684\u8C03\u7528 memory_recurrence_complete \u6E05\u7406\u3002`}}async recheckMemoryCleanup(e,t){let o;try{const a=await E(e.client.callTool({name:"get_memory_stats",arguments:{_aws_sub_agent:!0}},void 0,{timeout:3e4}),3e4,"recheck get_memory_stats"),l=H(a);o=JSON.parse(l)}catch{return{done:!1,continueMessage:"get_memory_stats \u67E5\u8BE2\u5931\u8D25\uFF0C\u65E0\u6CD5\u786E\u8BA4\u5BB9\u91CF\u662F\u5426\u5DF2\u8FBE\u6807\uFF0C\u8BF7\u91CD\u65B0\u9A8C\u8BC1\u540E\u518D\u7EE7\u7EED\u3002"}}const s=o.by_type??{},i=[];for(const a of t){const l=a.indexOf("/");if(l<0)continue;const u=a.slice(0,l),c=a.slice(l+1),p=s[u]?.by_domain?.[c];p?.exceeded&&i.push(`${u}/${c} (\u5F53\u524D ${p.count??"?"} \u6761\uFF0C\u5EFA\u8BAE\u4E0A\u9650 ${p.limit??"?"})`)}if(i.length===0)return h(`[ACodeRuntime] recheck memory_cleanup: all ${t.length} type/domain pairs within limits`),{done:!0};const r=i.map(a=>`- ${a}`).join(`
46
+ `);return h(`[ACodeRuntime] recheck memory_cleanup: ${i.length}/${t.length} type/domain pairs still exceeded`),{done:!1,continueMessage:`\u7ECF\u68C0\u67E5\uFF0C\u4EE5\u4E0B\u7C7B\u578B/\u57DF\u5C1A\u672A\u6574\u7406\u5B8C\u6210\uFF0C\u8BF7\u7EE7\u7EED\uFF1A
41
47
  ${r}
42
48
 
43
- \u8BF7\u8C03\u7528 list_memories \u67E5\u770B\u8D85\u9650\u8BB0\u5FC6\uFF0C\u5220\u9664\u4E0D\u518D\u9700\u8981\u7684 instance_memory \u6216\u5BF9 instance_long_memory \u8C03\u7528 update_memory \u7EED\u671F\u3002`}}buildMemoryDelegatePrompt(e){const t=e.uris.map(o=>`- ${o}`).join(`
49
+ \u8BF7\u8C03\u7528 list_memories \u67E5\u770B\u8D85\u9650\u8BB0\u5FC6\uFF0C\u5220\u9664\u4E0D\u518D\u9700\u8981\u7684 instance_hotspot_memory \u6216 instance_permanent_memory\uFF08\u6C38\u4E45\u8BB0\u5FC6\u65E0\u8FC7\u671F\uFF0C\u4E0D\u9700\u7EED\u671F\uFF09\u3002`}}buildMemoryDelegatePrompt(e){const t=e.uris.map(o=>`- ${o}`).join(`
44
50
  `);return e.type==="memory_expiration"?`\u4F60\u662F\u4E00\u6761\u4E13\u95E8\u5904\u7406 memory \u8FC7\u671F\u6574\u7406\u7684\u5B50 agent\u3002
45
51
 
46
52
  \u5F53\u524D\u6709\u4EE5\u4E0B ${e.uris.length} \u6761\u5373\u5C06\u9057\u5FD8\u7684\u8BB0\u5FC6\u9700\u8981\u6574\u7406\uFF1A
@@ -54,8 +60,9 @@ ${t}
54
60
  \u5DF2\u7EED\u671F\u7684\u8BB0\u5FC6\uFF08expiresAt \u5728\u672A\u6765\uFF09\u4E0D\u4F1A\u518D\u6B21\u51FA\u73B0
55
61
  2. \u9010\u6761\u5206\u6790\uFF1A\u8FD9\u4E9B\u5185\u5BB9\u662F\u5426\u4ECD\u7136\u6709\u4EF7\u503C\uFF1F\u662F\u5426\u9700\u8981\u4FDD\u7559\u3001\u66F4\u65B0\u6216\u5220\u9664\uFF1F
56
62
  3. \u9010\u6761\u51B3\u7B56\uFF1A
57
- - \u6709\u4EF7\u503C\u7684 \u2192 \u8C03\u7528 update_memory \u7EED\u671F\uFF08TTL \xD72\uFF0C\u7EED\u671F\u540E\u4E0D\u4F1A\u88AB\u5220\u9664\uFF09
58
- - \u9700\u8981\u957F\u671F\u4FDD\u5B58\u7684 \u2192 \u5148\u8C03\u7528 create_memory \u521B\u5EFA\u6C38\u4E45\u7C7B\u578B\u8BB0\u5FC6\uFF08\u5982 project_memory\uFF09\u4FDD\u5B58\u5185\u5BB9\uFF0C\u65E7\u6761\u76EE\u4E0D\u7EED\u671F
63
+ - \u6709\u4EF7\u503C\u7684 \u2192 \u8C03\u7528 update_memory \u7EED\u671F\uFF08\u56FA\u5B9A 24h TTL\uFF0C\u7EED\u671F\u540E\u4E0D\u4F1A\u88AB\u5220\u9664\uFF09
64
+ - \u9700\u8981\u957F\u671F\u4FDD\u5B58\u7684\u73AF\u5883/\u5DE5\u5177\u7ECF\u9A8C \u2192 \u5148\u8C03\u7528 create_memory \u521B\u5EFA instance_permanent_memory \u4FDD\u5B58\u5185\u5BB9\uFF0C\u65E7\u6761\u76EE\u4E0D\u7EED\u671F
65
+ - \u9700\u8981\u957F\u671F\u4FDD\u5B58\u7684\u9879\u76EE\u6587\u6863\u77E5\u8BC6 \u2192 \u5148\u8C03\u7528 create_memory \u521B\u5EFA project_doc_memory\uFF08\u9700\u5E26 bound_files \u4E0E\u89C4\u8303\u6807\u9898/\u5C0F\u8282\uFF09\u4FDD\u5B58\u5185\u5BB9\uFF0C\u65E7\u6761\u76EE\u4E0D\u7EED\u671F
59
66
  - \u786E\u65E0\u4EF7\u503C\u7684 \u2192 \u4E0D\u7EED\u671F\uFF08\u4FDD\u6301[\u56DE\u5FC6\u4E2D]\u72B6\u6001\uFF0C\u7B49\u5F85\u7EDF\u4E00\u6E05\u7406\uFF09
60
67
  4. \u672C\u6279\u5BA1\u67E5\u5B8C\u6BD5\u540E\uFF0C\u8C03\u7528 memory_recurrence_complete(uris=[\u672C\u6279\u786E\u5B9A\u5220\u9664\u7684URI]) \u5220\u9664\u672C\u6279\u65E0\u4EF7\u503C\u6761\u76EE
61
68
  \uFF08\u6CE8\u610F\uFF1A\u8BE5\u5DE5\u5177\u53EA\u505A\u5220\u9664\uFF0C\u4E0D\u505A\u5F52\u6863\uFF1B\u8BF7\u52FF\u5728\u672A\u4F20 uris \u65F6\u63D0\u524D\u8C03\u7528\uFF0C\u5426\u5219\u4F1A\u5220\u9664\u672C\u4EBA\u8BA4\u9886\u7684\u5168\u90E8[\u56DE\u5FC6\u4E2D]\u6761\u76EE\uFF09
@@ -80,7 +87,7 @@ ${t}
80
87
  === \u5904\u7406\u9636\u6BB5 ===
81
88
  1. \u8C03\u7528 get_memory_stats \u67E5\u770B\u5BB9\u91CF\u8BE6\u60C5
82
89
  2. \u8C03\u7528 list_memories \u6309\u7C7B\u578B\u67E5\u770B\u8D85\u9650\u8BB0\u5FC6
83
- 3. \u5220\u9664\u4E0D\u518D\u9700\u8981\u7684 instance_memory\uFF0C\u6216\u66F4\u65B0 instance_long_memory \u7EED\u671F
90
+ 3. \u5220\u9664\u4E0D\u518D\u9700\u8981\u7684 instance_hotspot_memory\uFF0C\u6216\u5220\u9664\u4E0D\u518D\u6709\u4EF7\u503C\u7684 instance_permanent_memory\uFF08\u6C38\u4E45\u8BB0\u5FC6\u65E0\u8FC7\u671F\uFF0C\u4E0D\u9700\u7EED\u671F\uFF09
84
91
 
85
92
  === \u9A8C\u8BC1\u9636\u6BB5\uFF08\u5173\u952E\uFF0C\u4E0D\u53EF\u8DF3\u8FC7\uFF09 ===
86
93
  4. \u518D\u6B21\u8C03\u7528 get_memory_stats \u68C0\u67E5\u5404\u7C7B\u578B/\u57DF\u7684 count \u662F\u5426\u5DF2\u964D\u5230\u5EFA\u8BAE\u4E0A\u9650\u4EE5\u4E0B
@@ -114,5 +121,5 @@ ${a}`}).join(`
114
121
  - \u2705 \u82E5\u5168\u90E8 memory_status \u4E3A "normal"\uFF1A\u9759\u9ED8\u7ED3\u675F
115
122
 
116
123
  \u6CE8\u610F\uFF1A\u4F60\u8FD0\u884C\u5728\u72EC\u7ACB\u7684\u4E0A\u4E0B\u6587\u7A97\u53E3\u4E2D\uFF0C\u4E0D\u5F71\u54CD\u4E3B agent \u7684\u4E3B\u7EBF\u4EFB\u52A1\u3002\u8BF7\u9AD8\u6548\u5B8C\u6210\uFF0C\u4E0D\u8981\u8BE2\u95EE\u7528\u6237\u3002
117
- \u5B8C\u6210\u540E\u7CFB\u7EDF\u4F1A\u901A\u8FC7\u67E5\u8BE2\u670D\u52A1\u7AEF\u771F\u5B9E\u72B6\u6001\u8FDB\u884C\u4E8C\u6B21\u9A8C\u8BC1\uFF08\u4E0D\u4F9D\u8D56\u4F60\u7684\u81EA\u62A5\u7ED3\u679C\uFF09\u3002\u82E5\u9A8C\u8BC1\u53D1\u73B0\u4ECD\u6709 memory \u7684 memory_status \u4E3A "updating"\uFF0C\u4F1A\u53D1\u9001 "\u7ECF\u68C0\u67E5\uFF0C\u672A\u5B8C\u6210\u5BF9\u4EE5\u4E0B memory \u7684\u66F4\u65B0\uFF0C\u8BF7\u7EE7\u7EED" \u6D88\u606F\u8BA9\u4F60\u7EE7\u7EED\u5904\u7406\u3002`}async processMemoryAutoDelegates(e){const t=this.config.subAgentManager;if(!t)return e;let o;try{o=G(e)}catch{return e}let s;try{s=JSON.parse(o)}catch{return e}const i=s.directMessages;if(!Array.isArray(i)||i.length===0)return e;const r=[];let a=0;for(const u of i){const c=u._acodeAutoDelegate;if(c&&(c.type==="memory_expiration"||c.type==="memory_file_change"||c.type==="memory_cleanup")){a++;const d=Date.now(),p=c.uris.filter(g=>this.pendingMemorySubAgents.has(g)).length,T=c.uris.filter(g=>{const y=this.memoryDelegateCooldownUntil.get(g);return y!==void 0&&d<y}).length,_=c.uris.filter(g=>{if(this.pendingMemorySubAgents.has(g))return!1;const y=this.memoryDelegateCooldownUntil.get(g);return!(y!==void 0&&d<y)});if(_.length===0){f(`[ACodeRuntime] Memory ${c.type} skipped: ${p} in-progress, ${T} in cooldown (total ${c.uris.length} URIs)`);continue}const m=Array.isArray(c.fileChanges)?c.fileChanges.filter(g=>_.includes(g.uri)):void 0,h=this.buildMemoryDelegatePrompt({type:c.type,uris:_,fileChanges:m});try{const g=ho("explore",[],Ge(await this.buildAllocatableToolList())).patterns,y=await t.spawn({parentAgentId:this.config.agentId||"unknown",parentSessionId:this.config.sessionId,subagentType:po,description:`Memory ${c.type} auto-delegate (${_.length} items)`,prompt:h,...g.length>0?{allowedTools:g}:{},workingDirectory:this.config.workingDirectory,parentConfig:{...this.config,sharedMcpConnections:this.state?.mcpConnections},silent:!0});for(const k of _)this.pendingMemorySubAgents.set(k,y);const w=new Set(_);t.subscribe(y,()=>{const k=t.getSubAgent(y);if(k&&(k.status==="completed"||k.status==="failed"||k.status==="cancelled")){const v=Date.now();for(const M of w)this.pendingMemorySubAgents.get(M)===y&&this.pendingMemorySubAgents.delete(M),this.memoryDelegateCooldownUntil.set(M,v+st);for(const[M,L]of this.memoryDelegateCooldownUntil)L<=v&&this.memoryDelegateCooldownUntil.delete(M);f(`[ACodeRuntime] Memory delegate sub-agent ${y} finished (${k.status}), ${w.size} URI(s) entered ${st}ms cooldown`)}});const A=c.type,N=async(k,v)=>this.recheckMemoryDelegate(A,_,k,v);await t.startWithRecheck(y,N,3),f(`[ACodeRuntime] Auto-delegated memory ${c.type} to sub-agent ${y} (${_.length} URIs, ${c.uris.length-_.length} already in progress)`)}catch(g){for(const y of _)this.pendingMemorySubAgents.delete(y);f(`[ACodeRuntime] Failed to auto-delegate memory ${c.type} (suppressed, will retry next poll): ${g instanceof Error?g.message:String(g)}`)}}else r.push(u)}if(a===0)return e;if(r.length===0)return null;const l={...s,directMessages:r};return{content:[{type:"text",text:JSON.stringify(l,null,2)}]}}async callPollMessageWithSubAgentRace(e,t,o,s,i={}){const r=this.config.subAgentManager;if(!r)return B("runtime.poll.no-subagent-manager","\u65E0 SubAgentManager\uFF0C\u76F4\u63A5\u8D70\u666E\u901A MCP \u8C03\u7528"),await this.callMcpToolWithTimeout(e,t,o,s,!0);const a=i.allowRepoll!==!1,l=r.takeCompletedSubAgents();if(l.length>0)return f(`[ACodeRuntime] poll_message: ${l.length} sub-agent(s) already completed, returning synthetic result`),B("runtime.poll.subagent-synthetic",`${l.length} \u4E2A\u5B50 agent \u5DF2\u5B8C\u6210\uFF0C\u76F4\u63A5\u8FD4\u56DE\u5408\u6210\u7ED3\u679C\uFF08\u4E0D\u8C03 MCP\uFF09`),Z.formatSubAgentCompletionAsPollResult(l);let u=!1,c=0;for(;;){c++,B("runtime.poll.round-start",`\u7B2C ${c} \u8F6E race \u5F00\u59CB: timeoutMs=${s} silent=${u}`);const d=new AbortController,p=r.waitForAnyCompletion(),T=u?{...o,_aws_silent_poll:!0}:o,_=Date.now(),m=this.callMcpToolWithTimeout(e,t,T,s,!0,d.signal);try{const h=await Promise.race([m.then(w=>({type:"mcp",result:w})),p.promise.then(w=>({type:"subagent",notif:w}))]);if(h.type==="subagent"){B("runtime.poll.race-winner-subagent",`\u5B50 agent \u5148\u5B8C\u6210\uFF0Cabort MCP \u8C03\u7528\uFF08\u5DF2\u7B49\u5F85 ${Date.now()-_}ms\uFF09\u540E\u8FD4\u56DE\u5408\u6210\u7ED3\u679C`),d.abort(),m.catch(()=>{});const w=r.takeCompletedSubAgents();return w.length===0&&w.push(h.notif),f(`[ACodeRuntime] poll_message: sub-agent ${h.notif.subId} completed during race, returning synthetic result (${w.length} notification(s))`),Z.formatSubAgentCompletionAsPollResult(w)}B("runtime.poll.mcp-returned",`MCP \u5148\u8FD4\u56DE\uFF08\u8017\u65F6 ${Date.now()-_}ms\uFF09\uFF0C\u68C0\u67E5\u5F85\u5408\u5E76\u7684\u5B50 agent \u5B8C\u6210`);const g=r.takeCompletedSubAgents();if(g.length>0){f(`[ACodeRuntime] poll_message: MCP returned, merging ${g.length} sub-agent completion(s)`);const w=Z.mergeSubAgentCompletionsIntoMcpResult(h.result,g),A=await this.processMemoryAutoDelegates(w);if(B("runtime.poll.delegate-check",`\u5408\u5E76 ${g.length} \u4E2A\u5B50 agent \u5B8C\u6210\u540E\u59D4\u6258\u68C0\u67E5: processed=${A===null?"\u5168\u90E8\u88AB\u59D4\u6258(null)":"\u6709\u53EF\u4EA4\u4ED8"}`),A!==null){if(this.pollResultHasMessages(A))return B("runtime.poll.final-return",`\u7B2C ${c} \u8F6E\uFF1A\u8FD4\u56DE\uFF08MCP+\u5B50agent\u5408\u5E76\u7ED3\u679C\uFF09`),A;B("runtime.poll.empty-repoll",`\u7B2C ${c} \u8F6E\uFF1A\u5408\u5E76\u7ED3\u679C\u4E3A\u7A7A\uFF0C\u7B49\u5F85 ${Te}ms \u540E\u91CD\u65B0 poll`)}if(!a)return A;await this.waitForDelegateRepoll(),u=!0;continue}const y=await this.processMemoryAutoDelegates(h.result);if(B("runtime.poll.delegate-check",`\u59D4\u6258\u68C0\u67E5: processed=${y===null?"\u5168\u90E8\u88AB\u59D4\u6258(null)":"\u6709\u53EF\u4EA4\u4ED8"}`),y!==null){if(this.pollResultHasMessages(y)){const w=this.summarizePollResultForDebug(y);return B("runtime.poll.final-return",`\u7B2C ${c} \u8F6E\uFF1A\u8FD4\u56DE poll \u7ED3\u679C\u7ED9 LLM: ${w}`),y}B("runtime.poll.empty-repoll",`\u7B2C ${c} \u8F6E\uFF1Apoll \u7ED3\u679C\u65E0\u5B9E\u9645\u6D88\u606F\uFF08directMessages/groupMessages \u5747\u7A7A\uFF09\uFF0C\u7B49\u5F85 ${Te}ms \u540E\u91CD\u65B0 poll`)}if(!a)return B("runtime.poll.delegate-return-no-repoll","\u975E\u9876\u5C42\u8F6E\u8BE2\u5165\u53E3\uFF1A\u59D4\u6258\u5DF2\u5B8C\u6210\uFF0C\u8FD4\u56DE\u539F\u59CB poll \u7ED3\u679C\uFF08\u4E0D\u91CD\u65B0 poll\uFF09"),h.result;await this.waitForDelegateRepoll(),u=!0}catch(h){throw B("runtime.poll.error",`\u7B2C ${c} \u8F6E MCP \u8C03\u7528\u5F02\u5E38: ${h instanceof Error?h.message:String(h)}`),h}finally{p.cancel()}}}summarizePollResultForDebug(e){try{const t=G(e),o=JSON.parse(t),s=Array.isArray(o.directMessages)?o.directMessages:[],i=Array.isArray(o.groupMessages)?o.groupMessages:[];return`dm=${s.length}${s.length>0?JSON.stringify(s.map(r=>({id:r.msgId,ch:r.channel}))):""} gm=${i.length}`}catch{return"(\u65E0\u6CD5\u89E3\u6790\u4E3A JSON)"}}pollResultHasMessages(e){try{const t=G(e),o=JSON.parse(t),s=Array.isArray(o.directMessages)?o.directMessages.length:0,i=Array.isArray(o.groupMessages)?o.groupMessages.length:0;return s>0||i>0}catch{return!0}}async waitForDelegateRepoll(){f(`[ACodeRuntime] poll_message: all messages delegated, waiting ${Te}ms before re-poll`);const e=this.createRuntimeStopWaiter("delegate re-poll delay");try{await Promise.race([new Promise(t=>{const o=setTimeout(t,Te);o.unref&&o.unref()}),e.promise])}finally{e.cancel()}}createRuntimeStopWaiter(e){if(this.state.terminated)return{promise:Promise.reject(new Error(`${e} interrupted because ACode runtime stopped`)),cancel:()=>{}};let t;const o=new Promise((s,i)=>{t=()=>{i(new Error(`${e} interrupted because ACode runtime stopped`))}});return t?(this.stopWaiters.add(t),{promise:o,cancel:()=>{t&&this.stopWaiters.delete(t)}}):{promise:o,cancel:()=>{}}}notifyRuntimeStop(){const e=[...this.stopWaiters];this.stopWaiters.clear();for(const t of e)t()}async appendSyntheticMultimodalUserMessage(e,t,o=this.contextVersion){const s=Re(e);{const r=e.slice(0,200);let a="unknown";try{const l=JSON.parse(e);l&&typeof l=="object"&&!Array.isArray(l)?a=`keys=[${Object.keys(l).join(",")}]`:Array.isArray(l)?a="array":a=typeof l}catch{a="non-json"}_e({stage:"entry",toolCallId:t.slice(0,12),contentLen:e.length,topLevelShape:a,prefix:r})}if(!s.hasImages){let r=null;try{const a=JSON.parse(e);if(a&&typeof a=="object"&&!Array.isArray(a)){const l=[a.directMessages,a.groupMessages];r=[];for(const u of l)if(Array.isArray(u))for(const c of u){if(!c||typeof c!="object")continue;const d=c,p=typeof d.content=="string"?d.content:"",T={senderName:typeof d.senderName=="string"?d.senderName:"",msgId:typeof d.msgId=="string"?d.msgId:"",contentLen:p.length};let _=null;try{const m=JSON.parse(p);m&&typeof m=="object"&&!Array.isArray(m)&&(_=m)}catch{}_?(T.contentKind="json",T.hasAttachmentsField=Array.isArray(_.attachments),T.attachmentCount=Array.isArray(_.attachments)?_.attachments.length:0,T.attachmentKinds=Array.isArray(_.attachments)?_.attachments.map(m=>String(m.type??m.kind??"").toLowerCase()||"(empty)"):[],T.attachmentBase64Lens=Array.isArray(_.attachments)?_.attachments.map(m=>(typeof m.base64Data=="string"?m.base64Data:typeof m.base64=="string"?m.base64:typeof m.data=="string"?m.data:"").length):[]):(T.contentKind="non-json",T.contentPrefix=p.slice(0,60)),r.push(T)}}}catch{}return _e({stage:"hasImages_false",toolCallId:t.slice(0,12),contentLen:e.length,parsedContentKind:Array.isArray(s.content)?"parts":typeof s.content,partsCount:Array.isArray(s.content)?s.content.length:null,dmProbe:r}),null}if(!this.state.provider.supportsImageInput)return this.emitAcodeEvent("error",{message:"ACode skipped image content from tool result because the provider/model is not configured for image input."}),_e({stage:"supportsImageInput_false",toolCallId:t.slice(0,12),providerSupportsImageInput:this.state.provider.supportsImageInput,partsCount:Array.isArray(s.content)?s.content.length:null}),this.cleanToolMessageAttachments(t,"[Tool result contained images; skipped because the current model does not support image input]"),null;let i;try{i=await mt(s.content)}catch(r){const a=r instanceof Error?r.message:String(r),l=Array.isArray(s.content)?s.content.filter(u=>u.type==="image_url").map(u=>{const c=u.image_url.url,d=c.indexOf(",");return{urlHead:c.slice(0,Math.min(30,c.length)),base64Len:d>=0?c.length-d-1:null,isDataUrl:/^data:image\//i.test(c)}}):null;_e({stage:"materialize_threw",toolCallId:t.slice(0,12),errMessage:a,imagePartsCount:l?l.length:0,imageParts:l}),this.emitAcodeEvent("error",{message:`ACode skipped image content from tool result: ${a}`}),i=Array.isArray(s.content)?s.content.map(u=>u.type==="text"?u:{type:"text",text:`[Image omitted: ${a}]`}):s.content}return this.isTurnSuperseded(o)?null:(this.cleanToolMessageAttachments(t,"[Tool result contained images; see user message above]"),{role:"user",content:i})}expandCommandsInPolledResult(e){const t=this.state.commandRegistry;if(!t||t.list().length===0)return e;let o;try{o=JSON.parse(e)}catch{return e}if(!S(o))return e;let s=!1;for(const i of["directMessages","groupMessages"]){const r=o[i];if(Array.isArray(r))for(const a of r){if(!S(a))continue;const l=I(a.content);if(!l)continue;const u=t.expand(l);u&&(a.content=u.prompt,s=!0)}}return s?JSON.stringify(o):e}cleanToolMessageAttachments(e,t){const o=this.state.conversation.find(i=>i.role==="tool"&&i.tool_call_id===e);if(!o||typeof o.content!="string")return;let s;try{const i=JSON.parse(o.content);if(typeof i=="object"&&i!==null){const r={...i};"attachments"in r&&delete r.attachments,ts(r),s=JSON.stringify(r)}}catch{}if(s===void 0){const i=o.content.replace(/\[(图片|文件)\s*:\s*([^\]\n]*?)\s*\]/gi,"").trim();i!==o.content&&(s=i)}s!==void 0&&(o.content=s.length>0?s:t)}appendToolFailureResult(e,t,o,s){const i=gt(t,o),r=It(o),a=r?gt(t,o,r):i;f(`[ACodeRuntime] \u{1F4E4} appendToolFailureResult: emitting mcp_status tool_result (failed: true) for ${t.exposedName}, result length: ${i.length} chars`+(r?`, conversation snapshot: ${r.bytes} bytes`:"")),this.emitAcodeEvent("error",{message:`ACode tool failed: ${t.exposedName}: ${me(o)}`,nonFatal:!0}),this.emitAcodeEvent("mcp_status",{action:"tool_result",server:t.kind==="mcp"?t.serverName:"builtin",tool:t.toolName,toolUseId:e.id,result:i,failed:!0,...s?{batchId:s}:{}}),this.state.conversation.push({role:"tool",tool_call_id:e.id,content:a})}filterSharedMcpConnectionsForSubAgent(e){const t=this.config.subAgentAllowedTools&&this.config.subAgentAllowedTools.length>0?this.config.subAgentAllowedTools:null;return e.map(o=>({...o,tools:o.tools.filter(s=>t?Je(s,t):fo.has(s.toolName))}))}async connectMcpServers(e,t,o){const s=[];for(const[i,r]of Object.entries(e))try{const a=new Mt({name:"acode",version:"0.1.0"}),l=this.createMcpTransport(i,r);await $(a.connect(l),t,`ACode MCP server ${i} connect`);const u={serverName:i,client:a,transport:l,tools:[]};a.setNotificationHandler(xt,()=>{this.refreshMcpConnectionTools(u,t)});const{tools:c}=await $(a.listTools(),t,`ACode MCP server ${i} listTools`);u.tools=Ye(i,c);try{u.instructions=a.getInstructions()}catch{}u.spec=r,s.push(u)}catch(a){const l=a instanceof Error?a.message:String(a);o?.set(i,l),this.emitAcodeEvent("error",{message:`ACode MCP server failed to connect: ${i}: ${l}`})}return s}registerMcpCollapsedGroup(e,t,o){if(!this.toolGroupManager||t.collapsed!==!0||o.tools.length===0)return;const s=Be(e),i=this.toolGroupManager.getRegistration(s),r=t.description?.trim()||vo(o.instructions)||`MCP \u5DE5\u5177\u96C6\uFF1A${e}`,a=this.toolGroupManager.claimedToolNamesBySubGroups(),l=o.tools.map(u=>u.toolName).filter(u=>!a.has(u));l.length!==0&&(this.toolGroupManager.register({key:s,label:t.description?.trim()||e,summary:r,collapsible:!0,toolNames:l,serverName:e}),this.emitAcodeEvent("mcp_status",{serverName:e,status:"collapsed_group_registered",toolCount:l.length,updated:!!i}))}registerToolGroupsFromMcp(e){if(!this.toolGroupManager)return!1;const t=Mo(e.instructions);if(t.length===0)return!1;let o=0;for(const s of t)this.toolGroupManager.getRegistration(s.key)||(this.toolGroupManager.register({key:s.key,label:s.label,summary:"",collapsible:!0,toolNames:s.toolNames}),o+=1);return this.emitAcodeEvent("mcp_status",{serverName:e.serverName,status:"tool_groups_registered",declared:t.length,registered:o}),!0}requestMcpToolsRefresh(e){const t=this.state.mcpConnections.filter(o=>!e||o.serverName===e);for(const o of t)this.refreshMcpConnectionTools(o,this.state.provider.mcpToolTimeoutMs)}async recoverHiddenMcpTool(e){if(this.recoveredToolNames.has(e)||this.recoveredToolNames.size>=Ro)return!1;this.recoveredToolNames.add(e);const t=this.state.mcpConnections.filter(o=>o.tools.some(s=>s.toolName==="expand_tools"||s.exposedName==="expand_tools"||s.exposedName.endsWith("__expand_tools")));if(t.length===0)return!1;for(const o of t)await this.refreshMcpConnectionTools(o,this.state.provider.mcpToolTimeoutMs);return this.state.exposedTools.some(o=>o.toolName===e||o.exposedName===e)}async refreshMcpConnectionTools(e,t){try{const{tools:s}=await $(e.client.listTools(),t,`ACode MCP server ${e.serverName} listTools refresh`);e.tools=Ye(e.serverName,s)}catch(s){this.emitAcodeEvent("warning",{message:`ACode MCP server ${e.serverName} tools/list_changed refresh failed: ${s instanceof Error?s.message:String(s)}`});return}if(!this.exposedToolsInitialized)return;const o=this.state.exposedTools.filter(s=>!(s.kind==="mcp"&&s.serverName===e.serverName));this.state.exposedTools=[...o,...e.tools],this.emitExposedToolsStatus()}createMcpTransport(e,t){if(t.type==="stdio"||t.command){if(!t.command)throw new Error("stdio MCP server requires command");const s=new $t({command:t.command,args:t.args,cwd:t.cwd||this.config.workingDirectory,env:{...this.config.env??{},...t.env??{}},stderr:"pipe"}),i=t.debugStderr===!0?this.ensureMcpStderrBuffer(e):null;return s.stderr?.on("data",r=>{i&&i.push(String(r))}),s}if(!t.url)throw new Error("remote MCP server requires url");const o=t.headers?{headers:t.headers}:void 0;return t.type==="sse"?new vt(new URL(t.url),{requestInit:o}):new Et(new URL(t.url),{requestInit:o})}ensureMcpStderrBuffer(e){let t=this.mcpStderrBuffers.get(e);return t||(t=new mo,this.mcpStderrBuffers.set(e,t)),t}getMcpServerStderr(e,t=100){const o=this.mcpStderrBuffers.get(e);if(!o)return[];const s=Math.max(1,Math.min(Math.floor(t)||100,500));return o.tail(s)}async fetchProfilePrompt(e){for(const t of e)if(t.tools.find(s=>s.toolName==="get_profile"))try{const s=await $(t.client.callTool({name:"get_profile",arguments:{}},void 0,{timeout:ye}),ye,"ACode startup get_profile"),i=this.extractProfileFromToolResult(s);return As(i)}catch(s){return this.emitAcodeEvent("warning",{message:`ACode failed to fetch profile via ${t.serverName}/get_profile: ${s instanceof Error?s.message:String(s)}`}),""}return""}extractProfileFromToolResult(e){if(!S(e))return null;const t=e.content;if(Array.isArray(t)){for(const o of t)if(S(o)&&typeof o.text=="string"&&o.text.trim())try{const s=JSON.parse(o.text);if(S(s))return s}catch{}}return S(e)?e:null}async disconnectMcpServers(){if(!this.state.ownsMcpConnections){this.state.mcpConnections=[],this.state.exposedTools=[],this.exposedToolsInitialized=!1;return}const e=this.state.mcpConnections;this.state.mcpConnections=[],this.state.exposedTools=[],this.exposedToolsInitialized=!1,await Promise.all(e.map(t=>se(`ACode MCP server ${t.serverName} close`,t.transport.close(),o=>{this.emitAcodeEvent("error",{message:o})},this.state.provider.mcpToolTimeoutMs)))}}Z.SKILL_REFRESH_DEBOUNCE_MS=500;export{Z as ACodeRuntime,ge as TOOL_GROUP_MANIFEST_PREFIX,Lo as hasExplicitRequestBodyByteCap,vo as humanReadableInstructions,Mo as parseToolGroupManifest,Do as resolveMaxRequestBodyBytes,gt as toToolErrorResultText};
124
+ \u5B8C\u6210\u540E\u7CFB\u7EDF\u4F1A\u901A\u8FC7\u67E5\u8BE2\u670D\u52A1\u7AEF\u771F\u5B9E\u72B6\u6001\u8FDB\u884C\u4E8C\u6B21\u9A8C\u8BC1\uFF08\u4E0D\u4F9D\u8D56\u4F60\u7684\u81EA\u62A5\u7ED3\u679C\uFF09\u3002\u82E5\u9A8C\u8BC1\u53D1\u73B0\u4ECD\u6709 memory \u7684 memory_status \u4E3A "updating"\uFF0C\u4F1A\u53D1\u9001 "\u7ECF\u68C0\u67E5\uFF0C\u672A\u5B8C\u6210\u5BF9\u4EE5\u4E0B memory \u7684\u66F4\u65B0\uFF0C\u8BF7\u7EE7\u7EED" \u6D88\u606F\u8BA9\u4F60\u7EE7\u7EED\u5904\u7406\u3002`}async processMemoryAutoDelegates(e){const t=this.config.subAgentManager;if(!t)return e;let o;try{o=H(e)}catch{return e}let s;try{s=JSON.parse(o)}catch{return e}const i=s.directMessages;if(!Array.isArray(i)||i.length===0)return e;const r=[];let a=0;for(const u of i){const c=u._acodeAutoDelegate;if(c&&(c.type==="memory_expiration"||c.type==="memory_file_change"||c.type==="memory_cleanup")){a++;const d=Date.now(),p=c.uris.filter(g=>this.pendingMemorySubAgents.has(g)).length,C=c.uris.filter(g=>{const T=this.memoryDelegateCooldownUntil.get(g);return T!==void 0&&d<T}).length,y=c.uris.filter(g=>{if(this.pendingMemorySubAgents.has(g))return!1;const T=this.memoryDelegateCooldownUntil.get(g);return!(T!==void 0&&d<T)});if(y.length===0){h(`[ACodeRuntime] Memory ${c.type} skipped: ${p} in-progress, ${C} in cooldown (total ${c.uris.length} URIs)`);continue}const m=Array.isArray(c.fileChanges)?c.fileChanges.filter(g=>y.includes(g.uri)):void 0,f=this.buildMemoryDelegatePrompt({type:c.type,uris:y,fileChanges:m});try{const g=wo("explore",[],Ve(await this.buildAllocatableToolList())).patterns,T=await t.spawn({parentAgentId:this.config.agentId||"unknown",parentSessionId:this.config.sessionId,subagentType:bo,description:`Memory ${c.type} auto-delegate (${y.length} items)`,prompt:f,...g.length>0?{allowedTools:g}:{},workingDirectory:this.config.workingDirectory,parentConfig:{...this.config,sharedMcpConnections:this.state?.mcpConnections},silent:!0});for(const k of y)this.pendingMemorySubAgents.set(k,T);const _=new Set(y);t.subscribe(T,()=>{const k=t.getSubAgent(T);if(k&&(k.status==="completed"||k.status==="failed"||k.status==="cancelled")){const $=Date.now();for(const v of _)this.pendingMemorySubAgents.get(v)===T&&this.pendingMemorySubAgents.delete(v),this.memoryDelegateCooldownUntil.set(v,$+ct);for(const[v,B]of this.memoryDelegateCooldownUntil)B<=$&&this.memoryDelegateCooldownUntil.delete(v);h(`[ACodeRuntime] Memory delegate sub-agent ${T} finished (${k.status}), ${_.size} URI(s) entered ${ct}ms cooldown`)}});const b=c.type,S=async(k,$)=>this.recheckMemoryDelegate(b,y,k,$);await t.startWithRecheck(T,S,3),h(`[ACodeRuntime] Auto-delegated memory ${c.type} to sub-agent ${T} (${y.length} URIs, ${c.uris.length-y.length} already in progress)`)}catch(g){for(const T of y)this.pendingMemorySubAgents.delete(T);h(`[ACodeRuntime] Failed to auto-delegate memory ${c.type} (suppressed, will retry next poll): ${g instanceof Error?g.message:String(g)}`)}}else r.push(u)}if(a===0)return e;if(r.length===0)return null;const l={...s,directMessages:r};return{content:[{type:"text",text:JSON.stringify(l,null,2)}]}}async callPollMessageWithSubAgentRace(e,t,o,s,i={}){const r=this.config.subAgentManager;if(!r)return U("runtime.poll.no-subagent-manager","\u65E0 SubAgentManager\uFF0C\u76F4\u63A5\u8D70\u666E\u901A MCP \u8C03\u7528"),await this.callMcpToolWithTimeout(e,t,o,s,!0);const a=i.allowRepoll!==!1,l=r.takeCompletedSubAgents();if(l.length>0)return h(`[ACodeRuntime] poll_message: ${l.length} sub-agent(s) already completed, returning synthetic result`),U("runtime.poll.subagent-synthetic",`${l.length} \u4E2A\u5B50 agent \u5DF2\u5B8C\u6210\uFF0C\u76F4\u63A5\u8FD4\u56DE\u5408\u6210\u7ED3\u679C\uFF08\u4E0D\u8C03 MCP\uFF09`),te.formatSubAgentCompletionAsPollResult(l);let u=!1,c=0;for(;;){c++,U("runtime.poll.round-start",`\u7B2C ${c} \u8F6E race \u5F00\u59CB: timeoutMs=${s} silent=${u}`);const d=new AbortController,p=r.waitForAnyCompletion(),C=u?{...o,_aws_silent_poll:!0}:o,y=Date.now(),m=this.callMcpToolWithTimeout(e,t,C,s,!0,d.signal);try{const f=await Promise.race([m.then(_=>({type:"mcp",result:_})),p.promise.then(_=>({type:"subagent",notif:_}))]);if(f.type==="subagent"){U("runtime.poll.race-winner-subagent",`\u5B50 agent \u5148\u5B8C\u6210\uFF0Cabort MCP \u8C03\u7528\uFF08\u5DF2\u7B49\u5F85 ${Date.now()-y}ms\uFF09\u540E\u8FD4\u56DE\u5408\u6210\u7ED3\u679C`),d.abort(),m.catch(()=>{});const _=r.takeCompletedSubAgents();return _.length===0&&_.push(f.notif),h(`[ACodeRuntime] poll_message: sub-agent ${f.notif.subId} completed during race, returning synthetic result (${_.length} notification(s))`),te.formatSubAgentCompletionAsPollResult(_)}U("runtime.poll.mcp-returned",`MCP \u5148\u8FD4\u56DE\uFF08\u8017\u65F6 ${Date.now()-y}ms\uFF09\uFF0C\u68C0\u67E5\u5F85\u5408\u5E76\u7684\u5B50 agent \u5B8C\u6210`);const g=r.takeCompletedSubAgents();if(g.length>0){h(`[ACodeRuntime] poll_message: MCP returned, merging ${g.length} sub-agent completion(s)`);const _=te.mergeSubAgentCompletionsIntoMcpResult(f.result,g),b=await this.processMemoryAutoDelegates(_);if(U("runtime.poll.delegate-check",`\u5408\u5E76 ${g.length} \u4E2A\u5B50 agent \u5B8C\u6210\u540E\u59D4\u6258\u68C0\u67E5: processed=${b===null?"\u5168\u90E8\u88AB\u59D4\u6258(null)":"\u6709\u53EF\u4EA4\u4ED8"}`),b!==null){if(this.pollResultHasMessages(b))return U("runtime.poll.final-return",`\u7B2C ${c} \u8F6E\uFF1A\u8FD4\u56DE\uFF08MCP+\u5B50agent\u5408\u5E76\u7ED3\u679C\uFF09`),b;U("runtime.poll.empty-repoll",`\u7B2C ${c} \u8F6E\uFF1A\u5408\u5E76\u7ED3\u679C\u4E3A\u7A7A\uFF0C\u7B49\u5F85 ${_e}ms \u540E\u91CD\u65B0 poll`)}if(!a)return b;await this.waitForDelegateRepoll(),u=!0;continue}const T=await this.processMemoryAutoDelegates(f.result);if(U("runtime.poll.delegate-check",`\u59D4\u6258\u68C0\u67E5: processed=${T===null?"\u5168\u90E8\u88AB\u59D4\u6258(null)":"\u6709\u53EF\u4EA4\u4ED8"}`),T!==null){if(this.pollResultHasMessages(T)){const _=this.summarizePollResultForDebug(T);return U("runtime.poll.final-return",`\u7B2C ${c} \u8F6E\uFF1A\u8FD4\u56DE poll \u7ED3\u679C\u7ED9 LLM: ${_}`),T}U("runtime.poll.empty-repoll",`\u7B2C ${c} \u8F6E\uFF1Apoll \u7ED3\u679C\u65E0\u5B9E\u9645\u6D88\u606F\uFF08directMessages/groupMessages \u5747\u7A7A\uFF09\uFF0C\u7B49\u5F85 ${_e}ms \u540E\u91CD\u65B0 poll`)}if(!a)return U("runtime.poll.delegate-return-no-repoll","\u975E\u9876\u5C42\u8F6E\u8BE2\u5165\u53E3\uFF1A\u59D4\u6258\u5DF2\u5B8C\u6210\uFF0C\u8FD4\u56DE\u539F\u59CB poll \u7ED3\u679C\uFF08\u4E0D\u91CD\u65B0 poll\uFF09"),f.result;await this.waitForDelegateRepoll(),u=!0}catch(f){throw U("runtime.poll.error",`\u7B2C ${c} \u8F6E MCP \u8C03\u7528\u5F02\u5E38: ${f instanceof Error?f.message:String(f)}`),f}finally{p.cancel()}}}summarizePollResultForDebug(e){try{const t=H(e),o=JSON.parse(t),s=Array.isArray(o.directMessages)?o.directMessages:[],i=Array.isArray(o.groupMessages)?o.groupMessages:[];return`dm=${s.length}${s.length>0?JSON.stringify(s.map(r=>({id:r.msgId,ch:r.channel}))):""} gm=${i.length}`}catch{return"(\u65E0\u6CD5\u89E3\u6790\u4E3A JSON)"}}pollResultHasMessages(e){try{const t=H(e),o=JSON.parse(t),s=Array.isArray(o.directMessages)?o.directMessages.length:0,i=Array.isArray(o.groupMessages)?o.groupMessages.length:0;return s>0||i>0}catch{return!0}}async waitForDelegateRepoll(){h(`[ACodeRuntime] poll_message: all messages delegated, waiting ${_e}ms before re-poll`);const e=this.createRuntimeStopWaiter("delegate re-poll delay");try{await Promise.race([new Promise(t=>{const o=setTimeout(t,_e);o.unref&&o.unref()}),e.promise])}finally{e.cancel()}}createRuntimeStopWaiter(e){if(this.state.terminated)return{promise:Promise.reject(new Error(`${e} interrupted because ACode runtime stopped`)),cancel:()=>{}};let t;const o=new Promise((s,i)=>{t=()=>{i(new Error(`${e} interrupted because ACode runtime stopped`))}});return t?(this.stopWaiters.add(t),{promise:o,cancel:()=>{t&&this.stopWaiters.delete(t)}}):{promise:o,cancel:()=>{}}}notifyRuntimeStop(){const e=[...this.stopWaiters];this.stopWaiters.clear();for(const t of e)t()}async appendSyntheticMultimodalUserMessage(e,t,o=this.contextVersion){const s=Pe(e);{const r=e.slice(0,200);let a="unknown";try{const l=JSON.parse(e);l&&typeof l=="object"&&!Array.isArray(l)?a=`keys=[${Object.keys(l).join(",")}]`:Array.isArray(l)?a="array":a=typeof l}catch{a="non-json"}we({stage:"entry",toolCallId:t.slice(0,12),contentLen:e.length,topLevelShape:a,prefix:r})}if(!s.hasImages){let r=null;try{const a=JSON.parse(e);if(a&&typeof a=="object"&&!Array.isArray(a)){const l=[a.directMessages,a.groupMessages];r=[];for(const u of l)if(Array.isArray(u))for(const c of u){if(!c||typeof c!="object")continue;const d=c,p=typeof d.content=="string"?d.content:"",C={senderName:typeof d.senderName=="string"?d.senderName:"",msgId:typeof d.msgId=="string"?d.msgId:"",contentLen:p.length};let y=null;try{const m=JSON.parse(p);m&&typeof m=="object"&&!Array.isArray(m)&&(y=m)}catch{}y?(C.contentKind="json",C.hasAttachmentsField=Array.isArray(y.attachments),C.attachmentCount=Array.isArray(y.attachments)?y.attachments.length:0,C.attachmentKinds=Array.isArray(y.attachments)?y.attachments.map(m=>String(m.type??m.kind??"").toLowerCase()||"(empty)"):[],C.attachmentBase64Lens=Array.isArray(y.attachments)?y.attachments.map(m=>(typeof m.base64Data=="string"?m.base64Data:typeof m.base64=="string"?m.base64:typeof m.data=="string"?m.data:"").length):[]):(C.contentKind="non-json",C.contentPrefix=p.slice(0,60)),r.push(C)}}}catch{}return we({stage:"hasImages_false",toolCallId:t.slice(0,12),contentLen:e.length,parsedContentKind:Array.isArray(s.content)?"parts":typeof s.content,partsCount:Array.isArray(s.content)?s.content.length:null,dmProbe:r}),null}if(!this.state.provider.supportsImageInput)return this.emitAcodeEvent("error",{message:"ACode skipped image content from tool result because the provider/model is not configured for image input."}),we({stage:"supportsImageInput_false",toolCallId:t.slice(0,12),providerSupportsImageInput:this.state.provider.supportsImageInput,partsCount:Array.isArray(s.content)?s.content.length:null}),this.cleanToolMessageAttachments(t,"[Tool result contained images; skipped because the current model does not support image input]"),null;let i;try{i=await yt(s.content)}catch(r){const a=r instanceof Error?r.message:String(r),l=Array.isArray(s.content)?s.content.filter(u=>u.type==="image_url").map(u=>{const c=u.image_url.url,d=c.indexOf(",");return{urlHead:c.slice(0,Math.min(30,c.length)),base64Len:d>=0?c.length-d-1:null,isDataUrl:/^data:image\//i.test(c)}}):null;we({stage:"materialize_threw",toolCallId:t.slice(0,12),errMessage:a,imagePartsCount:l?l.length:0,imageParts:l}),this.emitAcodeEvent("error",{message:`ACode skipped image content from tool result: ${a}`}),i=Array.isArray(s.content)?s.content.map(u=>u.type==="text"?u:{type:"text",text:`[Image omitted: ${a}]`}):s.content}return this.isTurnSuperseded(o)?null:(this.cleanToolMessageAttachments(t,"[Tool result contained images; see user message above]"),{role:"user",content:i})}expandCommandsInPolledResult(e){const t=this.state.commandRegistry;if(!t||t.list().length===0)return e;let o;try{o=JSON.parse(e)}catch{return e}if(!M(o))return e;let s=!1;for(const i of["directMessages","groupMessages"]){const r=o[i];if(Array.isArray(r))for(const a of r){if(!M(a))continue;const l=R(a.content);if(!l)continue;const u=t.expand(l);u&&(a.content=u.prompt,s=!0)}}return s?JSON.stringify(o):e}cleanToolMessageAttachments(e,t){const o=this.state.conversation.find(i=>i.role==="tool"&&i.tool_call_id===e);if(!o||typeof o.content!="string")return;let s;try{const i=JSON.parse(o.content);if(typeof i=="object"&&i!==null){const r={...i};"attachments"in r&&delete r.attachments,ps(r),s=JSON.stringify(r)}}catch{}if(s===void 0){const i=o.content.replace(/\[(图片|文件)\s*:\s*([^\]\n]*?)\s*\]/gi,"").trim();i!==o.content&&(s=i)}s!==void 0&&(o.content=s.length>0?s:t)}appendToolFailureResult(e,t,o,s){const i=wt(t,o),r=Ut(o),a=r?wt(t,o,r):i;h(`[ACodeRuntime] \u{1F4E4} appendToolFailureResult: emitting mcp_status tool_result (failed: true) for ${t.exposedName}, result length: ${i.length} chars`+(r?`, conversation snapshot: ${r.bytes} bytes`:"")),this.emitAcodeEvent("error",{message:`ACode tool failed: ${t.exposedName}: ${pe(o)}`,nonFatal:!0}),this.emitAcodeEvent("mcp_status",{action:"tool_result",server:t.kind==="mcp"?t.serverName:"builtin",tool:t.toolName,toolUseId:e.id,result:i,failed:!0,...s?{batchId:s}:{}}),this.state.conversation.push({role:"tool",tool_call_id:e.id,content:a})}filterSharedMcpConnectionsForSubAgent(e){const t=this.config.subAgentAllowedTools&&this.config.subAgentAllowedTools.length>0?this.config.subAgentAllowedTools:null;return e.map(o=>({...o,tools:o.tools.filter(s=>t?Xe(s,t):ko.has(s.toolName))}))}async connectMcpServers(e,t,o){const s=[];for(const[i,r]of Object.entries(e))try{const a=new Nt({name:"acode",version:"0.1.0"}),l=this.createMcpTransport(i,r);await E(a.connect(l),t,`ACode MCP server ${i} connect`);const u={serverName:i,client:a,transport:l,tools:[]};a.setNotificationHandler(Bt,()=>{this.refreshMcpConnectionTools(u,t)});const{tools:c}=await E(a.listTools(),t,`ACode MCP server ${i} listTools`);u.tools=ot(i,c);try{u.instructions=a.getInstructions()}catch{}u.spec=r,s.push(u)}catch(a){const l=a instanceof Error?a.message:String(a);o?.set(i,l),this.emitAcodeEvent("error",{message:`ACode MCP server failed to connect: ${i}: ${l}`})}return s}registerMcpCollapsedGroup(e,t,o){if(!this.toolGroupManager||t.collapsed!==!0||o.tools.length===0)return;const s=Fe(e),i=this.toolGroupManager.getRegistration(s),r=t.description?.trim()||Lo(o.instructions)||`MCP \u5DE5\u5177\u96C6\uFF1A${e}`,a=this.toolGroupManager.claimedToolNamesBySubGroups(),l=o.tools.map(u=>u.toolName).filter(u=>!a.has(u));l.length!==0&&(this.toolGroupManager.register({key:s,label:t.description?.trim()||e,summary:r,collapsible:!0,toolNames:l,serverName:e}),this.emitAcodeEvent("mcp_status",{serverName:e,status:"collapsed_group_registered",toolCount:l.length,updated:!!i}))}registerToolGroupsFromMcp(e){if(!this.toolGroupManager)return!1;const t=Oo(e.instructions);if(t.length===0)return!1;let o=0;for(const s of t)this.toolGroupManager.getRegistration(s.key)||(this.toolGroupManager.register({key:s.key,label:s.label,summary:"",collapsible:!0,toolNames:s.toolNames}),o+=1);return this.emitAcodeEvent("mcp_status",{serverName:e.serverName,status:"tool_groups_registered",declared:t.length,registered:o}),!0}requestMcpToolsRefresh(e){const t=this.state.mcpConnections.filter(o=>!e||o.serverName===e);for(const o of t)this.refreshMcpConnectionTools(o,this.state.provider.mcpToolTimeoutMs)}async recoverHiddenMcpTool(e){if(this.recoveredToolNames.has(e)||this.recoveredToolNames.size>=qo)return!1;this.recoveredToolNames.add(e);const t=this.state.mcpConnections.filter(o=>o.tools.some(s=>s.toolName==="expand_tools"||s.exposedName==="expand_tools"||s.exposedName.endsWith("__expand_tools")));if(t.length===0)return!1;for(const o of t)await this.refreshMcpConnectionTools(o,this.state.provider.mcpToolTimeoutMs);return this.state.exposedTools.some(o=>o.toolName===e||o.exposedName===e)}async refreshMcpConnectionTools(e,t){try{const{tools:s}=await E(e.client.listTools(),t,`ACode MCP server ${e.serverName} listTools refresh`);e.tools=ot(e.serverName,s)}catch(s){this.emitAcodeEvent("warning",{message:`ACode MCP server ${e.serverName} tools/list_changed refresh failed: ${s instanceof Error?s.message:String(s)}`});return}if(!this.exposedToolsInitialized)return;const o=this.state.exposedTools.filter(s=>!(s.kind==="mcp"&&s.serverName===e.serverName));this.state.exposedTools=[...o,...e.tools],this.emitExposedToolsStatus()}createMcpTransport(e,t){if(t.type==="stdio"||t.command){if(!t.command)throw new Error("stdio MCP server requires command");const s=new Ot({command:t.command,args:t.args,cwd:t.cwd||this.config.workingDirectory,env:{...this.config.env??{},...t.env??{}},stderr:"pipe"}),i=t.debugStderr===!0?this.ensureMcpStderrBuffer(e):null;return s.stderr?.on("data",r=>{i&&i.push(String(r))}),s}if(!t.url)throw new Error("remote MCP server requires url");const o=t.headers?{headers:t.headers}:void 0;return t.type==="sse"?new Pt(new URL(t.url),{requestInit:o}):new Lt(new URL(t.url),{requestInit:o})}ensureMcpStderrBuffer(e){let t=this.mcpStderrBuffers.get(e);return t||(t=new _o,this.mcpStderrBuffers.set(e,t)),t}getMcpServerStderr(e,t=100){const o=this.mcpStderrBuffers.get(e);if(!o)return[];const s=Math.max(1,Math.min(Math.floor(t)||100,500));return o.tail(s)}async fetchProfilePrompt(e){for(const t of e)if(t.tools.find(s=>s.toolName==="get_profile"))try{const s=await E(t.client.callTool({name:"get_profile",arguments:{}},void 0,{timeout:Ae}),Ae,"ACode startup get_profile"),i=this.extractProfileFromToolResult(s);return Ns(i)}catch(s){return this.emitAcodeEvent("warning",{message:`ACode failed to fetch profile via ${t.serverName}/get_profile: ${s instanceof Error?s.message:String(s)}`}),""}return""}extractProfileFromToolResult(e){if(!M(e))return null;const t=e.content;if(Array.isArray(t)){for(const o of t)if(M(o)&&typeof o.text=="string"&&o.text.trim())try{const s=JSON.parse(o.text);if(M(s))return s}catch{}}return M(e)?e:null}async disconnectMcpServers(){if(!this.state.ownsMcpConnections){this.state.mcpConnections=[],this.state.exposedTools=[],this.exposedToolsInitialized=!1;return}const e=this.state.mcpConnections;this.state.mcpConnections=[],this.state.exposedTools=[],this.exposedToolsInitialized=!1,await Promise.all(e.map(t=>ie(`ACode MCP server ${t.serverName} close`,t.transport.close(),o=>{this.emitAcodeEvent("error",{message:o})},this.state.provider.mcpToolTimeoutMs)))}}te.SKILL_REFRESH_DEBOUNCE_MS=500;export{te as ACodeRuntime,Ce as TOOL_GROUP_MANIFEST_PREFIX,Go as hasExplicitRequestBodyByteCap,Lo as humanReadableInstructions,Oo as parseToolGroupManifest,Jo as resolveMaxRequestBodyBytes,wt as toToolErrorResultText};
118
125