aws-runtime-bridge 1.9.33 → 1.9.41

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 (324) hide show
  1. package/dist/adapter/AcodeSdkAdapter.d.ts +66 -5
  2. package/dist/adapter/AcodeSdkAdapter.d.ts.map +1 -1
  3. package/dist/adapter/AcodeSdkAdapter.js +771 -69
  4. package/dist/adapter/ClaudeSdkAdapter.d.ts +6 -0
  5. package/dist/adapter/ClaudeSdkAdapter.d.ts.map +1 -1
  6. package/dist/adapter/ClaudeSdkAdapter.js +24 -1
  7. package/dist/adapter/OpencodeSdkAdapter.d.ts +19 -0
  8. package/dist/adapter/OpencodeSdkAdapter.d.ts.map +1 -1
  9. package/dist/adapter/OpencodeSdkAdapter.js +62 -0
  10. package/dist/adapter/idle-poll-loop.d.ts +2 -1
  11. package/dist/adapter/idle-poll-loop.d.ts.map +1 -1
  12. package/dist/adapter/types.d.ts +86 -9
  13. package/dist/adapter/types.d.ts.map +1 -1
  14. package/dist/adapter/types.js +15 -5
  15. package/dist/index.js +15 -0
  16. package/dist/routes/acode-todos.d.ts +11 -0
  17. package/dist/routes/acode-todos.d.ts.map +1 -0
  18. package/dist/routes/acode-todos.js +75 -0
  19. package/dist/routes/ai-sources.js +4 -1
  20. package/dist/routes/dashboard.d.ts.map +1 -1
  21. package/dist/routes/dashboard.js +1 -1
  22. package/dist/routes/memory.d.ts +1 -1
  23. package/dist/routes/memory.d.ts.map +1 -1
  24. package/dist/routes/memory.js +3 -3
  25. package/dist/routes/pty.d.ts.map +1 -1
  26. package/dist/routes/pty.js +9 -0
  27. package/dist/routes/runtime-binding.d.ts.map +1 -1
  28. package/dist/routes/runtime-binding.js +6 -3
  29. package/dist/routes/sessions.js +89 -4
  30. package/dist/routes/sub-agents.d.ts +14 -0
  31. package/dist/routes/sub-agents.d.ts.map +1 -0
  32. package/dist/routes/sub-agents.js +267 -0
  33. package/dist/routes/terminal.d.ts +12 -1
  34. package/dist/routes/terminal.d.ts.map +1 -1
  35. package/dist/routes/terminal.js +326 -24
  36. package/dist/services/acode-package.d.ts +8 -1
  37. package/dist/services/acode-package.d.ts.map +1 -1
  38. package/dist/services/acode-package.js +33 -4
  39. package/dist/services/agent-event-store.d.ts +1 -0
  40. package/dist/services/agent-event-store.d.ts.map +1 -1
  41. package/dist/services/aws-client-agent-mcp.d.ts.map +1 -1
  42. package/dist/services/aws-client-agent-mcp.js +11 -4
  43. package/dist/services/event-delta-pusher.js +4 -4
  44. package/dist/services/fileSnapshotStore.js +1 -1
  45. package/dist/services/legacy-path-migration.d.ts +3 -0
  46. package/dist/services/legacy-path-migration.d.ts.map +1 -0
  47. package/dist/services/legacy-path-migration.js +66 -0
  48. package/dist/services/lifecycle-state.d.ts.map +1 -1
  49. package/dist/services/lifecycle-state.js +1 -1
  50. package/dist/services/runtime-binding.d.ts +5 -0
  51. package/dist/services/runtime-binding.d.ts.map +1 -1
  52. package/dist/services/runtime-binding.js +33 -1
  53. package/dist/services/session-output.d.ts +10 -1
  54. package/dist/services/session-output.d.ts.map +1 -1
  55. package/dist/services/session-output.js +54 -4
  56. package/dist/services/sub-agent-manager-instance.d.ts +4 -0
  57. package/dist/services/sub-agent-manager-instance.d.ts.map +1 -0
  58. package/dist/services/sub-agent-manager-instance.js +12 -0
  59. package/dist/services/workspace-files.d.ts +1 -0
  60. package/dist/services/workspace-files.d.ts.map +1 -1
  61. package/dist/services/workspace-files.js +57 -1
  62. package/package/acode/dist/ask-user-question-tool.d.ts +47 -0
  63. package/package/acode/dist/ask-user-question-tool.d.ts.map +1 -0
  64. package/package/acode/dist/ask-user-question-tool.js +233 -0
  65. package/package/acode/dist/built-in-file-tools.d.ts +2 -0
  66. package/package/acode/dist/built-in-file-tools.d.ts.map +1 -1
  67. package/package/acode/dist/built-in-file-tools.js +504 -3
  68. package/package/acode/dist/compaction.d.ts +242 -0
  69. package/package/acode/dist/compaction.d.ts.map +1 -0
  70. package/package/acode/dist/compaction.js +919 -0
  71. package/package/acode/dist/config.d.ts +6 -1
  72. package/package/acode/dist/config.d.ts.map +1 -1
  73. package/package/acode/dist/config.js +27 -2
  74. package/package/acode/dist/index.d.ts +4 -0
  75. package/package/acode/dist/index.d.ts.map +1 -1
  76. package/package/acode/dist/index.js +4 -0
  77. package/package/acode/dist/runtime.d.ts +257 -0
  78. package/package/acode/dist/runtime.d.ts.map +1 -1
  79. package/package/acode/dist/runtime.js +1843 -191
  80. package/package/acode/dist/skill-tool.d.ts +30 -0
  81. package/package/acode/dist/skill-tool.d.ts.map +1 -0
  82. package/package/acode/dist/skill-tool.js +174 -0
  83. package/package/acode/dist/sub-agent-manager.d.ts +264 -0
  84. package/package/acode/dist/sub-agent-manager.d.ts.map +1 -0
  85. package/package/acode/dist/sub-agent-manager.js +825 -0
  86. package/package/acode/dist/sub-agent-store.d.ts +40 -0
  87. package/package/acode/dist/sub-agent-store.d.ts.map +1 -0
  88. package/package/acode/dist/sub-agent-store.js +164 -0
  89. package/package/acode/dist/sub-agent-tools.d.ts +72 -0
  90. package/package/acode/dist/sub-agent-tools.d.ts.map +1 -0
  91. package/package/acode/dist/sub-agent-tools.js +429 -0
  92. package/package/acode/dist/sub-agent-types.d.ts +85 -0
  93. package/package/acode/dist/sub-agent-types.d.ts.map +1 -0
  94. package/package/acode/dist/sub-agent-types.js +8 -0
  95. package/package/acode/dist/todo-store.d.ts +42 -0
  96. package/package/acode/dist/todo-store.d.ts.map +1 -0
  97. package/package/acode/dist/todo-store.js +68 -0
  98. package/package/acode/dist/todo-tool.d.ts +6 -0
  99. package/package/acode/dist/todo-tool.d.ts.map +1 -0
  100. package/package/acode/dist/todo-tool.js +138 -0
  101. package/package/acode/dist/types.d.ts +41 -1
  102. package/package/acode/dist/types.d.ts.map +1 -1
  103. package/package/acode/package.json +13 -2
  104. package/package/aws-client-agent-mcp/dist/agent-client.d.ts +9 -0
  105. package/package/aws-client-agent-mcp/dist/agent-client.d.ts.map +1 -1
  106. package/package/aws-client-agent-mcp/dist/agent-client.js +69 -10
  107. package/package/aws-client-agent-mcp/dist/agent-client.js.map +1 -1
  108. package/package/aws-client-agent-mcp/dist/config.d.ts.map +1 -1
  109. package/package/aws-client-agent-mcp/dist/config.js +4 -0
  110. package/package/aws-client-agent-mcp/dist/config.js.map +1 -1
  111. package/package/aws-client-agent-mcp/dist/constants.d.ts +2 -0
  112. package/package/aws-client-agent-mcp/dist/constants.d.ts.map +1 -1
  113. package/package/aws-client-agent-mcp/dist/constants.js +3 -1
  114. package/package/aws-client-agent-mcp/dist/constants.js.map +1 -1
  115. package/package/aws-client-agent-mcp/dist/context-manager.d.ts +4 -1
  116. package/package/aws-client-agent-mcp/dist/context-manager.d.ts.map +1 -1
  117. package/package/aws-client-agent-mcp/dist/context-manager.js +6 -2
  118. package/package/aws-client-agent-mcp/dist/context-manager.js.map +1 -1
  119. package/package/aws-client-agent-mcp/dist/context-manager.test.js +5 -3
  120. package/package/aws-client-agent-mcp/dist/context-manager.test.js.map +1 -1
  121. package/package/aws-client-agent-mcp/dist/http-client.d.ts +5 -0
  122. package/package/aws-client-agent-mcp/dist/http-client.d.ts.map +1 -1
  123. package/package/aws-client-agent-mcp/dist/http-client.js +15 -1
  124. package/package/aws-client-agent-mcp/dist/http-client.js.map +1 -1
  125. package/package/aws-client-agent-mcp/dist/mcp-server.d.ts +162 -71
  126. package/package/aws-client-agent-mcp/dist/mcp-server.d.ts.map +1 -1
  127. package/package/aws-client-agent-mcp/dist/mcp-server.js +1007 -504
  128. package/package/aws-client-agent-mcp/dist/mcp-server.js.map +1 -1
  129. package/package/aws-client-agent-mcp/dist/mcp-server.test.js +371 -253
  130. package/package/aws-client-agent-mcp/dist/mcp-server.test.js.map +1 -1
  131. package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts +6 -17
  132. package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts.map +1 -1
  133. package/package/aws-client-agent-mcp/dist/mcp-tools.js +20 -75
  134. package/package/aws-client-agent-mcp/dist/mcp-tools.js.map +1 -1
  135. package/package/aws-client-agent-mcp/dist/memory-store.d.ts +45 -45
  136. package/package/aws-client-agent-mcp/dist/memory-store.d.ts.map +1 -1
  137. package/package/aws-client-agent-mcp/dist/memory-store.js +114 -162
  138. package/package/aws-client-agent-mcp/dist/memory-store.js.map +1 -1
  139. package/package/aws-client-agent-mcp/dist/memory-store.test.js +175 -164
  140. package/package/aws-client-agent-mcp/dist/memory-store.test.js.map +1 -1
  141. package/package/aws-client-agent-mcp/dist/memory-tools.d.ts +3 -9
  142. package/package/aws-client-agent-mcp/dist/memory-tools.d.ts.map +1 -1
  143. package/package/aws-client-agent-mcp/dist/memory-tools.js +31 -58
  144. package/package/aws-client-agent-mcp/dist/memory-tools.js.map +1 -1
  145. package/package/aws-client-agent-mcp/dist/message-buffer.d.ts +40 -9
  146. package/package/aws-client-agent-mcp/dist/message-buffer.d.ts.map +1 -1
  147. package/package/aws-client-agent-mcp/dist/message-buffer.js +123 -23
  148. package/package/aws-client-agent-mcp/dist/message-buffer.js.map +1 -1
  149. package/package/aws-client-agent-mcp/dist/server-memory-store.d.ts +13 -13
  150. package/package/aws-client-agent-mcp/dist/server-memory-store.d.ts.map +1 -1
  151. package/package/aws-client-agent-mcp/dist/server-memory-store.js +23 -16
  152. package/package/aws-client-agent-mcp/dist/server-memory-store.js.map +1 -1
  153. package/package/aws-client-agent-mcp/dist/status-reporter.d.ts.map +1 -1
  154. package/package/aws-client-agent-mcp/dist/status-reporter.js +8 -5
  155. package/package/aws-client-agent-mcp/dist/status-reporter.js.map +1 -1
  156. package/package/aws-client-agent-mcp/dist/status-reporter.test.js +93 -0
  157. package/package/aws-client-agent-mcp/dist/status-reporter.test.js.map +1 -1
  158. package/package/aws-client-agent-mcp/dist/types.d.ts +12 -25
  159. package/package/aws-client-agent-mcp/dist/types.d.ts.map +1 -1
  160. package/package/aws-client-agent-mcp/dist/types.js.map +1 -1
  161. package/package/aws-client-agent-mcp/dist/websocket-client.d.ts +34 -1
  162. package/package/aws-client-agent-mcp/dist/websocket-client.d.ts.map +1 -1
  163. package/package/aws-client-agent-mcp/dist/websocket-client.js +146 -18
  164. package/package/aws-client-agent-mcp/dist/websocket-client.js.map +1 -1
  165. package/package.json +17 -7
  166. package/dist/adapter/AcodeSdkAdapter.test.d.ts +0 -2
  167. package/dist/adapter/AcodeSdkAdapter.test.d.ts.map +0 -1
  168. package/dist/adapter/AcodeSdkAdapter.test.js +0 -2000
  169. package/dist/adapter/AdapterRegistry.test.d.ts +0 -5
  170. package/dist/adapter/AdapterRegistry.test.d.ts.map +0 -1
  171. package/dist/adapter/AdapterRegistry.test.js +0 -118
  172. package/dist/adapter/ClaudeSdkAdapter.test.d.ts +0 -2
  173. package/dist/adapter/ClaudeSdkAdapter.test.d.ts.map +0 -1
  174. package/dist/adapter/ClaudeSdkAdapter.test.js +0 -311
  175. package/dist/adapter/CodexSdkAdapter.test.d.ts +0 -2
  176. package/dist/adapter/CodexSdkAdapter.test.d.ts.map +0 -1
  177. package/dist/adapter/CodexSdkAdapter.test.js +0 -270
  178. package/dist/adapter/OpencodeSdkAdapter.test.d.ts +0 -2
  179. package/dist/adapter/OpencodeSdkAdapter.test.d.ts.map +0 -1
  180. package/dist/adapter/OpencodeSdkAdapter.test.js +0 -158
  181. package/dist/adapter/acode-tool-names.test.d.ts +0 -2
  182. package/dist/adapter/acode-tool-names.test.d.ts.map +0 -1
  183. package/dist/adapter/acode-tool-names.test.js +0 -28
  184. package/dist/adapter/adapter.test.d.ts +0 -5
  185. package/dist/adapter/adapter.test.d.ts.map +0 -1
  186. package/dist/adapter/adapter.test.js +0 -180
  187. package/dist/adapter/idle-poll-loop.test.d.ts +0 -2
  188. package/dist/adapter/idle-poll-loop.test.d.ts.map +0 -1
  189. package/dist/adapter/idle-poll-loop.test.js +0 -85
  190. package/dist/adapter/types.test.d.ts +0 -2
  191. package/dist/adapter/types.test.d.ts.map +0 -1
  192. package/dist/adapter/types.test.js +0 -50
  193. package/dist/adapters/cc-switch/mcp-acode.test.d.ts +0 -2
  194. package/dist/adapters/cc-switch/mcp-acode.test.d.ts.map +0 -1
  195. package/dist/adapters/cc-switch/mcp-acode.test.js +0 -80
  196. package/dist/adapters/cc-switch/mcp-claudecode.test.d.ts +0 -2
  197. package/dist/adapters/cc-switch/mcp-claudecode.test.d.ts.map +0 -1
  198. package/dist/adapters/cc-switch/mcp-claudecode.test.js +0 -75
  199. package/dist/adapters/cc-switch/mcp-codex.test.d.ts +0 -2
  200. package/dist/adapters/cc-switch/mcp-codex.test.d.ts.map +0 -1
  201. package/dist/adapters/cc-switch/mcp-codex.test.js +0 -126
  202. package/dist/adapters/cc-switch/mcp-opencode.test.d.ts +0 -2
  203. package/dist/adapters/cc-switch/mcp-opencode.test.d.ts.map +0 -1
  204. package/dist/adapters/cc-switch/mcp-opencode.test.js +0 -62
  205. package/dist/adapters/cc-switch/skill-directory.test.d.ts +0 -2
  206. package/dist/adapters/cc-switch/skill-directory.test.d.ts.map +0 -1
  207. package/dist/adapters/cc-switch/skill-directory.test.js +0 -74
  208. package/dist/config.test.d.ts +0 -2
  209. package/dist/config.test.d.ts.map +0 -1
  210. package/dist/config.test.js +0 -107
  211. package/dist/routes/ai-sources.test.d.ts +0 -2
  212. package/dist/routes/ai-sources.test.d.ts.map +0 -1
  213. package/dist/routes/ai-sources.test.js +0 -169
  214. package/dist/routes/file-browser.test.d.ts +0 -5
  215. package/dist/routes/file-browser.test.d.ts.map +0 -1
  216. package/dist/routes/file-browser.test.js +0 -155
  217. package/dist/routes/git.test.d.ts +0 -2
  218. package/dist/routes/git.test.d.ts.map +0 -1
  219. package/dist/routes/git.test.js +0 -330
  220. package/dist/routes/instance.test.d.ts +0 -5
  221. package/dist/routes/instance.test.d.ts.map +0 -1
  222. package/dist/routes/instance.test.js +0 -389
  223. package/dist/routes/mcp.test.d.ts +0 -5
  224. package/dist/routes/mcp.test.d.ts.map +0 -1
  225. package/dist/routes/mcp.test.js +0 -92
  226. package/dist/routes/memory-route-wiring.test.d.ts +0 -2
  227. package/dist/routes/memory-route-wiring.test.d.ts.map +0 -1
  228. package/dist/routes/memory-route-wiring.test.js +0 -15
  229. package/dist/routes/memory.test.d.ts +0 -2
  230. package/dist/routes/memory.test.d.ts.map +0 -1
  231. package/dist/routes/memory.test.js +0 -177
  232. package/dist/routes/properties.test.d.ts +0 -5
  233. package/dist/routes/properties.test.d.ts.map +0 -1
  234. package/dist/routes/properties.test.js +0 -72
  235. package/dist/routes/pty.test.d.ts +0 -2
  236. package/dist/routes/pty.test.d.ts.map +0 -1
  237. package/dist/routes/pty.test.js +0 -82
  238. package/dist/routes/runtime-binding.test.d.ts +0 -2
  239. package/dist/routes/runtime-binding.test.d.ts.map +0 -1
  240. package/dist/routes/runtime-binding.test.js +0 -32
  241. package/dist/routes/sessions.test.d.ts +0 -5
  242. package/dist/routes/sessions.test.d.ts.map +0 -1
  243. package/dist/routes/sessions.test.js +0 -86
  244. package/dist/routes/skills.test.d.ts +0 -5
  245. package/dist/routes/skills.test.d.ts.map +0 -1
  246. package/dist/routes/skills.test.js +0 -50
  247. package/dist/routes/system-metrics.test.d.ts +0 -2
  248. package/dist/routes/system-metrics.test.d.ts.map +0 -1
  249. package/dist/routes/system-metrics.test.js +0 -16
  250. package/dist/routes/terminal.stop-options.test.d.ts +0 -2
  251. package/dist/routes/terminal.stop-options.test.d.ts.map +0 -1
  252. package/dist/routes/terminal.stop-options.test.js +0 -39
  253. package/dist/routes/terminal.test.d.ts +0 -2
  254. package/dist/routes/terminal.test.d.ts.map +0 -1
  255. package/dist/routes/terminal.test.js +0 -746
  256. package/dist/routes/yml.test.d.ts +0 -5
  257. package/dist/routes/yml.test.d.ts.map +0 -1
  258. package/dist/routes/yml.test.js +0 -58
  259. package/dist/services/ai-source-apply.test.d.ts +0 -2
  260. package/dist/services/ai-source-apply.test.d.ts.map +0 -1
  261. package/dist/services/ai-source-apply.test.js +0 -138
  262. package/dist/services/auto-register.test.d.ts +0 -2
  263. package/dist/services/auto-register.test.d.ts.map +0 -1
  264. package/dist/services/auto-register.test.js +0 -184
  265. package/dist/services/aws-client-agent-mcp.test.d.ts +0 -2
  266. package/dist/services/aws-client-agent-mcp.test.d.ts.map +0 -1
  267. package/dist/services/aws-client-agent-mcp.test.js +0 -242
  268. package/dist/services/bridge-package-publish-hooks.test.d.ts +0 -2
  269. package/dist/services/bridge-package-publish-hooks.test.d.ts.map +0 -1
  270. package/dist/services/bridge-package-publish-hooks.test.js +0 -136
  271. package/dist/services/cc-switch-discovery.test.d.ts +0 -2
  272. package/dist/services/cc-switch-discovery.test.d.ts.map +0 -1
  273. package/dist/services/cc-switch-discovery.test.js +0 -56
  274. package/dist/services/cli-commands.test.d.ts +0 -2
  275. package/dist/services/cli-commands.test.d.ts.map +0 -1
  276. package/dist/services/cli-commands.test.js +0 -230
  277. package/dist/services/instance-init-service.test.d.ts +0 -2
  278. package/dist/services/instance-init-service.test.d.ts.map +0 -1
  279. package/dist/services/instance-init-service.test.js +0 -140
  280. package/dist/services/instance-state.test.d.ts +0 -2
  281. package/dist/services/instance-state.test.d.ts.map +0 -1
  282. package/dist/services/instance-state.test.js +0 -245
  283. package/dist/services/mcp-launch-binding-queue.test.d.ts +0 -2
  284. package/dist/services/mcp-launch-binding-queue.test.d.ts.map +0 -1
  285. package/dist/services/mcp-launch-binding-queue.test.js +0 -181
  286. package/dist/services/runtime-binding.test.d.ts +0 -2
  287. package/dist/services/runtime-binding.test.d.ts.map +0 -1
  288. package/dist/services/runtime-binding.test.js +0 -78
  289. package/dist/services/runtime-lifecycle-policy.test.d.ts +0 -2
  290. package/dist/services/runtime-lifecycle-policy.test.d.ts.map +0 -1
  291. package/dist/services/runtime-lifecycle-policy.test.js +0 -41
  292. package/dist/services/session-output.test.d.ts +0 -5
  293. package/dist/services/session-output.test.d.ts.map +0 -1
  294. package/dist/services/session-output.test.js +0 -177
  295. package/dist/services/startup-config-wizard.test.d.ts +0 -2
  296. package/dist/services/startup-config-wizard.test.d.ts.map +0 -1
  297. package/dist/services/startup-config-wizard.test.js +0 -184
  298. package/dist/services/terminal-persistence.test.d.ts +0 -5
  299. package/dist/services/terminal-persistence.test.d.ts.map +0 -1
  300. package/dist/services/terminal-persistence.test.js +0 -159
  301. package/dist/services/tool-installer.test.d.ts +0 -2
  302. package/dist/services/tool-installer.test.d.ts.map +0 -1
  303. package/dist/services/tool-installer.test.js +0 -225
  304. package/dist/services/workspace-files.test.d.ts +0 -2
  305. package/dist/services/workspace-files.test.d.ts.map +0 -1
  306. package/dist/services/workspace-files.test.js +0 -648
  307. package/dist/services/workspace-watch.test.d.ts +0 -2
  308. package/dist/services/workspace-watch.test.d.ts.map +0 -1
  309. package/dist/services/workspace-watch.test.js +0 -38
  310. package/dist/utils/file-utils.test.d.ts +0 -2
  311. package/dist/utils/file-utils.test.d.ts.map +0 -1
  312. package/dist/utils/file-utils.test.js +0 -244
  313. package/dist/utils/logger.test.d.ts +0 -2
  314. package/dist/utils/logger.test.d.ts.map +0 -1
  315. package/dist/utils/logger.test.js +0 -93
  316. package/dist/utils/sdk-package-loader.test.d.ts +0 -2
  317. package/dist/utils/sdk-package-loader.test.d.ts.map +0 -1
  318. package/dist/utils/sdk-package-loader.test.js +0 -84
  319. package/dist/utils/validation.test.d.ts +0 -2
  320. package/dist/utils/validation.test.d.ts.map +0 -1
  321. package/dist/utils/validation.test.js +0 -88
  322. package/dist/utils/yaml-utils.test.d.ts +0 -2
  323. package/dist/utils/yaml-utils.test.d.ts.map +0 -1
  324. package/dist/utils/yaml-utils.test.js +0 -363
