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
@@ -1,746 +0,0 @@
1
- import { mkdtemp, mkdir, writeFile } from "node:fs/promises";
2
- import os from "node:os";
3
- import path from "node:path";
4
- import { describe, expect, it } from "vitest";
5
- import { SDK_PROVIDER_DEFINITIONS } from "../adapter/SdkProviderSpi.js";
6
- import { buildAcodeCommandOutputPath, buildClaudeCodeLaunchConfig, buildRuntimeEnv, buildSdkOutputMetadata, buildToolResultTimelineActionInfo, countTerminalOutputLines, createTerminalOutputDecoder, decodeTerminalOutputChunk, evaluatePersistedSessionReuse, formatCommandInactivityTimeoutNotice, formatCommandOutputSpilloverNotice, formatTerminalPrompt, formatSdkOutputEvent, normalizeTerminalCommandInput, parseTerminalDirectoryChangeTarget, resolveSdkInputMessage, resolveTerminalOutputEncoding, resolveSdkProviderId, resolveSdkSessionDisplayStatus, resolveRuntimeStatusFromProviderEvent, resolveStatusChangeRuntimeState, resolveStatusChangeUsage, shouldProbeSdkProcessPid, } from "./terminal.js";
7
- describe("terminal route validation", () => {
8
- it("requires agentId and workspacePath for start", () => {
9
- const validateStartRequest = (body) => {
10
- if (!body.agentId || !body.workspacePath)
11
- return {
12
- valid: false,
13
- error: "agentId and workspacePath are required",
14
- };
15
- return { valid: true };
16
- };
17
- expect(validateStartRequest({}).valid).toBe(false);
18
- expect(validateStartRequest({ agentId: "agent-1", workspacePath: "/path" })
19
- .valid).toBe(true);
20
- });
21
- it("uses SDK default command when not provided", () => {
22
- const resolveCommand = (command) => command || "acode";
23
- expect(resolveCommand(undefined)).toBe("acode");
24
- expect(resolveCommand("codex")).toBe("codex");
25
- });
26
- it("uses SDK launch mode for unsupported mode values", () => {
27
- const resolveLaunchMode = (mode) => mode === "sdk" ? "sdk" : "sdk";
28
- expect(resolveLaunchMode(undefined)).toBe("sdk");
29
- expect(resolveLaunchMode("sdk")).toBe("sdk");
30
- expect(resolveLaunchMode("unsupported")).toBe("sdk");
31
- });
32
- it("keeps shortcut mode available for manual key injection", () => {
33
- const buildInputResponse = (mode) => mode === "shortcut"
34
- ? { ok: true, mode: "shortcut" }
35
- : { ok: true, mode: "sdk" };
36
- expect(buildInputResponse("shortcut")).toEqual({
37
- ok: true,
38
- mode: "shortcut",
39
- });
40
- expect(buildInputResponse(undefined)).toEqual({ ok: true, mode: "sdk" });
41
- });
42
- it("does not downgrade unsupported shortcut input to normal SDK messages", () => {
43
- const buildShortcutFallbackResponse = (hasShortcutSupport) => hasShortcutSupport
44
- ? { status: 200, body: { ok: true, mode: "shortcut" } }
45
- : {
46
- status: 400,
47
- body: {
48
- error: "shortcut input is not supported by this SDK provider",
49
- },
50
- };
51
- expect(buildShortcutFallbackResponse(false)).toEqual({
52
- status: 400,
53
- body: { error: "shortcut input is not supported by this SDK provider" },
54
- });
55
- });
56
- it("requires sessionId and input for SDK terminal input", () => {
57
- const validateInputRequest = (body) => {
58
- if (!body.sessionId || body.input === undefined || body.input === null) {
59
- return { valid: false, error: "sessionId and input are required" };
60
- }
61
- return { valid: true };
62
- };
63
- expect(validateInputRequest({}).valid).toBe(false);
64
- expect(validateInputRequest({ sessionId: "session-1", input: "continue" }).valid).toBe(true);
65
- });
66
- it("keeps resize contract as SDK no-op compatibility endpoint", () => {
67
- const buildResizeResponse = (cols, rows) => ({
68
- ok: true,
69
- mode: "sdk",
70
- noop: true,
71
- cols,
72
- rows,
73
- });
74
- expect(buildResizeResponse(120, 30)).toEqual({
75
- ok: true,
76
- mode: "sdk",
77
- noop: true,
78
- cols: 120,
79
- rows: 30,
80
- });
81
- });
82
- it("requires sessionId for stop", () => {
83
- const validateStopRequest = (body) => {
84
- if (!body.sessionId)
85
- return { valid: false, error: "sessionId is required" };
86
- return { valid: true };
87
- };
88
- expect(validateStopRequest({}).valid).toBe(false);
89
- expect(validateStopRequest({ sessionId: "session-1" }).valid).toBe(true);
90
- });
91
- });
92
- describe("SDK startup idle command ordering", () => {
93
- it("skips PID probing for in-process ACode sessions", () => {
94
- expect(shouldProbeSdkProcessPid("acode")).toBe(false);
95
- expect(shouldProbeSdkProcessPid("claude-code")).toBe(true);
96
- });
97
- it("sets idle commands immediately after adapter startup and before PID probing or persistence", async () => {
98
- const calls = [];
99
- const adapter = {
100
- async startSession() {
101
- calls.push("startSession");
102
- },
103
- setIdleCommands() {
104
- calls.push("setIdleCommands");
105
- },
106
- };
107
- const startFlow = async () => {
108
- await adapter.startSession();
109
- adapter.setIdleCommands();
110
- calls.push("probePid");
111
- calls.push("persistSession");
112
- };
113
- await startFlow();
114
- expect(calls).toEqual([
115
- "startSession",
116
- "setIdleCommands",
117
- "probePid",
118
- "persistSession",
119
- ]);
120
- });
121
- });
122
- describe("terminal configuration", () => {
123
- it("builds correct SDK runtime environment", () => {
124
- const env = buildRuntimeEnv("agent-123", undefined, { PATH: "/usr/bin" });
125
- expect(env.AWS_AGENT_ID).toBe("agent-123");
126
- expect(env.AWS_MCP_LAUNCH_BINDING_ID).toBeUndefined();
127
- expect(env.AWS_MCP_CLAIM_LAUNCH_BINDING).toBe("true");
128
- });
129
- it("merges launch env overrides without allowing agent identity override", () => {
130
- const env = buildRuntimeEnv("agent-123", "/workspace", { PATH: "/usr/bin" }, {
131
- ANTHROPIC_BASE_URL: " https://api.example.com ",
132
- ANTHROPIC_AUTH_TOKEN: "secret-token",
133
- ANTHROPIC_MODEL: "claude-sonnet-4-5",
134
- AWS_AGENT_ID: "malicious-agent",
135
- EMPTY_VALUE: " ",
136
- });
137
- expect(env.ANTHROPIC_BASE_URL).toBe("https://api.example.com");
138
- expect(env.ANTHROPIC_AUTH_TOKEN).toBe("secret-token");
139
- expect(env.ANTHROPIC_MODEL).toBe("claude-sonnet-4-5");
140
- expect(env.EMPTY_VALUE).toBeUndefined();
141
- expect(env.AWS_AGENT_ID).toBe("agent-123");
142
- expect(env.AWS_WORKSPACE_PATH).toBe("/workspace");
143
- });
144
- it("merges saved ClaudeCode AI settings into SDK launch env with request overrides taking precedence", () => {
145
- const launchConfig = buildClaudeCodeLaunchConfig({
146
- env: {
147
- ANTHROPIC_BASE_URL: "https://saved.example.com",
148
- ANTHROPIC_AUTH_TOKEN: "sk-saved",
149
- ANTHROPIC_MODEL: "claude-saved",
150
- EMPTY_SAVED: " ",
151
- },
152
- }, {
153
- ANTHROPIC_MODEL: " claude-request ",
154
- EXTRA_VALUE: "enabled",
155
- });
156
- expect(launchConfig).toEqual({
157
- envOverrides: {
158
- ANTHROPIC_BASE_URL: "https://saved.example.com",
159
- ANTHROPIC_AUTH_TOKEN: "sk-saved",
160
- ANTHROPIC_MODEL: "claude-request",
161
- EXTRA_VALUE: "enabled",
162
- },
163
- model: "claude-request",
164
- });
165
- });
166
- it("uses CODEX_MODEL from request env overrides as SDK launch model", () => {
167
- const launchConfig = buildClaudeCodeLaunchConfig(null, {
168
- OPENAI_API_KEY: "sk-codex",
169
- CODEX_MODEL: " gpt-5.3-codex ",
170
- });
171
- expect(launchConfig).toEqual({
172
- envOverrides: {
173
- OPENAI_API_KEY: "sk-codex",
174
- CODEX_MODEL: "gpt-5.3-codex",
175
- },
176
- model: "gpt-5.3-codex",
177
- });
178
- });
179
- });
180
- describe("persisted SDK session reuse", () => {
181
- it("does not reuse a persisted session without a PID", () => {
182
- const decision = evaluatePersistedSessionReuse({}, () => true);
183
- expect(decision).toEqual({ reusable: false, reason: "missing-pid" });
184
- });
185
- it("does not reuse a persisted session when its PID is no longer running", () => {
186
- const decision = evaluatePersistedSessionReuse({ pid: 1234 }, () => false);
187
- expect(decision).toEqual({ reusable: false, reason: "dead-pid" });
188
- });
189
- it("reuses a persisted session only when its PID is still running for externally controllable providers", () => {
190
- const decision = evaluatePersistedSessionReuse({ pid: 1234, command: "claude" }, () => true);
191
- expect(decision).toEqual({ reusable: true, reason: "active-pid" });
192
- });
193
- it("does not reuse ACode persisted sessions because their control channel is in-process only", () => {
194
- const decision = evaluatePersistedSessionReuse({ pid: 1234, command: "acode" }, () => true);
195
- expect(decision).toEqual({
196
- reusable: false,
197
- reason: "in-process-provider",
198
- });
199
- });
200
- });
201
- describe("SDK session display status", () => {
202
- it("prefers adapter fine-grained status over coarse running fallback", () => {
203
- expect(resolveSdkSessionDisplayStatus("waiting_input", "running")).toBe("waiting_input");
204
- expect(resolveSdkSessionDisplayStatus("thinking", "running")).toBe("thinking");
205
- });
206
- it("uses in-memory runtime status when adapter status is temporarily unavailable", () => {
207
- expect(resolveSdkSessionDisplayStatus(undefined, "tool_using")).toBe("tool_using");
208
- });
209
- it("falls back to running only when no fine-grained state exists", () => {
210
- expect(resolveSdkSessionDisplayStatus(undefined, undefined)).toBe("running");
211
- });
212
- });
213
- describe("SDK provider event runtime status mapping", () => {
214
- const event = (type, data = {}) => ({
215
- type,
216
- sessionId: "session-1",
217
- timestamp: new Date().toISOString(),
218
- data,
219
- });
220
- it("maps text and thinking stream events to thinking status", () => {
221
- expect(resolveRuntimeStatusFromProviderEvent(event("thinking"))?.status).toBe("thinking");
222
- expect(resolveRuntimeStatusFromProviderEvent(event("text_delta"))?.status).toBe("thinking");
223
- });
224
- it("keeps command output chunks from changing the runtime status", () => {
225
- expect(resolveRuntimeStatusFromProviderEvent(event("command_output", { text: "stdout chunk", stream: "stdout" }))).toBeUndefined();
226
- });
227
- it("maps AI request events to thinking status with request details", () => {
228
- const state = resolveRuntimeStatusFromProviderEvent(event("ai_request", {
229
- model: "test-model",
230
- endpoint: "https://example.invalid/v1/chat/completions",
231
- requestMethod: "POST",
232
- requestUrl: "https://example.invalid/v1/chat/completions",
233
- requestHeaders: {
234
- "Content-Type": "application/json",
235
- Authorization: "Bearer ***",
236
- },
237
- stream: true,
238
- messageCount: 3,
239
- toolCount: 2,
240
- lastUserMessagePreview: "inspect status",
241
- requestBody: '{"model":"test-model"}',
242
- }));
243
- expect(state?.status).toBe("thinking");
244
- expect(state?.actionInfo).toMatchObject({
245
- actionType: "ai_request",
246
- actionLabel: "AI请求",
247
- });
248
- expect(state?.actionInfo?.actionDetail).toContain("模型: test-model");
249
- expect(state?.actionInfo?.actionDetail).toContain("接口: https://example.invalid/v1/chat/completions");
250
- expect(state?.actionInfo?.actionDetail).toContain("方法: POST");
251
- expect(state?.actionInfo?.actionDetail).toContain("请求头:\nContent-Type: application/json\nAuthorization: Bearer ***");
252
- expect(state?.actionInfo?.actionDetail).toContain("最后请求: inspect status");
253
- expect(state?.actionInfo?.actionDetail).toContain('请求体:\n{"model":"test-model"}');
254
- });
255
- it("does not let idle polling text chunks override waiting_input", () => {
256
- expect(resolveRuntimeStatusFromProviderEvent(event("thinking"), "waiting_input")).toBeUndefined();
257
- expect(resolveRuntimeStatusFromProviderEvent(event("text_delta"), "waiting_input")).toBeUndefined();
258
- });
259
- it("still reports AI request details when a request starts from waiting_input", () => {
260
- expect(resolveRuntimeStatusFromProviderEvent(event("ai_request", {
261
- model: "test-model",
262
- requestBody: '{"model":"test-model"}',
263
- }), "waiting_input")?.actionInfo).toMatchObject({
264
- actionType: "ai_request",
265
- actionLabel: "AI请求",
266
- actionDetail: expect.stringContaining('请求体:\n{"model":"test-model"}'),
267
- });
268
- });
269
- it("maps tool start events to tool_using with action info", () => {
270
- const state = resolveRuntimeStatusFromProviderEvent(event("tool_use_start", {
271
- toolName: "mcp__aws__my_task",
272
- toolUseId: "tool-1",
273
- }));
274
- expect(state?.status).toBe("tool_using");
275
- expect(state?.actionInfo?.actionType).toBe("mcp");
276
- expect(state?.actionInfo?.actionId).toBe("tool-1");
277
- });
278
- it("maps turn completion to idle waiting_input status", () => {
279
- expect(resolveRuntimeStatusFromProviderEvent(event("turn_complete"))?.status).toBe("waiting_input");
280
- });
281
- it("keeps idle tool action info with waiting_input status for display", () => {
282
- const state = resolveRuntimeStatusFromProviderEvent(event("tool_use_start", {
283
- actionType: "idle",
284
- actionLabel: "监听消息",
285
- actionDetail: "poll_message",
286
- toolUseId: "tool-idle-1",
287
- }));
288
- expect(state?.status).toBe("waiting_input");
289
- expect(state?.actionInfo).toMatchObject({
290
- actionType: "idle",
291
- actionLabel: "监听消息",
292
- actionDetail: "poll_message",
293
- actionId: "tool-idle-1",
294
- });
295
- });
296
- it("turn_complete returns clean waiting_input without action info (A方案)", () => {
297
- // 验证: turn_complete 后返回干净的 waiting_input 状态,不设置 "AI响应" action
298
- // 这样可以避免状态卡在 "AI响应" 显示
299
- const state = resolveRuntimeStatusFromProviderEvent(event("turn_complete", {
300
- responseBody: '{"choices":[{"message":{"content":"done"}}]}',
301
- usage: { inputTokens: 100, outputTokens: 50 },
302
- }));
303
- expect(state?.status).toBe("waiting_input");
304
- // 方案 A:不再设置 ai_request action,只保留 usage
305
- expect(state?.actionInfo?.actionType).toBeUndefined();
306
- expect(state?.actionInfo?.actionLabel).toBeUndefined();
307
- expect(state?.actionInfo?.usage).toEqual({ inputTokens: 100, outputTokens: 50 });
308
- });
309
- });
310
- describe("terminal command helpers", () => {
311
- it("expands a whole mini-term clipboard paste file path into SDK input content", async () => {
312
- const tempDir = await mkdtemp(path.join(os.tmpdir(), "terminal-input-"));
313
- const clipboardDir = path.join(tempDir, "mini-term-clipboard");
314
- await mkdir(clipboardDir, { recursive: true });
315
- const pasteFile = path.join(clipboardDir, "paste-1780491671137.txt");
316
- await writeFile(pasteFile, "real pasted prompt", "utf-8");
317
- await expect(resolveSdkInputMessage(`"${pasteFile}"`)).resolves.toBe("real pasted prompt");
318
- });
319
- it("keeps explicit commands that mention mini-term clipboard files unchanged", async () => {
320
- const command = 'type "C:\\Users\\ZHUANG~1\\AppData\\Local\\Temp\\mini-term-clipboard\\paste-1780491671137.txt"';
321
- await expect(resolveSdkInputMessage(command)).resolves.toBe(command);
322
- });
323
- it("normalizes carriage-return terminal input into executable command text", () => {
324
- expect(normalizeTerminalCommandInput("npm test\r")).toBe("npm test");
325
- expect(normalizeTerminalCommandInput(" pwd \n")).toBe("pwd");
326
- });
327
- it("parses cd commands without treating other shell commands as directory changes", () => {
328
- expect(parseTerminalDirectoryChangeTarget("cd")).toBeNull();
329
- expect(parseTerminalDirectoryChangeTarget('cd /d "D:\\code\\repo"')).toBe("D:\\code\\repo");
330
- expect(parseTerminalDirectoryChangeTarget("npm run build")).toBeUndefined();
331
- });
332
- it("formats the working directory prompt as terminal output text", () => {
333
- expect(formatTerminalPrompt("D:\\code\\repo")).toBe("\x1b[36mD:\\code\\repo>\x1b[0m ");
334
- });
335
- it("defaults Windows terminal command output to UTF-8 decoding", () => {
336
- expect(resolveTerminalOutputEncoding("win32", {})).toBe("utf-8");
337
- expect(resolveTerminalOutputEncoding("linux", {})).toBe("utf-8");
338
- expect(resolveTerminalOutputEncoding("win32", {
339
- AWS_TERMINAL_OUTPUT_ENCODING: "utf-8",
340
- })).toBe("utf-8");
341
- });
342
- it("decodes GB18030 Chinese output across chunk boundaries", () => {
343
- const decoder = createTerminalOutputDecoder("gb18030");
344
- const first = decodeTerminalOutputChunk(decoder, Buffer.from([0xd6]));
345
- const second = decodeTerminalOutputChunk(decoder, Buffer.from([0xd0, 0xce, 0xc4]));
346
- const flushed = decodeTerminalOutputChunk(decoder, undefined, true);
347
- expect(`${first}${second}${flushed}`).toBe("中文");
348
- });
349
- it("counts terminal output lines without treating a trailing line break as an extra line", () => {
350
- expect(countTerminalOutputLines("")).toBe(0);
351
- expect(countTerminalOutputLines("one")).toBe(1);
352
- expect(countTerminalOutputLines("one\ntwo\n")).toBe(2);
353
- expect(countTerminalOutputLines("one\r\ntwo\rthree")).toBe(3);
354
- });
355
- it("builds ACode command output spillover paths under ~/.acode/cmd-dist/<agentId>/", () => {
356
- const outputPath = buildAcodeCommandOutputPath("agent-abc-123", new Date(2026, 1, 3, 4, 5, 6, 7));
357
- expect(outputPath).toBe(path.join(os.homedir(), ".acode", "cmd-dist", "agent-abc-123", "2026-02-03", "04", "05", "20260203-040506-007-cmd.out"));
358
- });
359
- it("formats ACode long-output and inactivity notices for terminal users", () => {
360
- expect(formatCommandOutputSpilloverNotice("/repo/out.txt", 300)).toContain("命令输出超过 300 行");
361
- expect(formatCommandOutputSpilloverNotice("/repo/out.txt", 300)).toContain("/repo/out.txt");
362
- expect(formatCommandInactivityTimeoutNotice(60_000)).toContain("超过 60 秒没有新的输出");
363
- });
364
- });
365
- describe("resolveSdkProviderId", () => {
366
- it("exposes codex through the SDK provider SPI", () => {
367
- expect(SDK_PROVIDER_DEFINITIONS.map((definition) => definition.runtimeMode)).toContain("codex");
368
- expect(SDK_PROVIDER_DEFINITIONS.find((definition) => definition.runtimeMode === "codex")).toMatchObject({
369
- providerId: "codex",
370
- defaultCommand: "codex",
371
- });
372
- });
373
- it("resolves codex commands to codex provider", () => {
374
- expect(resolveSdkProviderId("codex")).toBe("codex");
375
- expect(resolveSdkProviderId("npx codex --model gpt-5-codex")).toBe("codex");
376
- });
377
- it("resolves opencode commands to opencode provider", () => {
378
- expect(resolveSdkProviderId("opencode")).toBe("opencode");
379
- });
380
- it("falls back to acode for unknown or empty commands while keeping claude mapped to claude-code", () => {
381
- expect(resolveSdkProviderId("claude")).toBe("claude-code");
382
- expect(resolveSdkProviderId("acode")).toBe("acode");
383
- expect(resolveSdkProviderId("custom-binary")).toBe("acode");
384
- expect(resolveSdkProviderId(undefined)).toBe("acode");
385
- });
386
- });
387
- describe("SDK status usage forwarding", () => {
388
- it("normalizes idle tool status changes to waiting_input", () => {
389
- expect(resolveStatusChangeRuntimeState("tool_using", {
390
- actionType: "idle",
391
- actionLabel: "监听消息",
392
- actionDetail: "aws-mcp/poll_message",
393
- })).toEqual({
394
- status: "waiting_input",
395
- actionInfo: {
396
- actionType: "idle",
397
- actionLabel: "监听消息",
398
- actionDetail: "aws-mcp/poll_message",
399
- },
400
- });
401
- });
402
- it("keeps accumulated usage from status-change action info", () => {
403
- expect(resolveStatusChangeUsage({
404
- usage: { inputTokens: 12000, outputTokens: 345 },
405
- })).toEqual({
406
- inputTokens: 12000,
407
- outputTokens: 345,
408
- });
409
- expect(resolveStatusChangeUsage({ usage: { inputTokens: 0, outputTokens: 0 } })).toBeUndefined();
410
- expect(resolveStatusChangeUsage({
411
- actionType: "mcp",
412
- actionLabel: "Calling MCP",
413
- })).toBeUndefined();
414
- });
415
- it("returns waiting_input without action info on turn_complete (A方案:避免状态卡住)", () => {
416
- const runtimeStatus = resolveRuntimeStatusFromProviderEvent({
417
- type: "turn_complete",
418
- sessionId: "session-1",
419
- timestamp: new Date(0).toISOString(),
420
- data: {
421
- usage: { inputTokens: 12, outputTokens: 4 },
422
- responseBody: '{"choices":[{"message":{"content":"done"}}]}',
423
- finishReason: "stop",
424
- },
425
- });
426
- // 方案 A:不再设置 "AI响应" action 信息,只保留 usage 用于 token 统计
427
- expect(runtimeStatus).toEqual({
428
- status: "waiting_input",
429
- actionInfo: {
430
- usage: { inputTokens: 12, outputTokens: 4 },
431
- },
432
- });
433
- });
434
- it("returns waiting_input without action info when turn_complete has no usage", () => {
435
- const runtimeStatus = resolveRuntimeStatusFromProviderEvent({
436
- type: "turn_complete",
437
- sessionId: "session-1",
438
- timestamp: new Date(0).toISOString(),
439
- data: {
440
- responseBody: '{"choices":[{"message":{"content":"done"}}]}',
441
- finishReason: "stop",
442
- },
443
- });
444
- expect(runtimeStatus).toEqual({
445
- status: "waiting_input",
446
- actionInfo: undefined,
447
- });
448
- });
449
- it("includes file paths and commands in tool status action details", () => {
450
- expect(resolveRuntimeStatusFromProviderEvent({
451
- type: "tool_use_start",
452
- sessionId: "session-1",
453
- timestamp: new Date(0).toISOString(),
454
- data: {
455
- toolName: "builtin/read_file",
456
- toolInput: { path: "src/views/App.vue" },
457
- toolUseId: "tool-read",
458
- },
459
- })).toEqual({
460
- status: "tool_using",
461
- actionInfo: {
462
- actionType: "read_file",
463
- actionLabel: "读取文件",
464
- actionDetail: "src/views/App.vue",
465
- actionInput: JSON.stringify({ path: "src/views/App.vue" }, null, 2),
466
- actionId: "tool-read",
467
- },
468
- });
469
- expect(resolveRuntimeStatusFromProviderEvent({
470
- type: "tool_use_start",
471
- sessionId: "session-1",
472
- timestamp: new Date(0).toISOString(),
473
- data: {
474
- toolName: "bash",
475
- toolInput: { command: "npm run test:agent-timeline-panel" },
476
- toolUseId: "tool-bash",
477
- },
478
- })).toEqual({
479
- status: "tool_using",
480
- actionInfo: {
481
- actionType: "bash",
482
- actionLabel: "执行命令",
483
- actionDetail: "npm run test:agent-timeline-panel",
484
- actionInput: JSON.stringify({ command: "npm run test:agent-timeline-panel" }, null, 2),
485
- actionId: "tool-bash",
486
- },
487
- });
488
- });
489
- });
490
- describe("SDK output forwarding", () => {
491
- it("formats assistant text provider events for the terminal output callback path", () => {
492
- const textEvent = {
493
- type: "text_delta",
494
- sessionId: "session-1",
495
- timestamp: new Date(0).toISOString(),
496
- data: { text: "hello" },
497
- };
498
- expect(formatSdkOutputEvent(textEvent)).toBe("hello");
499
- });
500
- it("formats thinking provider events as typed realtime output chunks", () => {
501
- const thinkingEvent = {
502
- type: "thinking",
503
- sessionId: "session-1",
504
- timestamp: new Date(0).toISOString(),
505
- data: { text: "internal prompt or reasoning" },
506
- };
507
- expect(formatSdkOutputEvent(thinkingEvent)).toBe("internal prompt or reasoning");
508
- });
509
- it("formats command output provider events as realtime output chunks", () => {
510
- const commandOutputEvent = {
511
- type: "command_output",
512
- sessionId: "session-1",
513
- timestamp: new Date(0).toISOString(),
514
- data: {
515
- text: "stdout chunk",
516
- stream: "stdout",
517
- sequence: 7,
518
- cwd: "/repo",
519
- },
520
- };
521
- expect(formatSdkOutputEvent(commandOutputEvent)).toBe("stdout chunk");
522
- });
523
- it("formats SDK errors as terminal output and ignores non-output events", () => {
524
- const errorEvent = {
525
- type: "error",
526
- sessionId: "session-1",
527
- timestamp: new Date(0).toISOString(),
528
- data: { text: "boom" },
529
- };
530
- const toolEvent = {
531
- type: "tool_use_start",
532
- sessionId: "session-1",
533
- timestamp: new Date(0).toISOString(),
534
- data: { toolName: "read_file" },
535
- };
536
- expect(formatSdkOutputEvent(errorEvent)).toBe("\r\n[SDK Error] boom\r\n");
537
- expect(formatSdkOutputEvent(toolEvent)).toBeUndefined();
538
- });
539
- it("formats AI request events as immediate realtime ACode output", () => {
540
- const requestEvent = {
541
- type: "ai_request",
542
- sessionId: "session-1",
543
- timestamp: new Date(0).toISOString(),
544
- data: {
545
- model: "test-model",
546
- lastUserMessagePreview: "inspect status",
547
- },
548
- };
549
- expect(formatSdkOutputEvent(requestEvent)).toBe("\r\n[ACode] 正在请求模型 test-model:inspect status\r\n");
550
- });
551
- it("builds ACode log metadata for output callbacks", () => {
552
- const requestEvent = {
553
- type: "ai_request",
554
- sessionId: "session-1",
555
- timestamp: new Date(0).toISOString(),
556
- data: {
557
- model: "test-model",
558
- endpoint: "openai-compatible",
559
- toolCount: 2,
560
- },
561
- };
562
- const errorEvent = {
563
- type: "error",
564
- sessionId: "session-1",
565
- timestamp: new Date(0).toISOString(),
566
- data: { text: "provider failed" },
567
- };
568
- expect(buildSdkOutputMetadata(requestEvent)).toEqual({
569
- sourceEventType: "ai_request",
570
- logCategory: "acode",
571
- logLevel: "info",
572
- logMessage: "AI request started: test-model @ openai-compatible, tools=2",
573
- });
574
- expect(buildSdkOutputMetadata(errorEvent)).toEqual({
575
- sourceEventType: "error",
576
- logCategory: "acode",
577
- logLevel: "error",
578
- logMessage: "provider failed",
579
- });
580
- });
581
- it("builds ordered ACode log metadata for command output callbacks", () => {
582
- const commandOutputEvent = {
583
- type: "command_output",
584
- sessionId: "session-1",
585
- timestamp: new Date(0).toISOString(),
586
- data: {
587
- text: "stdout chunk",
588
- stream: "stdout",
589
- sequence: 7,
590
- cwd: "/repo",
591
- },
592
- };
593
- expect(buildSdkOutputMetadata(commandOutputEvent)).toEqual({
594
- sourceEventType: "command_output",
595
- logCategory: "acode",
596
- logLevel: "info",
597
- logMessage: "命令输出(stdout #7): stdout chunk",
598
- stream: "stdout",
599
- sequence: 7,
600
- cwd: "/repo",
601
- });
602
- });
603
- it("does not mark streaming text chunks as standalone ACode log rows", () => {
604
- const metadata = buildSdkOutputMetadata({
605
- type: "text_delta",
606
- sessionId: "session-1",
607
- data: { text: "word" },
608
- });
609
- expect(metadata).toEqual({
610
- sourceEventType: "text_delta",
611
- logCategory: "acode",
612
- });
613
- });
614
- it("includes file paths and commands in ACode tool log metadata", () => {
615
- const readEvent = {
616
- type: "tool_use_start",
617
- sessionId: "session-1",
618
- timestamp: new Date(0).toISOString(),
619
- data: {
620
- toolName: "read_file",
621
- toolInput: { path: "src/index.ts" },
622
- },
623
- };
624
- const editEvent = {
625
- type: "tool_use_start",
626
- sessionId: "session-1",
627
- timestamp: new Date(0).toISOString(),
628
- data: {
629
- toolName: "edit",
630
- toolInput: { file_path: "src/app.ts" },
631
- },
632
- };
633
- const writeEvent = {
634
- type: "tool_use_end",
635
- sessionId: "session-1",
636
- timestamp: new Date(0).toISOString(),
637
- data: {
638
- toolName: "write_file",
639
- toolInput: { path: "src/new-file.ts" },
640
- },
641
- };
642
- const bashEvent = {
643
- type: "tool_use_start",
644
- sessionId: "session-1",
645
- timestamp: new Date(0).toISOString(),
646
- data: {
647
- toolName: "bash",
648
- toolInput: { command: "npm run build -- --mode production" },
649
- },
650
- };
651
- expect(buildSdkOutputMetadata(readEvent).logMessage).toBe("开始读取文件: src/index.ts");
652
- expect(buildSdkOutputMetadata(editEvent).logMessage).toBe("开始编辑文件: src/app.ts");
653
- expect(buildSdkOutputMetadata(writeEvent).logMessage).toBe("完成写入文件: src/new-file.ts");
654
- expect(buildSdkOutputMetadata(bashEvent).logMessage).toBe("开始执行命令: npm run build -- --mode production");
655
- });
656
- });
657
- describe("SDK tool result timeline action info", () => {
658
- it("keeps MCP tool results on MCP timeline events", () => {
659
- const event = {
660
- type: "tool_use_end",
661
- sessionId: "session-1",
662
- timestamp: new Date(0).toISOString(),
663
- data: {
664
- toolName: "mcp__aws-mcp__get_profile",
665
- toolUseId: "tool-1",
666
- toolResult: '{"displayName":"Agent"}',
667
- },
668
- };
669
- expect(buildToolResultTimelineActionInfo(event)).toEqual({
670
- actionType: "mcp",
671
- actionLabel: "MCP返回",
672
- actionDetail: "mcp__aws-mcp__get_profile",
673
- actionId: "tool-1",
674
- actionResult: '{"displayName":"Agent"}',
675
- });
676
- });
677
- it("forwards bash tool results to command timeline events", () => {
678
- const event = {
679
- type: "tool_use_end",
680
- sessionId: "session-1",
681
- timestamp: new Date(0).toISOString(),
682
- data: {
683
- toolName: "bash",
684
- toolInput: { command: "npm run build" },
685
- toolUseId: "tool-2",
686
- toolResult: "build passed",
687
- },
688
- };
689
- expect(buildToolResultTimelineActionInfo(event)).toEqual({
690
- actionType: "bash",
691
- actionLabel: "执行命令",
692
- actionDetail: "npm run build",
693
- actionId: "tool-2",
694
- actionResult: "build passed",
695
- });
696
- });
697
- it("forwards read tool results to file-read timeline events", () => {
698
- const event = {
699
- type: "tool_use_end",
700
- sessionId: "session-1",
701
- timestamp: new Date(0).toISOString(),
702
- data: {
703
- toolName: "read_file",
704
- toolInput: { path: "src/index.ts" },
705
- actionId: "tool-3",
706
- actionResult: "export const ok = true",
707
- },
708
- };
709
- expect(buildToolResultTimelineActionInfo(event)).toEqual({
710
- actionType: "read_file",
711
- actionLabel: "读取文件",
712
- actionDetail: "src/index.ts",
713
- actionId: "tool-3",
714
- actionResult: "export const ok = true",
715
- });
716
- });
717
- it("keeps MCP-named filesystem results on semantic file-read timeline events", () => {
718
- const event = {
719
- type: "tool_use_end",
720
- sessionId: "session-1",
721
- timestamp: new Date(0).toISOString(),
722
- data: {
723
- toolName: "mcp__filesystem__read_file",
724
- toolInput: { path: "src/index.ts" },
725
- toolUseId: "tool-4",
726
- toolResult: "export const ok = true",
727
- },
728
- };
729
- expect(buildToolResultTimelineActionInfo(event)).toEqual({
730
- actionType: "read_file",
731
- actionLabel: "读取文件",
732
- actionDetail: "src/index.ts",
733
- actionId: "tool-4",
734
- actionResult: "export const ok = true",
735
- });
736
- });
737
- it("ignores tool result events without displayable result content", () => {
738
- const event = {
739
- type: "tool_use_end",
740
- sessionId: "session-1",
741
- timestamp: new Date(0).toISOString(),
742
- data: { toolName: "read_file", toolResult: " " },
743
- };
744
- expect(buildToolResultTimelineActionInfo(event)).toBeUndefined();
745
- });
746
- });