@@ -27,6 +27,56 @@ import { logger as log } from "../utils/logger.js";
27
27
  export const terminalRouter = Router();
28
28
  // 导出 SDK 会话存储,供其他模块使用(如 sessions.ts)
29
29
  export const sdkSessions = new Map();
30
+ // ── 活跃状态定期刷新,防止长时间 LLM 调用期间 WebSocket 心跳超时导致 LOST ──
31
+ /**
32
+ * 状态刷新间隔(毫秒)。
33
+ * 服务端 WebSocket 空闲超时默认 60 秒(maxIdleTimeMs),取 45 秒作为刷新周期,
34
+ * 留出足够的余量防止因网络抖动或事件循环延迟导致的超时。
35
+ */
36
+ const STATUS_REFRESH_INTERVAL_MS = 45_000;
37
+ /** 每个 session 的定期刷新定时器,仅在 thinking/tool_using/compacting 时运行 */
38
+ const statusRefreshTimers = new Map();
39
+ /**
40
+ * 启动 session 定期状态刷新。
41
+ * 每隔 STATUS_REFRESH_INTERVAL_MS 向服务端发送一次当前运行状态,
42
+ * 刷新服务端 WebSocket 会话的 lastActiveTime,避免长时间无消息导致连接断开 → LOST。
43
+ */
44
+ function startStatusRefresh(sessionId) {
45
+ if (statusRefreshTimers.has(sessionId))
46
+ return;
47
+ const timer = setInterval(() => {
48
+ const entry = sdkSessions.get(sessionId);
49
+ if (!entry) {
50
+ stopStatusRefresh(sessionId);
51
+ return;
52
+ }
53
+ const status = entry.currentRuntimeStatus;
54
+ // 仅活跃状态需要刷新:thinking / tool_using / compacting
55
+ if (status !== "thinking" && status !== "tool_using" && status !== "compacting") {
56
+ stopStatusRefresh(sessionId);
57
+ return;
58
+ }
59
+ // 发送轻量级状态刷新(不带 actionInfo),保持 WebSocket 会话活跃
60
+ void sendStatus(entry.agentId, sessionId, status, undefined, // 不传 actionInfo,避免创建额外时间线条目
61
+ undefined, {
62
+ runtimeAccessToken: entry.runtimeAccessToken,
63
+ schedulerBaseUrl: entry.schedulerBaseUrl,
64
+ }).catch(() => {
65
+ // sendStatus 失败静默处理,不影响主流程
66
+ });
67
+ }, STATUS_REFRESH_INTERVAL_MS);
68
+ statusRefreshTimers.set(sessionId, timer);
69
+ }
70
+ /**
71
+ * 停止 session 定期状态刷新。
72
+ */
73
+ function stopStatusRefresh(sessionId) {
74
+ const timer = statusRefreshTimers.get(sessionId);
75
+ if (timer) {
76
+ clearInterval(timer);
77
+ statusRefreshTimers.delete(sessionId);
78
+ }
79
+ }
30
80
  const TOOL_RESULT_PREVIEW_MAX_LENGTH = 4000;
31
81
  const AI_REQUEST_BODY_MARKER = "\n\n请求体:\n";
32
82
  /**
@@ -58,10 +108,10 @@ const AI_REQUEST_HEADERS_MARKER = "\n\n请求头:\n";
58
108
  const startingAgents = new Set();
59
109
  // ============ 启动记忆加载 ============
60
110
  /**
61
- * 从工作区的 .agentswork/memory/ 目录加载 task_listrecently_memory
111
+ * 从工作区的 .agentswork/memory/ 目录加载 recently_memoryagent_memory
62
112
  * 格式化为可注入 System 3 的文本。
63
113
  *
64
- * 主流程:遍历目录下所有 domain JSON 文件 -> 提取 task_list/recently_memory 记录 ->
114
+ * 主流程:遍历目录下所有 domain JSON 文件 -> 提取 recently_memory/agent_memory 记录 ->
65
115
  * 按类型分组排序 -> 返回格式化文本;目录不存在或解析失败时返回 undefined。
66
116
  */
67
117
  async function loadAgentStartupMemories(workspacePath, options) {
@@ -93,10 +143,10 @@ async function loadAgentStartupMemories(workspacePath, options) {
93
143
  const content = (record.content || "").trim();
94
144
  if (!content)
95
145
  continue;
96
- if (type === "task_list") {
146
+ if (type === "recently_memory") {
97
147
  taskList.push({ title: record.title, content, uri: record.uri || "" });
98
148
  }
99
- else if (type === "recently_memory") {
149
+ else if (type === "agent_memory") {
100
150
  recentMemories.push({ title: record.title, content, uri: record.uri || "" });
101
151
  }
102
152
  }
@@ -115,8 +165,8 @@ async function loadAgentStartupMemories(workspacePath, options) {
115
165
  "X-Runtime-Token": options.runtimeAccessToken,
116
166
  Authorization: `Bearer ${options.runtimeAccessToken}`,
117
167
  };
118
- // 并行请求 task_listrecently_memory
119
- const typesToFetch = ["task_list", "recently_memory"];
168
+ // 并行请求 recently_memoryagent_memory
169
+ const typesToFetch = ["recently_memory", "agent_memory"];
120
170
  const results = await Promise.allSettled(typesToFetch.map((memoryType) => fetch(mcpUrl, {
121
171
  method: "POST",
122
172
  headers,
@@ -136,7 +186,7 @@ async function loadAgentStartupMemories(workspacePath, options) {
136
186
  const records = settled.value;
137
187
  if (!Array.isArray(records))
138
188
  continue;
139
- const target = typesToFetch[i] === "task_list" ? taskList : recentMemories;
189
+ const target = typesToFetch[i] === "recently_memory" ? taskList : recentMemories;
140
190
  for (const r of records) {
141
191
  const content = (r.content || "").trim();
142
192
  if (!content)
@@ -156,12 +206,12 @@ async function loadAgentStartupMemories(workspacePath, options) {
156
206
  if (taskList.length > 0) {
157
207
  const items = taskList.slice(0, MAX_PER_TYPE);
158
208
  const lines = items.map((t, i) => {
159
- const titleLine = t.title ? `【${t.title}】` : `待办 ${i + 1}`;
209
+ const titleLine = t.title ? `【${t.title}】` : `条目 ${i + 1}`;
160
210
  return `${titleLine}\n${t.content}`;
161
211
  });
162
- sections.push(`【短期任务清单】\n${lines.join("\n\n")}`);
212
+ sections.push(`【短期记忆】\n${lines.join("\n\n")}`);
163
213
  if (taskList.length > MAX_PER_TYPE) {
164
- sections.push(`... 及另外 ${taskList.length - MAX_PER_TYPE} 条任务`);
214
+ sections.push(`... 及另外 ${taskList.length - MAX_PER_TYPE} 条短期记忆`);
165
215
  }
166
216
  }
167
217
  if (recentMemories.length > 0) {
@@ -170,9 +220,9 @@ async function loadAgentStartupMemories(workspacePath, options) {
170
220
  const titleLine = t.title ? `【${t.title}】` : "";
171
221
  return titleLine ? `${titleLine}\n${t.content}` : t.content;
172
222
  });
173
- sections.push(`【近期记忆】\n${lines.join("\n\n")}`);
223
+ sections.push(`【agent认知】\n${lines.join("\n\n")}`);
174
224
  if (recentMemories.length > MAX_PER_TYPE) {
175
- sections.push(`... 及另外 ${recentMemories.length - MAX_PER_TYPE} 条近期记忆`);
225
+ sections.push(`... 及另外 ${recentMemories.length - MAX_PER_TYPE} 条 agent 认知`);
176
226
  }
177
227
  }
178
228
  if (sections.length === 0)
@@ -226,21 +276,34 @@ export function parseRuntimeStopOptions(body) {
226
276
  }
227
277
  export function resolveStatusChangeUsage(actionInfo) {
228
278
  const usage = actionInfo?.usage;
229
- if (!usage)
279
+ if (!usage) {
230
280
  return undefined;
281
+ }
231
282
  const inputTokens = Number.isFinite(usage.inputTokens)
232
283
  ? usage.inputTokens
233
284
  : 0;
234
285
  const outputTokens = Number.isFinite(usage.outputTokens)
235
286
  ? usage.outputTokens
236
287
  : 0;
237
- if (inputTokens <= 0 && outputTokens <= 0 && !usage.contextLimit)
288
+ // 即使 input/output token 都为 0(如 session_started 初始状态),只要有任一压缩配置字段也应传出,
289
+ // 否则前端拿不到 compactionThreshold,压缩点竖线无法显示。
290
+ if (inputTokens <= 0 &&
291
+ outputTokens <= 0 &&
292
+ !usage.contextLimit &&
293
+ !usage.maxOutput &&
294
+ !usage.inputLimit &&
295
+ !usage.compactionThreshold) {
238
296
  return undefined;
239
- return {
297
+ }
298
+ const result = {
240
299
  inputTokens,
241
300
  outputTokens,
242
301
  ...(usage.contextLimit ? { contextLimit: usage.contextLimit } : {}),
302
+ ...(usage.maxOutput ? { maxOutput: usage.maxOutput } : {}),
303
+ ...(usage.inputLimit ? { inputLimit: usage.inputLimit } : {}),
304
+ ...(usage.compactionThreshold ? { compactionThreshold: usage.compactionThreshold } : {}),
243
305
  };
306
+ return result;
244
307
  }
245
308
  export function resolveStatusChangeRuntimeState(status, actionInfo) {
246
309
  const normalizedStatus = String(status || "")
@@ -937,10 +1000,15 @@ function formatSdkLogMessage(event) {
937
1000
  }
938
1001
  return undefined;
939
1002
  }
1003
+ // 匹配 CSI 类 ANSI 转义序列(颜色/光标/清屏等),用于 DevTools 日志预览剥离
1004
+ const ANSI_ESCAPE_PATTERN = /\x1b\[[0-9;?]*[a-zA-Z]/g;
1005
+ function stripAnsiEscapeCodes(text) {
1006
+ return text.replace(ANSI_ESCAPE_PATTERN, "");
1007
+ }
940
1008
  function formatCommandOutputLogMessage(event) {
941
1009
  const stream = typeof event.data.stream === "string" ? event.data.stream : "mixed";
942
1010
  const sequence = typeof event.data.sequence === "number" ? ` #${event.data.sequence}` : "";
943
- const normalized = String(event.data.text || "")
1011
+ const normalized = stripAnsiEscapeCodes(String(event.data.text || ""))
944
1012
  .replace(/\s+/g, " ")
945
1013
  .trim();
946
1014
  const preview = normalized.length > 240 ? `${normalized.slice(0, 240)}...` : normalized;
@@ -1083,17 +1151,45 @@ function isWaitingInputProgressEvent(event, currentRuntimeStatus) {
1083
1151
  }
1084
1152
  return event.type === "thinking" || event.type === "text_delta";
1085
1153
  }
1154
+ /**
1155
+ * 从事件 data 中提取 estimatedContextTokens(兼容多种字段名)。
1156
+ * 返回 undefined 表示无有效值,使调用方能区分"无数据"和"0"。
1157
+ */
1158
+ function extractEstimatedContextTokens(data) {
1159
+ for (const key of [
1160
+ "estimatedContextTokens",
1161
+ "contextTokens",
1162
+ "context_tokens",
1163
+ "contextUsedTokens",
1164
+ "context_used_tokens",
1165
+ ]) {
1166
+ const value = data[key];
1167
+ const count = Number(value);
1168
+ if (Number.isFinite(count) && count > 0) {
1169
+ return count;
1170
+ }
1171
+ }
1172
+ return undefined;
1173
+ }
1086
1174
  export function resolveRuntimeStatusFromProviderEvent(event, currentRuntimeStatus) {
1087
1175
  if (isWaitingInputProgressEvent(event, currentRuntimeStatus)) {
1088
1176
  return undefined;
1089
1177
  }
1090
1178
  if (event.type === "ai_request") {
1179
+ // ★ 从 event.data 提取 estimatedContextTokens 构建 usage,
1180
+ // 确保 event handler 路径也能传递 token 用量到前端。
1181
+ // 这对压缩后面板刷新尤为关键:压缩后 ai_request 的 estimatedContextTokens
1182
+ // 反映了压缩后的真实上下文大小,前端据此更新进度条。
1183
+ const estimatedTokens = extractEstimatedContextTokens(event.data);
1091
1184
  return {
1092
1185
  status: "thinking",
1093
1186
  actionInfo: {
1094
1187
  actionType: "ai_request",
1095
1188
  actionLabel: "AI请求",
1096
1189
  actionDetail: formatAiRequestDetail(event.data),
1190
+ ...(estimatedTokens !== undefined
1191
+ ? { usage: { inputTokens: estimatedTokens, outputTokens: 0 } }
1192
+ : {}),
1097
1193
  },
1098
1194
  };
1099
1195
  }
@@ -1145,11 +1241,39 @@ export function resolveRuntimeStatusFromProviderEvent(event, currentRuntimeStatu
1145
1241
  if (event.type === "error") {
1146
1242
  return { status: "error" };
1147
1243
  }
1244
+ if (event.type === "context_compaction") {
1245
+ return {
1246
+ status: "compacting",
1247
+ actionInfo: {
1248
+ actionType: "context_compaction",
1249
+ actionLabel: event.data.actionLabel,
1250
+ actionDetail: event.data.actionDetail,
1251
+ ...(event.data.actionId ? { actionId: event.data.actionId } : {}),
1252
+ ...(event.data.parentId ? { parentId: event.data.parentId } : {}),
1253
+ },
1254
+ };
1255
+ }
1256
+ if (event.type === "runtime_capabilities") {
1257
+ // 运行时能力清单(MCP 工具 / Skill 列表)—— 保持当前运行态不变,仅推送 actionInfo 到时间线供调试面板展示
1258
+ return {
1259
+ status: currentRuntimeStatus || "waiting_input",
1260
+ actionInfo: {
1261
+ actionType: "runtime_capabilities",
1262
+ actionLabel: event.data.actionLabel || "运行时能力",
1263
+ actionDetail: event.data.actionDetail,
1264
+ },
1265
+ };
1266
+ }
1148
1267
  return undefined;
1149
1268
  }
1150
1269
  // Per-session 输出队列:确保 sendOutput HTTP POST 按事件顺序串行到达 Server,
1151
1270
  // 避免并发 POST 因网络时序导致流式文本 chunk 乱序。
1152
1271
  const sdkOutputQueueBySession = new Map();
1272
+ // Per-session 压缩状态事件队列:确保 context_compaction 事件(start/detect/prune/.../end)
1273
+ // 按发射顺序串行发送 HTTP POST,避免并发请求导致部分事件丢失(DB 证据:所有压缩都只保留了 2-4 个事件)。
1274
+ // ★ 根因:runtime.ts 同步连续发射 start/detect 等事件,多个 void sendStatus 并发执行 HTTP POST,
1275
+ // 部分 HTTP 请求因竞争/超时/Java 后端 FOR UPDATE 锁等待而失败,事件永久丢失(本地 buffer 不重推)。
1276
+ const compactionStatusChainBySession = new Map();
1153
1277
  /** 小 chunk 积攒缓存:sessionId:sourceEventType → { buffer, seq, timer, sourceEventType, entry },不足 20 字符时积攒最多 500ms 再推送 */
1154
1278
  const sdkOutputSmallChunkAccumulators = new Map();
1155
1279
  /** 小 chunk 积攒阈值:字符数少于此值的 output 事件积攒发送 */
@@ -1272,11 +1396,29 @@ function wireSdkAdapterEvents(adapter, definition) {
1272
1396
  const entry = sdkSessions.get(event.sessionId);
1273
1397
  if (entry) {
1274
1398
  console.log(`[${definition.displayName} Adapter] Event: ${event.type} for session ${event.sessionId}`);
1275
- // Skip sendStatus for thinking/text_delta/tool_use_start events — the status-change
1399
+ // Skip sendStatus for thinking/text_delta/tool_use_start/context_compaction/ai_request events — the status-change
1276
1400
  // listener already emits the authoritative status with restored actionInfo,
1277
1401
  // avoiding duplicate timeline entries in agentEventStore.
1278
- const isDeferredStatusEvent = event.type === "thinking" || event.type === "text_delta" || event.type === "tool_use_start";
1402
+ // context_compaction 加入此列表:adapter 对每个压缩事件(start/phase/end)都会同时
1403
+ // 调用 emitProviderEvent(触发 event 监听器)和 emit("status-change")(触发 status-change 监听器),
1404
+ // 两条路径都会 sendStatus,导致 Bridge 收到重复事件。虽然前端 seenActionIds 会去重,
1405
+ // 但异步 sendStatus 到达顺序不确定,会造成同时间戳事件顺序错乱(如 prune_end 排在 prune_start 前)。
1406
+ // 只保留 status-change 路径(含完整 actionId/parentId),确保父子事件正确匹配与排序。
1407
+ // ★ ai_request 加入此列表(修复 BUG:Agent 永久卡在 "AI请求" 状态):
1408
+ // ai_request 同时触发 provider event 路径和 status-change 路径两条 sendStatus,
1409
+ // 而 tool_use_start(编辑文件等)仅通过 status-change 路径发送。
1410
+ // 异步 HTTP 乱序导致 ai_request 的 provider-event sendStatus 可能晚于 tool_use_start 到达,
1411
+ // 覆盖前端状态为 "AI请求",而时间线正确显示 "编辑文件"。
1412
+ // 将 ai_request 加入 deferred 列表,使其仅通过 status-change 路径发送,
1413
+ // 与 tool_use_start 保持一致,消除双路径竞态。
1414
+ const isDeferredStatusEvent = event.type === "thinking" || event.type === "text_delta" || event.type === "tool_use_start" || event.type === "context_compaction" || event.type === "ai_request";
1279
1415
  if (!isDeferredStatusEvent) {
1416
+ // ★ 修复时序竞争:runtime_capabilities 事件缓存 actionDetail,
1417
+ // 用于 session 稳定后重发(防止 "starting" 状态尚未更新 runtime_session_id
1418
+ // 导致服务端丢弃事件)
1419
+ if (event.type === "runtime_capabilities" && event.data.actionDetail) {
1420
+ entry.cachedCapabilitiesActionDetail = event.data.actionDetail;
1421
+ }
1280
1422
  const runtimeStatus = resolveRuntimeStatusFromProviderEvent(event, entry.currentRuntimeStatus);
1281
1423
  if (runtimeStatus) {
1282
1424
  void sendStatus(entry.agentId, event.sessionId, runtimeStatus.status, runtimeStatus.actionInfo, resolveStatusChangeUsage(runtimeStatus.actionInfo), {
@@ -1308,6 +1450,13 @@ function wireSdkAdapterEvents(adapter, definition) {
1308
1450
  adapter.on("status-change", (sessionId, status, actionInfo) => {
1309
1451
  const entry = sdkSessions.get(sessionId);
1310
1452
  if (entry) {
1453
+ // ★ 活跃状态定期刷新:防止长时间 LLM 调用期间服务端 WebSocket 空闲超时导致 LOST
1454
+ if (status === "thinking" || status === "tool_using" || status === "compacting") {
1455
+ startStatusRefresh(sessionId);
1456
+ }
1457
+ else {
1458
+ stopStatusRefresh(sessionId);
1459
+ }
1311
1460
  const runtimeState = resolveStatusChangeRuntimeState(status, actionInfo);
1312
1461
  entry.currentRuntimeStatus = runtimeState.status;
1313
1462
  // 当新状态未携带动作且进入 thinking 时,保留上一个 idle 类动作(如 poll_message),
@@ -1351,10 +1500,69 @@ function wireSdkAdapterEvents(adapter, definition) {
1351
1500
  actionInput: entry.currentRuntimeActionInput,
1352
1501
  }
1353
1502
  : undefined;
1354
- void sendStatus(entry.agentId, sessionId, runtimeState.status, restoredActionInfo, resolveStatusChangeUsage(runtimeState.actionInfo), {
1355
- runtimeAccessToken: entry.runtimeAccessToken,
1356
- schedulerBaseUrl: entry.schedulerBaseUrl,
1357
- });
1503
+ // compacting 状态(context_compaction 事件)使用 per-session 序列化队列,
1504
+ // 避免 start/detect/prune/.../end 等事件并发 HTTP POST 导致部分事件丢失。
1505
+ // DB 证据:所有压缩都只保留了 2-4 个事件(应该有 7 个),根因是并发请求竞争。
1506
+ if (runtimeState.status === "compacting") {
1507
+ const prev = compactionStatusChainBySession.get(sessionId) ?? Promise.resolve();
1508
+ const next = prev.then(async () => {
1509
+ // ★ 重试机制:HTTP 失败(sendStatus 返回 undefined)时重试,
1510
+ // 避免因网络超时/瞬时故障导致压缩事件(特别是父 start 事件)永久丢失。
1511
+ // scheduleEventPush 是 no-op,HTTP 回调是唯一投递路径,无 fallback。
1512
+ const maxRetries = 2;
1513
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
1514
+ const response = await sendStatus(entry.agentId, sessionId, runtimeState.status, restoredActionInfo, resolveStatusChangeUsage(runtimeState.actionInfo), {
1515
+ runtimeAccessToken: entry.runtimeAccessToken,
1516
+ schedulerBaseUrl: entry.schedulerBaseUrl,
1517
+ });
1518
+ if (response !== undefined)
1519
+ return; // HTTP 成功
1520
+ if (attempt < maxRetries) {
1521
+ log.warn(`[${definition.displayName}] compaction sendStatus attempt ${attempt + 1} failed (HTTP), retrying in ${1000 * (attempt + 1)}ms...`);
1522
+ await new Promise((r) => setTimeout(r, 1000 * (attempt + 1)));
1523
+ }
1524
+ }
1525
+ log.warn(`[${definition.displayName}] compaction sendStatus failed after ${maxRetries + 1} attempts, event may be lost`);
1526
+ }).catch((err) => {
1527
+ // 链中某次失败不影响后续事件发送
1528
+ log.warn(`[${definition.displayName}] compaction status chain error:`, err);
1529
+ });
1530
+ compactionStatusChainBySession.set(sessionId, next);
1531
+ // 链结束后清理,避免内存泄漏
1532
+ next.finally(() => {
1533
+ if (compactionStatusChainBySession.get(sessionId) === next) {
1534
+ compactionStatusChainBySession.delete(sessionId);
1535
+ }
1536
+ });
1537
+ }
1538
+ else {
1539
+ // ★ 修复重复时间线条目:当 shouldPreservePrevAction 为 true 且新 actionInfo 为 undefined
1540
+ // (idle 类型 poll_message 的 tool_use_end status-change 传 undefined)时,
1541
+ // 不传 restoredActionInfo,避免 dashboard 创建第二个"调用MCP"时间线条目。
1542
+ // tool_use_start 的 status-change 已创建了一个条目,这里只需纯状态变更。
1543
+ const skipRestoredActionInfo = shouldPreservePrevAction && !runtimeState.actionInfo?.actionType;
1544
+ void sendStatus(entry.agentId, sessionId, runtimeState.status, skipRestoredActionInfo ? undefined : restoredActionInfo, resolveStatusChangeUsage(runtimeState.actionInfo), {
1545
+ runtimeAccessToken: entry.runtimeAccessToken,
1546
+ schedulerBaseUrl: entry.schedulerBaseUrl,
1547
+ });
1548
+ }
1549
+ // ★ 修复时序竞争:session 稳定到 waiting_input 时,若缓存了 runtime_capabilities
1550
+ // 但尚未被清除(说明第一次发送可能因 runtime_session_id 未及时更新而被服务端丢弃),
1551
+ // 在此重发确保前端最终能收到能力清单。
1552
+ if (runtimeState.status === "waiting_input" &&
1553
+ entry.cachedCapabilitiesActionDetail) {
1554
+ const cachedDetail = entry.cachedCapabilitiesActionDetail;
1555
+ entry.cachedCapabilitiesActionDetail = undefined;
1556
+ console.log(`[${definition.displayName} Adapter] Re-sending cached runtime_capabilities for agent ${entry.agentId} (session stabilized to waiting_input)`);
1557
+ void sendStatus(entry.agentId, sessionId, "waiting_input", {
1558
+ actionType: "runtime_capabilities",
1559
+ actionLabel: "运行时能力",
1560
+ actionDetail: cachedDetail,
1561
+ }, undefined, {
1562
+ runtimeAccessToken: entry.runtimeAccessToken,
1563
+ schedulerBaseUrl: entry.schedulerBaseUrl,
1564
+ });
1565
+ }
1358
1566
  }
1359
1567
  });
1360
1568
  adapter.on("ask-user-question", (data) => {
@@ -1364,7 +1572,7 @@ function wireSdkAdapterEvents(adapter, definition) {
1364
1572
  void sendQuestionRequest(entry.agentId, data.sessionId, Array.isArray(data.questions) ? data.questions : [], {
1365
1573
  runtimeAccessToken: entry.runtimeAccessToken,
1366
1574
  schedulerBaseUrl: entry.schedulerBaseUrl,
1367
- });
1575
+ }, data.toolCallId);
1368
1576
  }
1369
1577
  });
1370
1578
  adapter.on("permission-request", (data) => {
@@ -1431,7 +1639,9 @@ async function startSdkSession(req, res) {
1431
1639
  // Per-agent model override(优先于全局配置)
1432
1640
  model: perAgentModel,
1433
1641
  // Per-instance AI provider 覆盖(仅 ACode 消费;优先级:api > env > file > global)
1434
- instanceAiConfig: perInstanceAiConfig, } = req.body || {};
1642
+ instanceAiConfig: perInstanceAiConfig,
1643
+ // Sub Agent 模型/强度覆盖(仅 ACode 消费,空值=继承主 Agent)
1644
+ subAgentModel: perAgentSubAgentModel, subAgentEffort: perAgentSubAgentEffort, } = req.body || {};
1435
1645
  const _dbg = getInstanceAiConfigDebugLogger();
1436
1646
  void _dbg.log({
1437
1647
  level: "info",
@@ -1639,6 +1849,13 @@ async function startSdkSession(req, res) {
1639
1849
  ...(resolvedInstanceAiConfig
1640
1850
  ? { instanceAiConfig: resolvedInstanceAiConfig }
1641
1851
  : {}),
1852
+ // Sub Agent 模型/强度覆盖(仅 ACode 消费)
1853
+ ...(typeof perAgentSubAgentModel === "string" && perAgentSubAgentModel.trim()
1854
+ ? { subAgentModel: perAgentSubAgentModel.trim() }
1855
+ : {}),
1856
+ ...(typeof perAgentSubAgentEffort === "string" && perAgentSubAgentEffort.trim()
1857
+ ? { subAgentEffort: perAgentSubAgentEffort.trim() }
1858
+ : {}),
1642
1859
  extraMcpServers: extraMcpServers || {},
1643
1860
  envOverrides: buildRuntimeEnv(String(agentId), String(workspacePath), process.env, effectiveEnvOverrides),
1644
1861
  };
@@ -1693,6 +1910,7 @@ async function startSdkSession(req, res) {
1693
1910
  catch (error) {
1694
1911
  // 同步错误处理(校验失败等)
1695
1912
  if (sessionId) {
1913
+ stopStatusRefresh(sessionId);
1696
1914
  sdkSessions.delete(sessionId);
1697
1915
  }
1698
1916
  if (normalizedAgentId) {
@@ -1784,6 +2002,7 @@ async function startSdkSessionBg(params) {
1784
2002
  }
1785
2003
  catch (error) {
1786
2004
  // 后台启动失败:清理本地状态 + 通知 server
2005
+ stopStatusRefresh(sessionId);
1787
2006
  sdkSessions.delete(sessionId);
1788
2007
  await removePersistedSession(sessionId);
1789
2008
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -1985,6 +2204,7 @@ terminalRouter.post("/sdk/stop", validateToken, async (req, res) => {
1985
2204
  // 如果有活跃 AI 请求,先立即中止(fire-and-forget),再清理资源
1986
2205
  adapter.abortCurrentTurn(sessionId).catch(() => { });
1987
2206
  await adapter.terminateSession(sessionId);
2207
+ stopStatusRefresh(sessionId);
1988
2208
  sdkSessions.delete(sessionId);
1989
2209
  stopTerminalCommandProcess(sessionId);
1990
2210
  await removePersistedSession(sessionId);
@@ -2036,6 +2256,86 @@ terminalRouter.get("/sdk/status/:sessionId", validateToken, (req, res) => {
2036
2256
  res.status(500).json({ error: errorMessage });
2037
2257
  }
2038
2258
  });
2259
+ /**
2260
+ * GET /runtime/sdk/capabilities/:sessionId
2261
+ *
2262
+ * 主动查询会话的运行时能力清单(MCP 工具 + skills)。
2263
+ * 只读 adapter 内存缓存(lastCombinedCapabilities),不触发 runtime 重新探测。
2264
+ * 缓存由 mcp_status / skill_status 事件维护;若尚未收到任何事件则返回 capabilities: null。
2265
+ */
2266
+ terminalRouter.get("/sdk/capabilities/:sessionId", validateToken, (req, res) => {
2267
+ const sessionId = req.params.sessionId;
2268
+ if (!sessionId) {
2269
+ res.status(400).json({ error: "sessionId is required" });
2270
+ return;
2271
+ }
2272
+ const entry = sdkSessions.get(sessionId);
2273
+ if (!entry) {
2274
+ res.status(404).json({ error: "SDK session not found" });
2275
+ return;
2276
+ }
2277
+ try {
2278
+ const providerId = entry.providerId || "claude-code";
2279
+ const adapter = adapterRegistry.get(providerId);
2280
+ // 仅 AcodeSdkAdapter 实现 getCapabilities;其他 adapter 返回 undefined
2281
+ const capabilities = adapter.getCapabilities?.(sessionId) ?? null;
2282
+ res.json({
2283
+ ok: true,
2284
+ sessionId,
2285
+ agentId: entry.agentId,
2286
+ capabilities,
2287
+ fetchedAt: Date.now(),
2288
+ });
2289
+ }
2290
+ catch (error) {
2291
+ const errorMessage = error instanceof Error ? error.message : String(error);
2292
+ res.status(500).json({ error: errorMessage });
2293
+ }
2294
+ });
2295
+ /**
2296
+ * 查询会话当前挂起的 ask_user_question(agent 提问)。
2297
+ *
2298
+ * 只读 adapter 内存缓存(pendingQuestionToolCallId + pendingQuestions)。
2299
+ * 用于前端刷新后重建提问 UI:bridge 在 session entry 中保留了最近一次提问的
2300
+ * toolCallId 与 questions 数组,前端刷新后通过此端点取回并重建 directMessages
2301
+ * 与 header 通知。toolCallId 封闭在 bridge 内部,前端无需感知。
2302
+ *
2303
+ * GET /runtime/sdk/pending-questions/:sessionId
2304
+ */
2305
+ terminalRouter.get("/sdk/pending-questions/:sessionId", validateToken, (req, res) => {
2306
+ const sessionId = req.params.sessionId;
2307
+ if (!sessionId) {
2308
+ res.status(400).json({ error: "sessionId is required" });
2309
+ return;
2310
+ }
2311
+ const entry = sdkSessions.get(sessionId);
2312
+ if (!entry) {
2313
+ res.status(404).json({ error: "SDK session not found" });
2314
+ return;
2315
+ }
2316
+ try {
2317
+ const providerId = entry.providerId || "claude-code";
2318
+ const adapter = adapterRegistry.get(providerId);
2319
+ // 仅 AcodeSdkAdapter 实现 getPendingQuestion;其他 adapter 返回 undefined
2320
+ const pendingQuestion = adapter.getPendingQuestion?.(sessionId) ?? null;
2321
+ res.json({
2322
+ ok: true,
2323
+ sessionId,
2324
+ agentId: entry.agentId,
2325
+ pendingQuestion: pendingQuestion
2326
+ ? {
2327
+ toolCallId: pendingQuestion.toolCallId,
2328
+ questions: pendingQuestion.questions,
2329
+ }
2330
+ : null,
2331
+ fetchedAt: Date.now(),
2332
+ });
2333
+ }
2334
+ catch (error) {
2335
+ const errorMessage = error instanceof Error ? error.message : String(error);
2336
+ res.status(500).json({ error: errorMessage });
2337
+ }
2338
+ });
2039
2339
  /**
2040
2340
  * 执行当前 Agent 工作目录下的终端命令。
2041
2341
  *
@@ -2240,6 +2540,7 @@ terminalRouter.post("/stop", validateToken, async (req, res) => {
2240
2540
  // 如果有活跃 AI 请求,先立即中止(fire-and-forget),再清理资源
2241
2541
  adapter.abortCurrentTurn(sessionId).catch(() => { });
2242
2542
  await adapter.terminateSession(sessionId);
2543
+ stopStatusRefresh(sessionId);
2243
2544
  sdkSessions.delete(sessionId);
2244
2545
  stopTerminalCommandProcess(sessionId);
2245
2546
  await removePersistedSession(sessionId);
@@ -2290,6 +2591,7 @@ terminalRouter.post("/stop-all", validateToken, async (_req, res) => {
2290
2591
  // 如果有活跃 AI 请求,先立即中止(fire-and-forget),再清理资源
2291
2592
  adapter.abortCurrentTurn(sessionId).catch(() => { });
2292
2593
  await adapter.terminateSession(sessionId);
2594
+ stopStatusRefresh(sessionId);
2293
2595
  sdkSessions.delete(sessionId);
2294
2596
  stopTerminalCommandProcess(sessionId);
2295
2597
  stoppedSdk.push(sessionId);
@@ -1,7 +1,14 @@
1
+ /**
2
+ * 获取 ACode 入口文件路径。
3
+ * 本地开发模式:直接使用项目下 package/acode/dist/index.js(修改即生效,无需复制)。
4
+ * 部署模式:~/.aws-bridge/acode/dist/index.js。
5
+ */
1
6
  export declare function getReleasedAcodeEntryPath(): string;
2
7
  /**
3
8
  * 释放随 bridge 打包的内置 ACode runtime。
4
- * 主流程:检查 bundled dist -> 复制 dist 与 metadata -> 链接 bridge node_modules,
9
+ *
10
+ * 本地开发模式:直接使用项目下 package/acode/dist,跳过复制(修改源码后重新 build 即生效)。
11
+ * 部署模式:复制 dist 与 metadata 到 ~/.aws-bridge/acode,链接 bridge node_modules,
5
12
  * 确保 ACode 无需安装即可被 Adapter 动态加载。
6
13
  */
7
14
  export declare function ensureAcodePackageReleased(): string | null;
@@ -1 +1 @@
1
- {"version":3,"file":"acode-package.d.ts","sourceRoot":"","sources":["../../src/services/acode-package.ts"],"names":[],"mappings":"AAyDA,wBAAgB,yBAAyB,IAAI,MAAM,CAElD;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,IAAI,MAAM,GAAG,IAAI,CAwB1D"}
1
+ {"version":3,"file":"acode-package.d.ts","sourceRoot":"","sources":["../../src/services/acode-package.ts"],"names":[],"mappings":"AAqEA;;;;GAIG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,CAMlD;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,IAAI,MAAM,GAAG,IAAI,CAgC1D"}
@@ -10,8 +10,19 @@ function getBridgePackageRoot() {
10
10
  function getBundledAcodeRoot(packageRoot = getBridgePackageRoot()) {
11
11
  return path.join(packageRoot, 'package', 'acode');
12
12
  }
13
+ /**
14
+ * 判断当前是否为本地开发模式(从项目源码目录运行)。
15
+ * 本地开发模式下 bridge packageRoot 下存在 src/ 目录,部署产物只有 dist/。
16
+ */
17
+ function isLocalDevMode(packageRoot = getBridgePackageRoot()) {
18
+ return existsSync(path.join(packageRoot, 'src'));
19
+ }
20
+ /**
21
+ * 部署模式下的 released 根目录:~/.aws-bridge/acode
22
+ * 与 aws-client-agent-mcp 的 ~/.aws-bridge/mcp 路径保持一致。
23
+ */
13
24
  function getReleasedAcodeRoot() {
14
- return path.join(getRuntimeHomeDir(), '.agentswork', 'runtime-bridge', 'packages', 'acode');
25
+ return path.join(getRuntimeHomeDir(), '.aws-bridge', 'acode');
15
26
  }
16
27
  function shouldReplaceNodeModulesLink(targetPath) {
17
28
  if (!existsSync(targetPath)) {
@@ -48,12 +59,23 @@ function ensureReleasedNodeModules(packageRoot, releasedRoot) {
48
59
  rmSync(releasedNodeModules, { recursive: true, force: true });
49
60
  symlinkSync(sourceNodeModules, releasedNodeModules, process.platform === 'win32' ? 'junction' : 'dir');
50
61
  }
62
+ /**
63
+ * 获取 ACode 入口文件路径。
64
+ * 本地开发模式:直接使用项目下 package/acode/dist/index.js(修改即生效,无需复制)。
65
+ * 部署模式:~/.aws-bridge/acode/dist/index.js。
66
+ */
51
67
  export function getReleasedAcodeEntryPath() {
68
+ const packageRoot = getBridgePackageRoot();
69
+ if (isLocalDevMode(packageRoot)) {
70
+ return path.join(getBundledAcodeRoot(packageRoot), 'dist', 'index.js');
71
+ }
52
72
  return path.join(getReleasedAcodeRoot(), 'dist', 'index.js');
53
73
  }
54
74
  /**
55
75
  * 释放随 bridge 打包的内置 ACode runtime。
56
- * 主流程:检查 bundled dist -> 复制 dist 与 metadata -> 链接 bridge node_modules,
76
+ *
77
+ * 本地开发模式:直接使用项目下 package/acode/dist,跳过复制(修改源码后重新 build 即生效)。
78
+ * 部署模式:复制 dist 与 metadata 到 ~/.aws-bridge/acode,链接 bridge node_modules,
57
79
  * 确保 ACode 无需安装即可被 Adapter 动态加载。
58
80
  */
59
81
  export function ensureAcodePackageReleased() {
@@ -65,6 +87,12 @@ export function ensureAcodePackageReleased() {
65
87
  logger.warn(`[runtime-bridge] 未找到 bundled ACode dist,ACode 启动可能失败: ${bundledEntry}`);
66
88
  return null;
67
89
  }
90
+ // 本地开发模式:直接使用项目下 dist,无需复制
91
+ if (isLocalDevMode(packageRoot)) {
92
+ logger.info(`[runtime-bridge] ACode 本地开发模式,直接使用项目 dist: ${bundledEntry}`);
93
+ return bundledEntry;
94
+ }
95
+ // 部署模式:复制到 ~/.aws-bridge/acode
68
96
  const releasedRoot = getReleasedAcodeRoot();
69
97
  const releasedDist = path.join(releasedRoot, 'dist');
70
98
  mkdirSync(releasedRoot, { recursive: true });
@@ -77,6 +105,7 @@ export function ensureAcodePackageReleased() {
77
105
  }
78
106
  }
79
107
  ensureReleasedNodeModules(packageRoot, releasedRoot);
80
- logger.info(`[runtime-bridge] ACode 已准备: ${getReleasedAcodeEntryPath()}`);
81
- return getReleasedAcodeEntryPath();
108
+ const releasedEntry = path.join(releasedDist, 'index.js');
109
+ logger.info(`[runtime-bridge] ACode 已准备: ${releasedEntry}`);
110
+ return releasedEntry;
82
111
  }
@@ -19,6 +19,7 @@ export interface BridgeEventPayload {
19
19
  readonly actionInput?: string;
20
20
  readonly actionResult?: string;
21
21
  readonly actionId?: string;
22
+ readonly parentId?: string;
22
23
  readonly inputTokens?: number;
23
24
  readonly outputTokens?: number;
24
25
  readonly sourceEventType?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"agent-event-store.d.ts","sourceRoot":"","sources":["../../src/services/agent-event-store.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEpE,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,QAAQ,GAAG,UAAU,GAAG,cAAc,CAAC;IACrE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC;IAC/B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAQD;;;;GAIG;AACH,cAAM,eAAe;IACnB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuC;IAE9D,OAAO,CAAC,YAAY;IASpB;;;OAGG;IACH,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,GAAG,eAAe,CAAC,kBAAkB,CAAC;IAIzF;;;;;OAKG;IACH,mBAAmB,CACjB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,kBAAkB,GAC1B,eAAe,CAAC,kBAAkB,CAAC;IA6BtC;;OAEG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;CAG9B;AAED,WAAW;AACX,eAAO,MAAM,eAAe,iBAAwB,CAAC"}
1
+ {"version":3,"file":"agent-event-store.d.ts","sourceRoot":"","sources":["../../src/services/agent-event-store.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEpE,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,QAAQ,GAAG,UAAU,GAAG,cAAc,CAAC;IACrE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC;IAC/B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAQD;;;;GAIG;AACH,cAAM,eAAe;IACnB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuC;IAE9D,OAAO,CAAC,YAAY;IASpB;;;OAGG;IACH,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,GAAG,eAAe,CAAC,kBAAkB,CAAC;IAIzF;;;;;OAKG;IACH,mBAAmB,CACjB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,kBAAkB,GAC1B,eAAe,CAAC,kBAAkB,CAAC;IA6BtC;;OAEG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;CAG9B;AAED,WAAW;AACX,eAAO,MAAM,eAAe,iBAAwB,CAAC"}