@downcity/agent 1.1.237 → 1.1.258

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 (578) hide show
  1. package/README.md +21 -20
  2. package/bin/agent/{local/Agent.d.ts → Agent.d.ts} +37 -27
  3. package/bin/agent/Agent.d.ts.map +1 -0
  4. package/bin/agent/Agent.js +211 -0
  5. package/bin/agent/Agent.js.map +1 -0
  6. package/bin/agent/AgentContext.d.ts +64 -0
  7. package/bin/agent/AgentContext.d.ts.map +1 -0
  8. package/bin/agent/AgentContext.js +53 -0
  9. package/bin/agent/AgentContext.js.map +1 -0
  10. package/bin/agent/{local/AgentInstructions.d.ts → AgentInstructions.d.ts} +1 -6
  11. package/bin/agent/AgentInstructions.d.ts.map +1 -0
  12. package/bin/agent/{local/AgentInstructions.js → AgentInstructions.js} +1 -10
  13. package/bin/agent/AgentInstructions.js.map +1 -0
  14. package/bin/{model/CityModelAdapter.d.ts → agent/AgentModel.d.ts} +3 -3
  15. package/bin/agent/AgentModel.d.ts.map +1 -0
  16. package/bin/{model/CityModelAdapter.js → agent/AgentModel.js} +11 -4
  17. package/bin/agent/AgentModel.js.map +1 -0
  18. package/bin/agent/{local/services/AgentSessions.d.ts → AgentSessions.d.ts} +30 -40
  19. package/bin/agent/AgentSessions.d.ts.map +1 -0
  20. package/bin/agent/{local/services/AgentSessions.js → AgentSessions.js} +62 -79
  21. package/bin/agent/AgentSessions.js.map +1 -0
  22. package/bin/agent/AgentState.d.ts +64 -0
  23. package/bin/agent/AgentState.d.ts.map +1 -0
  24. package/bin/agent/AgentState.js +118 -0
  25. package/bin/agent/AgentState.js.map +1 -0
  26. package/bin/config/Paths.d.ts +0 -43
  27. package/bin/config/Paths.d.ts.map +1 -1
  28. package/bin/config/Paths.js +0 -79
  29. package/bin/config/Paths.js.map +1 -1
  30. package/bin/config/ProjectSetup.d.ts.map +1 -0
  31. package/bin/{agent/local → config}/ProjectSetup.js +1 -1
  32. package/bin/config/ProjectSetup.js.map +1 -0
  33. package/bin/executor/Executor.d.ts +20 -86
  34. package/bin/executor/Executor.d.ts.map +1 -1
  35. package/bin/executor/Executor.js +109 -260
  36. package/bin/executor/Executor.js.map +1 -1
  37. package/bin/executor/composer/system/default/DefaultSessionSystemComposer.d.ts +1 -1
  38. package/bin/executor/composer/system/default/DefaultSessionSystemComposer.d.ts.map +1 -1
  39. package/bin/executor/composer/system/default/SystemDomain.d.ts +1 -1
  40. package/bin/executor/composer/system/default/SystemDomain.d.ts.map +1 -1
  41. package/bin/executor/composer/system/default/SystemDomain.js +4 -1
  42. package/bin/executor/composer/system/default/SystemDomain.js.map +1 -1
  43. package/bin/executor/composer/system/default/assets/core.prompt.d.ts +1 -1
  44. package/bin/executor/composer/system/default/assets/core.prompt.d.ts.map +1 -1
  45. package/bin/executor/composer/system/default/assets/core.prompt.js +1 -1
  46. package/bin/executor/composer/system/default/assets/core.prompt.js.map +1 -1
  47. package/bin/executor/core-engine/CoreEngineRunner.d.ts +7 -13
  48. package/bin/executor/core-engine/CoreEngineRunner.d.ts.map +1 -1
  49. package/bin/executor/core-engine/CoreEngineRunner.js +81 -34
  50. package/bin/executor/core-engine/CoreEngineRunner.js.map +1 -1
  51. package/bin/executor/services/ExecutorRecoveryPolicy.d.ts +6 -12
  52. package/bin/executor/services/ExecutorRecoveryPolicy.d.ts.map +1 -1
  53. package/bin/executor/services/ExecutorRecoveryPolicy.js +20 -6
  54. package/bin/executor/services/ExecutorRecoveryPolicy.js.map +1 -1
  55. package/bin/executor/tools/file/ReadImageToolBridge.d.ts +21 -0
  56. package/bin/executor/tools/file/ReadImageToolBridge.d.ts.map +1 -0
  57. package/bin/executor/tools/file/ReadImageToolBridge.js +69 -0
  58. package/bin/executor/tools/file/ReadImageToolBridge.js.map +1 -0
  59. package/bin/executor/tools/plugin/PluginToolBridge.d.ts.map +1 -1
  60. package/bin/executor/tools/plugin/PluginToolBridge.js +6 -5
  61. package/bin/executor/tools/plugin/PluginToolBridge.js.map +1 -1
  62. package/bin/executor/tools/plugin/PluginToolDefinition.d.ts.map +1 -1
  63. package/bin/executor/tools/plugin/PluginToolDefinition.js +15 -2
  64. package/bin/executor/tools/plugin/PluginToolDefinition.js.map +1 -1
  65. package/bin/executor/types/SessionHistoryMeta.d.ts +0 -2
  66. package/bin/executor/types/SessionHistoryMeta.d.ts.map +1 -1
  67. package/bin/index.d.ts +17 -21
  68. package/bin/index.d.ts.map +1 -1
  69. package/bin/index.js +9 -11
  70. package/bin/index.js.map +1 -1
  71. package/bin/plugin/core/ActionScheduleExecutor.d.ts +1 -1
  72. package/bin/plugin/core/ActionScheduleExecutor.d.ts.map +1 -1
  73. package/bin/plugin/core/ActionScheduleRuntime.d.ts +1 -1
  74. package/bin/plugin/core/ActionScheduleRuntime.d.ts.map +1 -1
  75. package/bin/plugin/core/BasePlugin.d.ts +4 -3
  76. package/bin/plugin/core/BasePlugin.d.ts.map +1 -1
  77. package/bin/plugin/core/BasePlugin.js.map +1 -1
  78. package/bin/plugin/core/HookRegistry.d.ts +5 -8
  79. package/bin/plugin/core/HookRegistry.d.ts.map +1 -1
  80. package/bin/plugin/core/HookRegistry.js +12 -12
  81. package/bin/plugin/core/HookRegistry.js.map +1 -1
  82. package/bin/plugin/core/PluginActionFactory.d.ts +6 -3
  83. package/bin/plugin/core/PluginActionFactory.d.ts.map +1 -1
  84. package/bin/plugin/core/PluginActionFactory.js.map +1 -1
  85. package/bin/plugin/core/PluginActionRunner.d.ts +1 -1
  86. package/bin/plugin/core/PluginActionRunner.d.ts.map +1 -1
  87. package/bin/plugin/core/PluginCatalog.d.ts +1 -1
  88. package/bin/plugin/core/PluginCatalog.d.ts.map +1 -1
  89. package/bin/plugin/core/PluginHttpRoutes.d.ts +1 -1
  90. package/bin/plugin/core/PluginHttpRoutes.d.ts.map +1 -1
  91. package/bin/plugin/core/PluginLocalExecution.d.ts +4 -5
  92. package/bin/plugin/core/PluginLocalExecution.d.ts.map +1 -1
  93. package/bin/plugin/core/PluginLocalExecution.js +4 -12
  94. package/bin/plugin/core/PluginLocalExecution.js.map +1 -1
  95. package/bin/plugin/core/PluginRegistry.d.ts +16 -12
  96. package/bin/plugin/core/PluginRegistry.d.ts.map +1 -1
  97. package/bin/plugin/core/PluginRegistry.js +43 -22
  98. package/bin/plugin/core/PluginRegistry.js.map +1 -1
  99. package/bin/plugin/core/PluginStateController.d.ts +1 -1
  100. package/bin/plugin/core/PluginStateController.d.ts.map +1 -1
  101. package/bin/{agent/remote → remote}/RemoteAgent.d.ts +4 -4
  102. package/bin/remote/RemoteAgent.d.ts.map +1 -0
  103. package/bin/{agent/remote → remote}/RemoteAgent.js +3 -3
  104. package/bin/remote/RemoteAgent.js.map +1 -0
  105. package/bin/{agent/remote → remote}/RemoteSession.d.ts +9 -11
  106. package/bin/remote/RemoteSession.d.ts.map +1 -0
  107. package/bin/{agent/remote → remote}/RemoteSession.js +3 -33
  108. package/bin/remote/RemoteSession.js.map +1 -0
  109. package/bin/{agent/remote → remote}/RemoteTransport.d.ts +7 -9
  110. package/bin/remote/RemoteTransport.d.ts.map +1 -0
  111. package/bin/remote/RemoteTransport.js.map +1 -0
  112. package/bin/{agent/remote → remote}/TransportFactory.d.ts +1 -1
  113. package/bin/remote/TransportFactory.d.ts.map +1 -0
  114. package/bin/{agent/remote → remote}/TransportFactory.js +2 -2
  115. package/bin/remote/TransportFactory.js.map +1 -0
  116. package/bin/{agent/remote → remote}/transports/HttpRemoteAgentTransport.d.ts +8 -9
  117. package/bin/remote/transports/HttpRemoteAgentTransport.d.ts.map +1 -0
  118. package/bin/{agent/remote → remote}/transports/HttpRemoteAgentTransport.js +0 -13
  119. package/bin/remote/transports/HttpRemoteAgentTransport.js.map +1 -0
  120. package/bin/{rpc/Client.d.ts → remote/transports/RpcClient.d.ts} +15 -22
  121. package/bin/remote/transports/RpcClient.d.ts.map +1 -0
  122. package/bin/{rpc/Client.js → remote/transports/RpcClient.js} +2 -13
  123. package/bin/remote/transports/RpcClient.js.map +1 -0
  124. package/bin/{agent/remote → remote}/transports/RpcRemoteAgentTransport.d.ts +8 -9
  125. package/bin/remote/transports/RpcRemoteAgentTransport.d.ts.map +1 -0
  126. package/bin/{agent/remote → remote}/transports/RpcRemoteAgentTransport.js +1 -4
  127. package/bin/remote/transports/RpcRemoteAgentTransport.js.map +1 -0
  128. package/bin/session/DefaultSessionComposer.d.ts +18 -0
  129. package/bin/session/DefaultSessionComposer.d.ts.map +1 -0
  130. package/bin/session/DefaultSessionComposer.js +62 -0
  131. package/bin/session/DefaultSessionComposer.js.map +1 -0
  132. package/bin/session/Session.d.ts +44 -33
  133. package/bin/session/Session.d.ts.map +1 -1
  134. package/bin/session/Session.js +440 -274
  135. package/bin/session/Session.js.map +1 -1
  136. package/bin/session/SessionMessages.d.ts +117 -0
  137. package/bin/session/SessionMessages.d.ts.map +1 -0
  138. package/bin/session/{recorder/SessionRecorder.js → SessionMessages.js} +194 -284
  139. package/bin/session/SessionMessages.js.map +1 -0
  140. package/bin/session/SessionQueue.d.ts +34 -0
  141. package/bin/session/SessionQueue.d.ts.map +1 -0
  142. package/bin/session/SessionQueue.js +60 -0
  143. package/bin/session/SessionQueue.js.map +1 -0
  144. package/bin/session/SessionState.d.ts +70 -0
  145. package/bin/session/SessionState.d.ts.map +1 -0
  146. package/bin/session/SessionState.js +267 -0
  147. package/bin/session/SessionState.js.map +1 -0
  148. package/bin/session/SessionSystem.d.ts +15 -0
  149. package/bin/session/SessionSystem.d.ts.map +1 -0
  150. package/bin/session/SessionSystem.js +95 -0
  151. package/bin/session/SessionSystem.js.map +1 -0
  152. package/bin/session/SessionTurn.d.ts +84 -0
  153. package/bin/session/SessionTurn.d.ts.map +1 -0
  154. package/bin/session/SessionTurn.js +588 -0
  155. package/bin/session/SessionTurn.js.map +1 -0
  156. package/bin/session/approval/SessionApprovalBroker.d.ts +48 -0
  157. package/bin/session/approval/SessionApprovalBroker.d.ts.map +1 -0
  158. package/bin/session/approval/SessionApprovalBroker.js +126 -0
  159. package/bin/session/approval/SessionApprovalBroker.js.map +1 -0
  160. package/bin/session/browse/Browse.d.ts.map +1 -1
  161. package/bin/session/browse/Browse.js +1 -4
  162. package/bin/session/browse/Browse.js.map +1 -1
  163. package/bin/session/{recorder → messages}/JsonlSessionMessageStore.d.ts.map +1 -1
  164. package/bin/session/{recorder → messages}/JsonlSessionMessageStore.js.map +1 -1
  165. package/bin/session/messages/SessionAssistantMessageWriter.d.ts +62 -0
  166. package/bin/session/messages/SessionAssistantMessageWriter.d.ts.map +1 -0
  167. package/bin/session/messages/SessionAssistantMessageWriter.js +287 -0
  168. package/bin/session/messages/SessionAssistantMessageWriter.js.map +1 -0
  169. package/bin/session/messages/SessionJsonValue.d.ts +10 -0
  170. package/bin/session/messages/SessionJsonValue.d.ts.map +1 -0
  171. package/bin/session/messages/SessionJsonValue.js +23 -0
  172. package/bin/session/messages/SessionJsonValue.js.map +1 -0
  173. package/bin/session/{recorder → messages}/SessionMessageCodec.d.ts +4 -1
  174. package/bin/session/messages/SessionMessageCodec.d.ts.map +1 -0
  175. package/bin/session/{recorder → messages}/SessionMessageCodec.js +33 -19
  176. package/bin/session/messages/SessionMessageCodec.js.map +1 -0
  177. package/bin/session/messages/SessionMessageCompaction.d.ts +22 -0
  178. package/bin/session/messages/SessionMessageCompaction.d.ts.map +1 -0
  179. package/bin/session/{recorder/SessionRecorderCompaction.js → messages/SessionMessageCompaction.js} +19 -51
  180. package/bin/session/messages/SessionMessageCompaction.js.map +1 -0
  181. package/bin/session/runtime/SessionEventHub.d.ts +1 -8
  182. package/bin/session/runtime/SessionEventHub.d.ts.map +1 -1
  183. package/bin/session/runtime/SessionEventHub.js +1 -6
  184. package/bin/session/runtime/SessionEventHub.js.map +1 -1
  185. package/bin/session/storage/Metadata.d.ts +23 -5
  186. package/bin/session/storage/Metadata.d.ts.map +1 -1
  187. package/bin/session/storage/Metadata.js +32 -29
  188. package/bin/session/storage/Metadata.js.map +1 -1
  189. package/bin/session/storage/RuntimeSessionPort.d.ts +5 -10
  190. package/bin/session/storage/RuntimeSessionPort.d.ts.map +1 -1
  191. package/bin/session/storage/RuntimeSessionPort.js +2 -4
  192. package/bin/session/storage/RuntimeSessionPort.js.map +1 -1
  193. package/bin/types/agent/AgentOptions.d.ts +6 -35
  194. package/bin/types/agent/AgentOptions.d.ts.map +1 -1
  195. package/bin/types/agent/AgentState.d.ts +28 -0
  196. package/bin/types/agent/AgentState.d.ts.map +1 -0
  197. package/bin/types/agent/AgentState.js +9 -0
  198. package/bin/types/agent/AgentState.js.map +1 -0
  199. package/bin/types/agent/SessionActor.d.ts +0 -2
  200. package/bin/types/agent/SessionActor.d.ts.map +1 -1
  201. package/bin/types/agent/SessionTypes.d.ts +5 -18
  202. package/bin/types/agent/SessionTypes.d.ts.map +1 -1
  203. package/bin/types/executor/SessionRunContext.d.ts +8 -2
  204. package/bin/types/executor/SessionRunContext.d.ts.map +1 -1
  205. package/bin/types/executor/SessionRunContext.js +1 -1
  206. package/bin/types/executor/SessionToolExecutionContext.d.ts +20 -0
  207. package/bin/types/executor/SessionToolExecutionContext.d.ts.map +1 -0
  208. package/bin/types/executor/SessionToolExecutionContext.js +10 -0
  209. package/bin/types/executor/SessionToolExecutionContext.js.map +1 -0
  210. package/bin/types/plugin/PluginAction.d.ts +10 -1
  211. package/bin/types/plugin/PluginAction.d.ts.map +1 -1
  212. package/bin/types/plugin/PluginCommand.d.ts +3 -11
  213. package/bin/types/plugin/PluginCommand.d.ts.map +1 -1
  214. package/bin/types/plugin/PluginConfig.d.ts +12 -0
  215. package/bin/types/plugin/PluginConfig.d.ts.map +1 -0
  216. package/bin/types/plugin/PluginConfig.js +5 -0
  217. package/bin/types/plugin/PluginConfig.js.map +1 -0
  218. package/bin/types/plugin/PluginDefinition.d.ts +10 -3
  219. package/bin/types/plugin/PluginDefinition.d.ts.map +1 -1
  220. package/bin/types/plugin/PluginHttp.d.ts +1 -1
  221. package/bin/types/plugin/PluginHttp.d.ts.map +1 -1
  222. package/bin/types/plugin/PluginRunContext.d.ts +26 -0
  223. package/bin/types/plugin/PluginRunContext.d.ts.map +1 -0
  224. package/bin/types/plugin/PluginRunContext.js +10 -0
  225. package/bin/types/plugin/PluginRunContext.js.map +1 -0
  226. package/bin/types/plugin/PluginRuntime.d.ts +9 -3
  227. package/bin/types/plugin/PluginRuntime.d.ts.map +1 -1
  228. package/bin/types/plugin/PluginToolRuntime.d.ts +11 -0
  229. package/bin/types/plugin/PluginToolRuntime.d.ts.map +1 -1
  230. package/bin/types/rpc/RpcProtocol.d.ts +1 -13
  231. package/bin/types/rpc/RpcProtocol.d.ts.map +1 -1
  232. package/bin/types/session/SessionApproval.d.ts +4 -38
  233. package/bin/types/session/SessionApproval.d.ts.map +1 -1
  234. package/bin/types/session/SessionApprovalBroker.d.ts +17 -0
  235. package/bin/types/session/SessionApprovalBroker.d.ts.map +1 -0
  236. package/bin/types/session/SessionApprovalBroker.js +7 -0
  237. package/bin/types/session/SessionApprovalBroker.js.map +1 -0
  238. package/bin/types/session/SessionComposer.d.ts +99 -0
  239. package/bin/types/session/SessionComposer.d.ts.map +1 -0
  240. package/bin/types/session/SessionComposer.js +8 -0
  241. package/bin/types/session/SessionComposer.js.map +1 -0
  242. package/bin/types/session/SessionLocalState.d.ts +6 -6
  243. package/bin/types/session/SessionLocalState.d.ts.map +1 -1
  244. package/bin/types/session/SessionLocalState.js +1 -1
  245. package/bin/types/session/SessionMessage.d.ts +3 -2
  246. package/bin/types/session/SessionMessage.d.ts.map +1 -1
  247. package/bin/types/session/SessionMessages.d.ts +115 -0
  248. package/bin/types/session/SessionMessages.d.ts.map +1 -0
  249. package/bin/types/session/SessionMessages.js +7 -0
  250. package/bin/types/session/SessionMessages.js.map +1 -0
  251. package/bin/types/session/SessionMutation.d.ts +1 -10
  252. package/bin/types/session/SessionMutation.d.ts.map +1 -1
  253. package/bin/types/session/SessionMutation.js.map +1 -1
  254. package/bin/types/session/SessionOptions.d.ts +8 -23
  255. package/bin/types/session/SessionOptions.d.ts.map +1 -1
  256. package/bin/types/session/SessionPort.d.ts +72 -0
  257. package/bin/types/session/SessionPort.d.ts.map +1 -0
  258. package/bin/types/session/SessionPort.js +9 -0
  259. package/bin/types/session/SessionPort.js.map +1 -0
  260. package/bin/types/session/SessionQueue.d.ts +104 -0
  261. package/bin/types/session/SessionQueue.d.ts.map +1 -0
  262. package/bin/types/session/SessionQueue.js +7 -0
  263. package/bin/types/session/SessionQueue.js.map +1 -0
  264. package/bin/types/session/SessionState.d.ts +43 -0
  265. package/bin/types/session/SessionState.d.ts.map +1 -0
  266. package/bin/types/session/SessionState.js +7 -0
  267. package/bin/types/session/SessionState.js.map +1 -0
  268. package/bin/types/session/SessionSystem.d.ts +26 -0
  269. package/bin/types/session/SessionSystem.d.ts.map +1 -0
  270. package/bin/types/session/SessionSystem.js +7 -0
  271. package/bin/types/session/SessionSystem.js.map +1 -0
  272. package/bin/types/session/SessionTool.d.ts +23 -0
  273. package/bin/types/session/SessionTool.d.ts.map +1 -0
  274. package/bin/types/session/SessionTool.js +7 -0
  275. package/bin/types/session/SessionTool.js.map +1 -0
  276. package/bin/types/session/SessionTurn.d.ts +52 -0
  277. package/bin/types/session/SessionTurn.d.ts.map +1 -0
  278. package/bin/types/session/SessionTurn.js +7 -0
  279. package/bin/types/session/SessionTurn.js.map +1 -0
  280. package/package.json +3 -3
  281. package/scripts/agent-env.test.mjs +4 -18
  282. package/scripts/agent-ready.test.mjs +33 -2
  283. package/scripts/agent-session-maintenance.test.mjs +52 -0
  284. package/scripts/city-model-tool-loop.test.mjs +3 -4
  285. package/scripts/core-engine-context-compaction.test.mjs +5 -22
  286. package/scripts/image-plugin-job.test.mjs +4 -6
  287. package/scripts/plugin-tool-bridge.test.mjs +44 -36
  288. package/scripts/read-image-tool-bridge.test.mjs +71 -0
  289. package/scripts/remote-session-reconnect.test.mjs +1 -34
  290. package/scripts/session-compaction-prompts.test.mjs +1 -49
  291. package/scripts/session-composer.test.mjs +163 -0
  292. package/scripts/session-config-turn-boundary.test.mjs +2 -5
  293. package/scripts/session-list-title.test.mjs +3 -2
  294. package/scripts/session-messages-error.test.mjs +57 -0
  295. package/scripts/{session-recorder.test.mjs → session-messages.test.mjs} +131 -90
  296. package/scripts/session-queue.test.mjs +64 -0
  297. package/scripts/session-shell-approval.test.mjs +171 -0
  298. package/scripts/session-system-blocks.test.mjs +10 -10
  299. package/scripts/session-title-event.test.mjs +1 -0
  300. package/src/agent/Agent.ts +241 -0
  301. package/src/agent/AgentContext.ts +92 -0
  302. package/src/agent/{local/AgentInstructions.ts → AgentInstructions.ts} +0 -11
  303. package/src/{model/CityModelAdapter.ts → agent/AgentModel.ts} +10 -3
  304. package/src/agent/{local/services/AgentSessions.ts → AgentSessions.ts} +81 -110
  305. package/src/agent/AgentState.ts +151 -0
  306. package/src/config/Paths.ts +0 -91
  307. package/src/executor/Executor.ts +180 -386
  308. package/src/executor/README.md +29 -89
  309. package/src/executor/composer/system/default/DefaultSessionSystemComposer.ts +1 -1
  310. package/src/executor/composer/system/default/SystemDomain.ts +4 -2
  311. package/src/executor/composer/system/default/assets/core.prompt.ts +1 -1
  312. package/src/executor/composer/system/default/assets/core.prompt.ts.txt +15 -2
  313. package/src/executor/core-engine/CoreEngineRunner.ts +95 -54
  314. package/src/executor/services/ExecutorRecoveryPolicy.ts +24 -19
  315. package/src/executor/tools/file/ReadImageToolBridge.ts +79 -0
  316. package/src/executor/tools/plugin/PluginToolBridge.ts +6 -8
  317. package/src/executor/tools/plugin/PluginToolDefinition.ts +23 -3
  318. package/src/executor/types/SessionHistoryMeta.ts +0 -2
  319. package/src/index.ts +34 -53
  320. package/src/plugin/core/ActionScheduleExecutor.ts +1 -1
  321. package/src/plugin/core/ActionScheduleRuntime.ts +1 -1
  322. package/src/plugin/core/BasePlugin.ts +7 -3
  323. package/src/plugin/core/HookRegistry.ts +15 -18
  324. package/src/plugin/core/PluginActionFactory.ts +9 -3
  325. package/src/plugin/core/PluginActionRunner.ts +1 -1
  326. package/src/plugin/core/PluginCatalog.ts +1 -1
  327. package/src/plugin/core/PluginHttpRoutes.ts +1 -1
  328. package/src/plugin/core/PluginLocalExecution.ts +11 -24
  329. package/src/plugin/core/PluginRegistry.ts +55 -32
  330. package/src/plugin/core/PluginStateController.ts +1 -1
  331. package/src/{agent/remote → remote}/RemoteAgent.ts +4 -4
  332. package/src/{agent/remote → remote}/RemoteSession.ts +2 -35
  333. package/src/{agent/remote → remote}/RemoteTransport.ts +0 -3
  334. package/src/{agent/remote → remote}/TransportFactory.ts +3 -3
  335. package/src/{agent/remote → remote}/transports/HttpRemoteAgentTransport.ts +1 -23
  336. package/src/{rpc/Client.ts → remote/transports/RpcClient.ts} +1 -19
  337. package/src/{agent/remote → remote}/transports/RpcRemoteAgentTransport.ts +2 -10
  338. package/src/session/DefaultSessionComposer.ts +79 -0
  339. package/src/session/Session.ts +496 -332
  340. package/src/session/{recorder/SessionRecorder.ts → SessionMessages.ts} +254 -428
  341. package/src/session/SessionQueue.ts +86 -0
  342. package/src/session/SessionState.ts +322 -0
  343. package/src/session/SessionSystem.ts +117 -0
  344. package/src/session/SessionTurn.ts +684 -0
  345. package/src/session/approval/SessionApprovalBroker.ts +164 -0
  346. package/src/session/browse/Browse.ts +1 -4
  347. package/src/session/messages/SessionAssistantMessageWriter.ts +345 -0
  348. package/src/session/messages/SessionJsonValue.ts +25 -0
  349. package/src/session/{recorder → messages}/SessionMessageCodec.ts +38 -20
  350. package/src/session/{recorder/SessionRecorderCompaction.ts → messages/SessionMessageCompaction.ts} +30 -69
  351. package/src/session/runtime/SessionEventHub.ts +1 -14
  352. package/src/session/storage/Metadata.ts +60 -34
  353. package/src/session/storage/RuntimeSessionPort.ts +7 -14
  354. package/src/types/agent/AgentOptions.ts +6 -38
  355. package/src/types/agent/AgentState.ts +33 -0
  356. package/src/types/agent/SessionActor.ts +0 -3
  357. package/src/types/agent/SessionTypes.ts +5 -18
  358. package/src/types/executor/SessionRunContext.ts +10 -2
  359. package/src/types/executor/SessionToolExecutionContext.ts +21 -0
  360. package/src/types/plugin/PluginAction.ts +10 -1
  361. package/src/types/plugin/PluginCommand.ts +3 -14
  362. package/src/types/plugin/PluginConfig.ts +13 -0
  363. package/src/types/plugin/PluginDefinition.ts +13 -6
  364. package/src/types/plugin/PluginHttp.ts +1 -1
  365. package/src/types/plugin/PluginRunContext.ts +31 -0
  366. package/src/types/plugin/PluginRuntime.ts +13 -6
  367. package/src/types/plugin/PluginToolRuntime.ts +13 -1
  368. package/src/types/rpc/RpcProtocol.ts +0 -14
  369. package/src/types/session/SessionApproval.ts +4 -43
  370. package/src/types/session/SessionApprovalBroker.ts +18 -0
  371. package/src/types/session/SessionComposer.ts +114 -0
  372. package/src/types/session/SessionLocalState.ts +6 -6
  373. package/src/types/session/SessionMessage.ts +3 -2
  374. package/src/types/session/SessionMessages.ts +127 -0
  375. package/src/types/session/SessionMutation.ts +0 -11
  376. package/src/types/session/SessionOptions.ts +8 -40
  377. package/src/types/session/SessionPort.ts +97 -0
  378. package/src/types/session/SessionQueue.ts +122 -0
  379. package/src/types/session/SessionState.ts +47 -0
  380. package/src/types/session/SessionSystem.ts +27 -0
  381. package/src/types/session/SessionTool.ts +25 -0
  382. package/src/types/session/SessionTurn.ts +56 -0
  383. package/tsconfig.tsbuildinfo +1 -1
  384. package/bin/agent/local/Agent.d.ts.map +0 -1
  385. package/bin/agent/local/Agent.js +0 -216
  386. package/bin/agent/local/Agent.js.map +0 -1
  387. package/bin/agent/local/AgentInstructions.d.ts.map +0 -1
  388. package/bin/agent/local/AgentInstructions.js.map +0 -1
  389. package/bin/agent/local/AgentPluginFactory.d.ts +0 -26
  390. package/bin/agent/local/AgentPluginFactory.d.ts.map +0 -1
  391. package/bin/agent/local/AgentPluginFactory.js +0 -33
  392. package/bin/agent/local/AgentPluginFactory.js.map +0 -1
  393. package/bin/agent/local/AgentRuntimeAssembly.d.ts +0 -10
  394. package/bin/agent/local/AgentRuntimeAssembly.d.ts.map +0 -1
  395. package/bin/agent/local/AgentRuntimeAssembly.js +0 -43
  396. package/bin/agent/local/AgentRuntimeAssembly.js.map +0 -1
  397. package/bin/agent/local/ProjectSetup.d.ts.map +0 -1
  398. package/bin/agent/local/ProjectSetup.js.map +0 -1
  399. package/bin/agent/local/services/AgentAssemblyService.d.ts +0 -105
  400. package/bin/agent/local/services/AgentAssemblyService.d.ts.map +0 -1
  401. package/bin/agent/local/services/AgentAssemblyService.js +0 -184
  402. package/bin/agent/local/services/AgentAssemblyService.js.map +0 -1
  403. package/bin/agent/local/services/AgentBackgroundService.d.ts +0 -55
  404. package/bin/agent/local/services/AgentBackgroundService.d.ts.map +0 -1
  405. package/bin/agent/local/services/AgentBackgroundService.js +0 -85
  406. package/bin/agent/local/services/AgentBackgroundService.js.map +0 -1
  407. package/bin/agent/local/services/AgentSessions.d.ts.map +0 -1
  408. package/bin/agent/local/services/AgentSessions.js.map +0 -1
  409. package/bin/agent/remote/RemoteAgent.d.ts.map +0 -1
  410. package/bin/agent/remote/RemoteAgent.js.map +0 -1
  411. package/bin/agent/remote/RemoteSession.d.ts.map +0 -1
  412. package/bin/agent/remote/RemoteSession.js.map +0 -1
  413. package/bin/agent/remote/RemoteTransport.d.ts.map +0 -1
  414. package/bin/agent/remote/RemoteTransport.js.map +0 -1
  415. package/bin/agent/remote/TransportFactory.d.ts.map +0 -1
  416. package/bin/agent/remote/TransportFactory.js.map +0 -1
  417. package/bin/agent/remote/transports/HttpRemoteAgentTransport.d.ts.map +0 -1
  418. package/bin/agent/remote/transports/HttpRemoteAgentTransport.js.map +0 -1
  419. package/bin/agent/remote/transports/RpcRemoteAgentTransport.d.ts.map +0 -1
  420. package/bin/agent/remote/transports/RpcRemoteAgentTransport.js.map +0 -1
  421. package/bin/executor/SessionRunScope.d.ts +0 -68
  422. package/bin/executor/SessionRunScope.d.ts.map +0 -1
  423. package/bin/executor/SessionRunScope.js +0 -96
  424. package/bin/executor/SessionRunScope.js.map +0 -1
  425. package/bin/executor/composer/compaction/SessionCompactionComposer.d.ts +0 -74
  426. package/bin/executor/composer/compaction/SessionCompactionComposer.d.ts.map +0 -1
  427. package/bin/executor/composer/compaction/SessionCompactionComposer.js +0 -9
  428. package/bin/executor/composer/compaction/SessionCompactionComposer.js.map +0 -1
  429. package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionComposer.d.ts +0 -27
  430. package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionComposer.d.ts.map +0 -1
  431. package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionComposer.js +0 -39
  432. package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionComposer.js.map +0 -1
  433. package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionExecutor.d.ts +0 -44
  434. package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionExecutor.d.ts.map +0 -1
  435. package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionExecutor.js +0 -218
  436. package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionExecutor.js.map +0 -1
  437. package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionFileOperations.d.ts +0 -27
  438. package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionFileOperations.d.ts.map +0 -1
  439. package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionFileOperations.js +0 -181
  440. package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionFileOperations.js.map +0 -1
  441. package/bin/executor/composer/context/LocalSessionContextComposer.d.ts +0 -50
  442. package/bin/executor/composer/context/LocalSessionContextComposer.d.ts.map +0 -1
  443. package/bin/executor/composer/context/LocalSessionContextComposer.js +0 -108
  444. package/bin/executor/composer/context/LocalSessionContextComposer.js.map +0 -1
  445. package/bin/executor/composer/context/SessionContextComposer.d.ts +0 -67
  446. package/bin/executor/composer/context/SessionContextComposer.d.ts.map +0 -1
  447. package/bin/executor/composer/context/SessionContextComposer.js +0 -9
  448. package/bin/executor/composer/context/SessionContextComposer.js.map +0 -1
  449. package/bin/executor/composer/history/SessionHistoryComposer.d.ts +0 -54
  450. package/bin/executor/composer/history/SessionHistoryComposer.d.ts.map +0 -1
  451. package/bin/executor/composer/history/SessionHistoryComposer.js +0 -10
  452. package/bin/executor/composer/history/SessionHistoryComposer.js.map +0 -1
  453. package/bin/executor/composer/history/SessionHistoryWriter.d.ts +0 -46
  454. package/bin/executor/composer/history/SessionHistoryWriter.d.ts.map +0 -1
  455. package/bin/executor/composer/history/SessionHistoryWriter.js +0 -65
  456. package/bin/executor/composer/history/SessionHistoryWriter.js.map +0 -1
  457. package/bin/executor/composer/history/jsonl/JsonlSessionHistoryComposer.d.ts +0 -35
  458. package/bin/executor/composer/history/jsonl/JsonlSessionHistoryComposer.d.ts.map +0 -1
  459. package/bin/executor/composer/history/jsonl/JsonlSessionHistoryComposer.js +0 -105
  460. package/bin/executor/composer/history/jsonl/JsonlSessionHistoryComposer.js.map +0 -1
  461. package/bin/executor/messages/AssistantResultPersistence.d.ts +0 -66
  462. package/bin/executor/messages/AssistantResultPersistence.d.ts.map +0 -1
  463. package/bin/executor/messages/AssistantResultPersistence.js +0 -44
  464. package/bin/executor/messages/AssistantResultPersistence.js.map +0 -1
  465. package/bin/executor/services/ExecutorInflightService.d.ts +0 -34
  466. package/bin/executor/services/ExecutorInflightService.d.ts.map +0 -1
  467. package/bin/executor/services/ExecutorInflightService.js +0 -73
  468. package/bin/executor/services/ExecutorInflightService.js.map +0 -1
  469. package/bin/executor/store/history/SessionHistoryStore.d.ts +0 -140
  470. package/bin/executor/store/history/SessionHistoryStore.d.ts.map +0 -1
  471. package/bin/executor/store/history/SessionHistoryStore.js +0 -10
  472. package/bin/executor/store/history/SessionHistoryStore.js.map +0 -1
  473. package/bin/executor/store/history/jsonl/JsonlSessionHistoryStore.d.ts +0 -116
  474. package/bin/executor/store/history/jsonl/JsonlSessionHistoryStore.d.ts.map +0 -1
  475. package/bin/executor/store/history/jsonl/JsonlSessionHistoryStore.js +0 -709
  476. package/bin/executor/store/history/jsonl/JsonlSessionHistoryStore.js.map +0 -1
  477. package/bin/executor/types/SessionHistoryPaths.d.ts +0 -34
  478. package/bin/executor/types/SessionHistoryPaths.d.ts.map +0 -1
  479. package/bin/executor/types/SessionHistoryPaths.js +0 -2
  480. package/bin/executor/types/SessionHistoryPaths.js.map +0 -1
  481. package/bin/model/CityModelAdapter.d.ts.map +0 -1
  482. package/bin/model/CityModelAdapter.js.map +0 -1
  483. package/bin/rpc/Client.d.ts.map +0 -1
  484. package/bin/rpc/Client.js.map +0 -1
  485. package/bin/session/SessionSystemBuilder.d.ts +0 -107
  486. package/bin/session/SessionSystemBuilder.d.ts.map +0 -1
  487. package/bin/session/SessionSystemBuilder.js +0 -148
  488. package/bin/session/SessionSystemBuilder.js.map +0 -1
  489. package/bin/session/recorder/SessionMessageCodec.d.ts.map +0 -1
  490. package/bin/session/recorder/SessionMessageCodec.js.map +0 -1
  491. package/bin/session/recorder/SessionRecorder.d.ts +0 -217
  492. package/bin/session/recorder/SessionRecorder.d.ts.map +0 -1
  493. package/bin/session/recorder/SessionRecorder.js.map +0 -1
  494. package/bin/session/recorder/SessionRecorderCompaction.d.ts +0 -18
  495. package/bin/session/recorder/SessionRecorderCompaction.d.ts.map +0 -1
  496. package/bin/session/recorder/SessionRecorderCompaction.js.map +0 -1
  497. package/bin/session/recorder/SessionRecorderHistoryStore.d.ts +0 -66
  498. package/bin/session/recorder/SessionRecorderHistoryStore.d.ts.map +0 -1
  499. package/bin/session/recorder/SessionRecorderHistoryStore.js +0 -190
  500. package/bin/session/recorder/SessionRecorderHistoryStore.js.map +0 -1
  501. package/bin/session/runtime/SessionPromptRuntime.d.ts +0 -112
  502. package/bin/session/runtime/SessionPromptRuntime.d.ts.map +0 -1
  503. package/bin/session/runtime/SessionPromptRuntime.js +0 -357
  504. package/bin/session/runtime/SessionPromptRuntime.js.map +0 -1
  505. package/bin/session/services/SessionStateService.d.ts +0 -187
  506. package/bin/session/services/SessionStateService.d.ts.map +0 -1
  507. package/bin/session/services/SessionStateService.js +0 -467
  508. package/bin/session/services/SessionStateService.js.map +0 -1
  509. package/bin/session/services/SessionTurnService.d.ts +0 -90
  510. package/bin/session/services/SessionTurnService.d.ts.map +0 -1
  511. package/bin/session/services/SessionTurnService.js +0 -293
  512. package/bin/session/services/SessionTurnService.js.map +0 -1
  513. package/bin/session/services/SessionViewService.d.ts +0 -114
  514. package/bin/session/services/SessionViewService.d.ts.map +0 -1
  515. package/bin/session/services/SessionViewService.js +0 -204
  516. package/bin/session/services/SessionViewService.js.map +0 -1
  517. package/bin/session/storage/Persistence.d.ts +0 -73
  518. package/bin/session/storage/Persistence.d.ts.map +0 -1
  519. package/bin/session/storage/Persistence.js +0 -63
  520. package/bin/session/storage/Persistence.js.map +0 -1
  521. package/bin/types/agent/AgentRuntimeAssembly.d.ts +0 -72
  522. package/bin/types/agent/AgentRuntimeAssembly.d.ts.map +0 -1
  523. package/bin/types/agent/AgentRuntimeAssembly.js +0 -10
  524. package/bin/types/agent/AgentRuntimeAssembly.js.map +0 -1
  525. package/bin/types/runtime/agent/AgentContext.d.ts +0 -306
  526. package/bin/types/runtime/agent/AgentContext.d.ts.map +0 -1
  527. package/bin/types/runtime/agent/AgentContext.js +0 -128
  528. package/bin/types/runtime/agent/AgentContext.js.map +0 -1
  529. package/bin/types/session/SessionComposerOptions.d.ts +0 -90
  530. package/bin/types/session/SessionComposerOptions.d.ts.map +0 -1
  531. package/bin/types/session/SessionComposerOptions.js +0 -10
  532. package/bin/types/session/SessionComposerOptions.js.map +0 -1
  533. package/bin/types/session/SessionQueueCommand.d.ts +0 -68
  534. package/bin/types/session/SessionQueueCommand.d.ts.map +0 -1
  535. package/bin/types/session/SessionQueueCommand.js +0 -10
  536. package/bin/types/session/SessionQueueCommand.js.map +0 -1
  537. package/scripts/session-action-message.test.mjs +0 -410
  538. package/scripts/session-compaction-context-window.test.mjs +0 -96
  539. package/scripts/session-history-inflight.test.mjs +0 -146
  540. package/scripts/session-history-writer-error.test.mjs +0 -57
  541. package/scripts/session-prompt-runtime.test.mjs +0 -390
  542. package/src/agent/local/Agent.ts +0 -250
  543. package/src/agent/local/AgentPluginFactory.ts +0 -51
  544. package/src/agent/local/AgentRuntimeAssembly.ts +0 -65
  545. package/src/agent/local/services/AgentAssemblyService.ts +0 -307
  546. package/src/agent/local/services/AgentBackgroundService.ts +0 -115
  547. package/src/executor/SessionRunScope.ts +0 -122
  548. package/src/executor/composer/compaction/SessionCompactionComposer.ts +0 -84
  549. package/src/executor/composer/compaction/jsonl/JsonlSessionCompactionComposer.ts +0 -51
  550. package/src/executor/composer/compaction/jsonl/JsonlSessionCompactionExecutor.ts +0 -294
  551. package/src/executor/composer/compaction/jsonl/JsonlSessionCompactionFileOperations.ts +0 -197
  552. package/src/executor/composer/context/LocalSessionContextComposer.ts +0 -175
  553. package/src/executor/composer/context/SessionContextComposer.ts +0 -83
  554. package/src/executor/composer/history/SessionHistoryComposer.ts +0 -62
  555. package/src/executor/composer/history/SessionHistoryWriter.ts +0 -100
  556. package/src/executor/composer/history/jsonl/JsonlSessionHistoryComposer.ts +0 -133
  557. package/src/executor/messages/AssistantResultPersistence.ts +0 -106
  558. package/src/executor/services/ExecutorInflightService.ts +0 -95
  559. package/src/executor/store/history/SessionHistoryStore.ts +0 -172
  560. package/src/executor/store/history/jsonl/JsonlSessionHistoryStore.ts +0 -879
  561. package/src/executor/types/SessionHistoryPaths.ts +0 -38
  562. package/src/session/SessionSystemBuilder.ts +0 -262
  563. package/src/session/recorder/SessionRecorderHistoryStore.ts +0 -256
  564. package/src/session/runtime/SessionPromptRuntime.ts +0 -518
  565. package/src/session/services/SessionStateService.ts +0 -628
  566. package/src/session/services/SessionTurnService.ts +0 -368
  567. package/src/session/services/SessionViewService.ts +0 -335
  568. package/src/session/storage/Persistence.ts +0 -137
  569. package/src/types/agent/AgentRuntimeAssembly.ts +0 -74
  570. package/src/types/runtime/agent/AgentContext.ts +0 -387
  571. package/src/types/session/SessionComposerOptions.ts +0 -107
  572. package/src/types/session/SessionQueueCommand.ts +0 -78
  573. /package/bin/{agent/local → config}/ProjectSetup.d.ts +0 -0
  574. /package/bin/{agent/remote → remote}/RemoteTransport.js +0 -0
  575. /package/bin/session/{recorder → messages}/JsonlSessionMessageStore.d.ts +0 -0
  576. /package/bin/session/{recorder → messages}/JsonlSessionMessageStore.js +0 -0
  577. /package/src/{agent/local → config}/ProjectSetup.ts +0 -0
  578. /package/src/session/{recorder → messages}/JsonlSessionMessageStore.ts +0 -0
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @file 验证 SessionRecorder 的 Message 快照、Assistant 草稿与实时事件一致性。
2
+ * @file 验证 SessionMessages 的 Message 快照、Assistant 草稿与实时事件一致性。
3
3
  */
4
4
 
5
5
  import test from "node:test";
@@ -8,10 +8,11 @@ import fs from "node:fs/promises";
8
8
  import os from "node:os";
9
9
  import path from "node:path";
10
10
 
11
- import { JsonlSessionMessageStore } from "../bin/session/recorder/JsonlSessionMessageStore.js";
12
- import { SessionRecorder } from "../bin/session/recorder/SessionRecorder.js";
13
- import { SessionRecorderHistoryStore } from "../bin/session/recorder/SessionRecorderHistoryStore.js";
14
- import { SessionViewService } from "../bin/session/services/SessionViewService.js";
11
+ import { JsonlSessionMessageStore } from "../bin/session/messages/JsonlSessionMessageStore.js";
12
+ import { SessionMessages } from "../bin/session/SessionMessages.js";
13
+ import { SessionApprovalBroker } from "../bin/session/approval/SessionApprovalBroker.js";
14
+ import { compose_session_compaction } from "../bin/session/messages/SessionMessageCompaction.js";
15
+ import { to_executor_history } from "../bin/session/messages/SessionMessageCodec.js";
15
16
  import { MockLanguageModelV3 } from "ai/test";
16
17
 
17
18
  async function create_recorder(session_id = "session-recorder-test") {
@@ -19,7 +20,7 @@ async function create_recorder(session_id = "session-recorder-test") {
19
20
  const file_path = path.join(root_path, "active.jsonl");
20
21
  const assistant_message_file_path = path.join(root_path, "assistant_message.json");
21
22
  const events = [];
22
- const recorder = new SessionRecorder({
23
+ const recorder = new SessionMessages({
23
24
  session_id,
24
25
  store: new JsonlSessionMessageStore({ session_id, file_path }),
25
26
  publish: (mutation) => events.push(mutation),
@@ -41,7 +42,7 @@ async function create_seeded_recorder(session_id, messages) {
41
42
  `${messages.map((message) => JSON.stringify(message)).join("\n")}\n`,
42
43
  "utf8",
43
44
  );
44
- const recorder = new SessionRecorder({
45
+ const recorder = new SessionMessages({
45
46
  session_id,
46
47
  store: new JsonlSessionMessageStore({ session_id, file_path }),
47
48
  publish: () => {},
@@ -50,6 +51,20 @@ async function create_seeded_recorder(session_id, messages) {
50
51
  return { recorder, file_path };
51
52
  }
52
53
 
54
+ async function compact_messages(recorder, session_id, model) {
55
+ const plan = await compose_session_compaction({
56
+ session_id,
57
+ snapshot: await recorder.context_snapshot(),
58
+ model,
59
+ });
60
+ if (!plan) return false;
61
+ await recorder.compact_active({
62
+ through_sequence: plan.through_sequence,
63
+ summary: plan.summary,
64
+ });
65
+ return true;
66
+ }
67
+
53
68
  function create_seeded_user_message(session_id, sequence) {
54
69
  return {
55
70
  message_id: `user-${String(sequence)}`,
@@ -110,26 +125,42 @@ test("delta 只更新 Assistant 草稿,完成后才写入 active.jsonl", async
110
125
  assert.equal(history.some((value) => "variant" in value), false);
111
126
  });
112
127
 
113
- test("Tool Part 在文本中间创建后,输入、审批和输出都保持原顺序", async () => {
128
+ test("Tool Runtime 在文本中间保持输入、审批和输出的确定顺序", async () => {
114
129
  const { recorder, events, file_path } = await create_recorder("tool-order-test");
130
+ const approval_broker = new SessionApprovalBroker({
131
+ session_id: "tool-order-test",
132
+ messages: recorder,
133
+ });
115
134
  const writer = await recorder.open_assistant_message({ turn_id: "turn-1", segment_index: 1 });
116
135
  await writer.apply_chunk({ type: "text-start", id: "text-1" });
117
136
  await writer.apply_chunk({ type: "text-delta", id: "text-1", delta: "before" });
118
137
  await writer.apply_chunk({ type: "text-end", id: "text-1" });
119
- await writer.apply_chunk({ type: "tool-input-start", toolCallId: "call-1", toolName: "search" });
138
+ await writer.apply_chunk({ type: "tool-input-start", toolCallId: "call-1", toolName: "shell_exec" });
120
139
  await writer.apply_chunk({
121
140
  type: "tool-input-available",
122
141
  toolCallId: "call-1",
123
- toolName: "search",
124
- input: { query: "downcity" },
142
+ toolName: "shell_exec",
143
+ input: { cmd: "pwd", sandbox: "unrestricted", reason: "Inspect directory" },
125
144
  });
126
145
  assert.equal(recorder.get_message(writer.message_id).parts[1].state, "ready");
127
- await writer.apply_chunk({
128
- type: "tool-approval-request",
129
- toolCallId: "call-1",
130
- approvalId: "approval-1",
146
+ const approval_handle = await approval_broker.request({
147
+ shell_id: "shell-1",
148
+ tool_call_id: "call-1",
149
+ tool_name: "shell_exec",
150
+ session_id: "tool-order-test",
151
+ turn_id: "turn-1",
152
+ command: "pwd",
153
+ cwd: "/workspace",
154
+ reason: "Inspect directory",
155
+ operation: "exec",
156
+ timeout_ms: 60_000,
131
157
  });
132
158
  assert.equal(recorder.get_message(writer.message_id).parts[1].state, "approval-required");
159
+ await approval_broker.resolve({
160
+ approval_id: approval_handle.approval_id,
161
+ decision: "approved",
162
+ });
163
+ assert.equal(await approval_handle.decision, "approved");
133
164
  await writer.apply_chunk({ type: "text-start", id: "text-2" });
134
165
  await writer.apply_chunk({ type: "text-delta", id: "text-2", delta: "after" });
135
166
  await writer.apply_chunk({ type: "text-end", id: "text-2" });
@@ -145,7 +176,76 @@ test("Tool Part 在文本中间创建后,输入、审批和输出都保持原
145
176
  events
146
177
  .filter((event) => event.variant === "part" && event.type === "tool")
147
178
  .map((event) => [event.part.sequence, event.part.state]),
148
- [[2, "input-streaming"], [2, "ready"], [2, "approval-required"], [2, "completed"]],
179
+ [
180
+ [2, "input-streaming"],
181
+ [2, "ready"],
182
+ [2, "approval-required"],
183
+ [2, "running"],
184
+ [2, "completed"],
185
+ ],
186
+ );
187
+ });
188
+
189
+ test("Approval Broker 只接受已经准备完整输入的 Tool", async () => {
190
+ const { recorder, events } = await create_recorder("tool-ready-barrier-test");
191
+ const approval_broker = new SessionApprovalBroker({
192
+ session_id: "tool-ready-barrier-test",
193
+ messages: recorder,
194
+ });
195
+ const writer = await recorder.open_assistant_message({
196
+ turn_id: "turn-ready-barrier",
197
+ segment_index: 1,
198
+ });
199
+ const approval_input = {
200
+ shell_id: "shell-ready-barrier",
201
+ tool_call_id: "call-ready-barrier",
202
+ tool_name: "shell_exec",
203
+ session_id: "tool-ready-barrier-test",
204
+ turn_id: "turn-ready-barrier",
205
+ command: "ls -la /Users/example/Desktop",
206
+ cwd: "/workspace",
207
+ reason: "Inspect requested desktop files",
208
+ operation: "exec",
209
+ timeout_ms: 60_000,
210
+ };
211
+ await assert.rejects(
212
+ approval_broker.request(approval_input),
213
+ /Streaming Tool Part not found/,
214
+ );
215
+ assert.equal(approval_broker.list().length, 0);
216
+
217
+ await writer.prepare_tool_input({
218
+ tool_call_id: "call-ready-barrier",
219
+ tool_name: "shell_exec",
220
+ input: {
221
+ cmd: "ls -la /Users/example/Desktop",
222
+ sandbox: "unrestricted",
223
+ reason: "Inspect requested desktop files",
224
+ },
225
+ });
226
+ const approval_handle = await approval_broker.request(approval_input);
227
+
228
+ const tool = recorder.get_message(writer.message_id).parts[0];
229
+ assert.equal(tool.state, "approval-required");
230
+ assert.equal(tool.approval.approval_id, approval_handle.approval_id);
231
+ assert.equal(tool.approval.command, approval_input.command);
232
+ assert.equal(tool.input.cmd, "ls -la /Users/example/Desktop");
233
+ await approval_broker.resolve({
234
+ approval_id: approval_handle.approval_id,
235
+ decision: "denied",
236
+ });
237
+ assert.equal(await approval_handle.decision, "denied");
238
+ await writer.apply_chunk({
239
+ type: "tool-output-available",
240
+ toolCallId: "call-ready-barrier",
241
+ output: { success: false, approval_status: "denied" },
242
+ });
243
+ assert.equal(recorder.get_message(writer.message_id).parts[0].state, "failed");
244
+ assert.deepEqual(
245
+ events
246
+ .filter((event) => event.variant === "part" && event.type === "tool")
247
+ .map((event) => event.part.state),
248
+ ["ready", "approval-required", "failed"],
149
249
  );
150
250
  });
151
251
 
@@ -248,7 +348,7 @@ test("重启时将 Assistant 草稿收口为 stopped,并将运行中 Action
248
348
  await recorder.open_action_message({ message_id: "running-action", action_type: "fork", title: "Forking" });
249
349
 
250
350
  const recovered_events = [];
251
- const recovered = new SessionRecorder({
351
+ const recovered = new SessionMessages({
252
352
  session_id: "recovery-test",
253
353
  store: new JsonlSessionMessageStore({ session_id: "recovery-test", file_path }),
254
354
  publish: (mutation) => recovered_events.push(mutation),
@@ -292,7 +392,6 @@ test("compact 把 Active 前缀关闭为带累计 Summary 的 Segment", async ()
292
392
  parts: [{ part_id: `user-${String(index)}`, type: "text", text: `message ${String(index)}`, state: "done" }],
293
393
  });
294
394
  }
295
- const history_store = new SessionRecorderHistoryStore({ session_id: "compact-test", recorder });
296
395
  const model = new MockLanguageModelV3({
297
396
  modelId: "compact-model",
298
397
  doGenerate: async () => ({
@@ -305,12 +404,7 @@ test("compact 把 Active 前缀关闭为带累计 Summary 的 Segment", async ()
305
404
  warnings: [],
306
405
  }),
307
406
  });
308
- const result = await history_store.compact({
309
- model,
310
- system: [],
311
- force: true,
312
- });
313
- assert.equal(result.compacted, true);
407
+ assert.equal(await compact_messages(recorder, "compact-test", model), true);
314
408
  assert.equal((await fs.readFile(file_path, "utf8")).includes("message 1"), false);
315
409
  const active = await recorder.list_messages({ include_internal: true });
316
410
  assert.deepEqual(active.items.map((message) => message.sequence), []);
@@ -322,7 +416,10 @@ test("compact 把 Active 前缀关闭为带累计 Summary 的 Segment", async ()
322
416
  });
323
417
  assert.deepEqual(segment.items.map((message) => message.sequence), [1, 2, 3, 4, 5, 6]);
324
418
  assert.equal(segment.source, "segment");
325
- assert.equal((await history_store.list_records()).length, 1);
419
+ assert.equal(
420
+ to_executor_history("compact-test", await recorder.context_snapshot()).length,
421
+ 1,
422
+ );
326
423
  await assert.rejects(
327
424
  recorder.list_messages({ before_sequence: 0 }),
328
425
  /before_sequence must be a positive integer/,
@@ -356,14 +453,13 @@ test("重启后从最新 Segment Summary 与 Active 恢复模型上下文", asyn
356
453
  },
357
454
  });
358
455
 
359
- const restarted = new SessionRecorder({
456
+ const restarted = new SessionMessages({
360
457
  session_id,
361
458
  store: new JsonlSessionMessageStore({ session_id, file_path }),
362
459
  publish: () => {},
363
460
  });
364
461
  await restarted.initialize();
365
- const context_store = new SessionRecorderHistoryStore({ session_id, recorder: restarted });
366
- const context = await context_store.list_records();
462
+ const context = to_executor_history(session_id, await restarted.context_snapshot());
367
463
  assert.deepEqual(
368
464
  context.map((message) => message.parts[0]?.text),
369
465
  ["summary through 4", "message 5", "message 6"],
@@ -414,7 +510,7 @@ test("Compact 两步提交中断后会清理 Active 与 Segment 的重叠前缀"
414
510
  "utf8",
415
511
  );
416
512
 
417
- const restarted = new SessionRecorder({
513
+ const restarted = new SessionMessages({
418
514
  session_id,
419
515
  store: new JsonlSessionMessageStore({ session_id, file_path }),
420
516
  publish: () => {},
@@ -449,7 +545,6 @@ test("连续 Compact 生成按 sequence 连续的 Segment 与累计 Summary", as
449
545
  };
450
546
  },
451
547
  });
452
- const history_store = new SessionRecorderHistoryStore({ session_id, recorder });
453
548
  const append_messages = async (start, end) => {
454
549
  for (let index = start; index <= end; index += 1) {
455
550
  await recorder.append_user_message({
@@ -464,16 +559,12 @@ test("连续 Compact 生成按 sequence 连续的 Segment 与累计 Summary", as
464
559
  });
465
560
  }
466
561
  };
467
- const compact = async () => await history_store.compact({
468
- model,
469
- system: [],
470
- force: true,
471
- });
562
+ const compact = async () => await compact_messages(recorder, session_id, model);
472
563
 
473
564
  await append_messages(1, 8);
474
- assert.equal((await compact()).compacted, true);
565
+ assert.equal(await compact(), true);
475
566
  await append_messages(9, 12);
476
- assert.equal((await compact()).compacted, true);
567
+ assert.equal(await compact(), true);
477
568
 
478
569
  assert.equal(prompts.length, 2);
479
570
  assert.equal(prompts[1].includes("<previous-summary>"), true);
@@ -487,7 +578,7 @@ test("连续 Compact 生成按 sequence 连续的 Segment 与累计 Summary", as
487
578
  before_sequence: latest_segment.start_sequence,
488
579
  });
489
580
  assert.deepEqual(earliest_segment.items.map((message) => message.sequence), [1, 2, 3, 4, 5, 6, 7, 8]);
490
- const context = await history_store.list_records();
581
+ const context = to_executor_history(session_id, await recorder.context_snapshot());
491
582
  assert.equal(context[0].parts[0]?.text, "Summary 2");
492
583
  });
493
584
 
@@ -512,14 +603,7 @@ test("Summary 生成失败时使用确定性 Summary 完成归档", async () =>
512
603
  throw new Error("summary unavailable");
513
604
  },
514
605
  });
515
- const history_store = new SessionRecorderHistoryStore({ session_id, recorder });
516
- const result = await history_store.compact({
517
- model,
518
- system: [],
519
- force: true,
520
- });
521
-
522
- assert.deepEqual(result, { compacted: true });
606
+ assert.equal(await compact_messages(recorder, session_id, model), true);
523
607
  assert.deepEqual((await recorder.list_messages()).items, []);
524
608
  const segment_entries = await fs.readdir(path.join(path.dirname(file_path), "segments"));
525
609
  assert.equal(segment_entries.length, 1);
@@ -554,52 +638,9 @@ test("内部上下文读取完整快照并保留第 500 条之后的最新消息
554
638
  assert.equal(previous.start_sequence, 1);
555
639
  assert.equal(previous.end_sequence, 499);
556
640
 
557
- const history_store = new SessionRecorderHistoryStore({ session_id, recorder });
558
- const context = await history_store.list_records();
641
+ const context = to_executor_history(session_id, await recorder.context_snapshot());
559
642
  assert.deepEqual(
560
643
  context.map((message) => message.parts[0]?.text),
561
644
  ["summary through 499", "message 500", "message 501"],
562
645
  );
563
646
  });
564
-
565
- test("Session fork 可以选择并复制第 500 条之后的消息", async () => {
566
- const session_id = "complete-fork-snapshot-test";
567
- const messages = Array.from(
568
- { length: 501 },
569
- (_, index) => create_seeded_user_message(session_id, index + 1),
570
- );
571
- const { recorder } = await create_seeded_recorder(session_id, messages);
572
- let imported_messages = [];
573
- const state_service = {
574
- emit_action_event: async () => {},
575
- get_config: () => ({}),
576
- };
577
- const view_service = new SessionViewService({
578
- agent_id: "fork-agent",
579
- project_root: os.tmpdir(),
580
- session_id,
581
- history_store: new SessionRecorderHistoryStore({ session_id, recorder }),
582
- recorder,
583
- state_service,
584
- logger: { log: async () => {} },
585
- is_executing: () => false,
586
- get_instruction_system_blocks: () => [],
587
- get_managed_plugin_system_blocks: async () => [],
588
- get_plugin_system_blocks: async () => [],
589
- create_fork_session: async () => ({
590
- session: { id: "forked-session", set: async () => {} },
591
- history_store: {},
592
- recorder: {
593
- import_messages: async (input) => {
594
- imported_messages = input;
595
- },
596
- },
597
- state_service: { set: async () => {} },
598
- }),
599
- });
600
-
601
- await view_service.fork("user-501");
602
-
603
- assert.equal(imported_messages.length, 501);
604
- assert.equal(imported_messages[500].message_id, "user-501");
605
- });
@@ -0,0 +1,64 @@
1
+ /**
2
+ * @file 验证 SessionQueue 只维护 Prompt/Command 的确定 FIFO 顺序。
3
+ */
4
+
5
+ import assert from "node:assert/strict";
6
+ import test from "node:test";
7
+ import { SessionQueue } from "../bin/session/SessionQueue.js";
8
+
9
+ function model_command(command_id) {
10
+ return {
11
+ type: "session_model",
12
+ command_id,
13
+ config: {},
14
+ };
15
+ }
16
+
17
+ test("SessionQueue 返回首个 Prompt 及其之前的命令", () => {
18
+ const queue = new SessionQueue();
19
+ queue.enqueue_command(model_command("command-1"));
20
+ const handle = queue.enqueue_prompt({ query: "first" });
21
+ queue.enqueue_command({ type: "compact", command_id: "compact-1" });
22
+
23
+ const next = queue.take_next_prompt();
24
+ assert.deepEqual(next.commands.map((item) => item.command_id), ["command-1"]);
25
+ assert.equal(next.prompt.input.query, "first");
26
+ assert.equal(handle instanceof Promise, true);
27
+ assert.equal(queue.has_command(), true);
28
+ assert.equal(queue.has_prompt(), false);
29
+ });
30
+
31
+ test("SessionQueue drain 保留 Prompt 和 Command 的原始顺序", () => {
32
+ const queue = new SessionQueue();
33
+ queue.enqueue_prompt({ query: "steer-1" });
34
+ queue.enqueue_command(model_command("command-1"));
35
+ queue.enqueue_prompt({ query: "steer-2" });
36
+
37
+ assert.deepEqual(
38
+ queue.drain().map((item) => item.type),
39
+ ["prompt", "session_model", "prompt"],
40
+ );
41
+ assert.equal(queue.has_prompt(), false);
42
+ });
43
+
44
+ test("SessionQueue cancel_prompts 取消 Prompt 但保留命令", () => {
45
+ const queue = new SessionQueue();
46
+ queue.enqueue_prompt({ query: "queued" });
47
+ queue.enqueue_command({ type: "compact", command_id: "compact-1" });
48
+
49
+ assert.equal(queue.cancel_prompts().length, 1);
50
+ assert.deepEqual(queue.drain(), [
51
+ { type: "compact", command_id: "compact-1" },
52
+ ]);
53
+ });
54
+
55
+ test("SessionQueue 可以把未处理输入恢复到队列头部", () => {
56
+ const queue = new SessionQueue();
57
+ queue.enqueue_command({ type: "compact", command_id: "tail" });
58
+ queue.restore_front([model_command("head")]);
59
+
60
+ assert.deepEqual(
61
+ queue.drain().map((item) => item.command_id),
62
+ ["head", "tail"],
63
+ );
64
+ });
@@ -0,0 +1,171 @@
1
+ /**
2
+ * @file 验证 Session Tool Runtime 向 Shell 传递完整审批归属。
3
+ *
4
+ * 关键点(中文)
5
+ * - 通过真实 Agent、Executor 与 Shell tool loop 发起 unrestricted 请求。
6
+ * - approval-required Mutation 必须携带当前 Session、Turn 与 Tool Call 标识。
7
+ * - 用户批准后命令才执行,最终 Tool Part 收口为 completed。
8
+ */
9
+
10
+ import test from "node:test";
11
+ import assert from "node:assert/strict";
12
+ import fs from "node:fs/promises";
13
+ import os from "node:os";
14
+ import path from "node:path";
15
+ import { MockLanguageModelV3 } from "ai/test";
16
+ import { Agent } from "@downcity/agent";
17
+ import { Shell } from "@downcity/shell";
18
+
19
+ /** 构造 AI SDK V3 usage。 */
20
+ function create_usage() {
21
+ return {
22
+ inputTokens: { total: 0, noCache: 0, cacheRead: 0, cacheWrite: 0 },
23
+ outputTokens: { total: 0, text: 0, reasoning: 0 },
24
+ };
25
+ }
26
+
27
+ /** 构造要求执行 unrestricted shell_exec 的模型流。 */
28
+ function create_tool_call_stream() {
29
+ return {
30
+ stream: new ReadableStream({
31
+ start(controller) {
32
+ controller.enqueue({ type: "stream-start", warnings: [] });
33
+ controller.enqueue({
34
+ type: "tool-input-start",
35
+ id: "call_unrestricted",
36
+ toolName: "shell_exec",
37
+ });
38
+ controller.enqueue({
39
+ type: "tool-input-delta",
40
+ id: "call_unrestricted",
41
+ delta: JSON.stringify({
42
+ cmd: "printf approval-ok",
43
+ shell: "/bin/sh",
44
+ login: false,
45
+ sandbox: "unrestricted",
46
+ reason: "验证 Session unrestricted 审批归属。",
47
+ }),
48
+ });
49
+ controller.enqueue({
50
+ type: "tool-input-end",
51
+ id: "call_unrestricted",
52
+ });
53
+ controller.enqueue({
54
+ type: "tool-call",
55
+ toolCallId: "call_unrestricted",
56
+ toolName: "shell_exec",
57
+ input: JSON.stringify({
58
+ cmd: "printf approval-ok",
59
+ shell: "/bin/sh",
60
+ login: false,
61
+ sandbox: "unrestricted",
62
+ reason: "验证 Session unrestricted 审批归属。",
63
+ }),
64
+ });
65
+ controller.enqueue({
66
+ type: "finish",
67
+ finishReason: { unified: "tool-calls", raw: "tool-calls" },
68
+ usage: create_usage(),
69
+ });
70
+ controller.close();
71
+ },
72
+ }),
73
+ };
74
+ }
75
+
76
+ /** 构造 Tool 执行后的最终文本流。 */
77
+ function create_final_text_stream() {
78
+ return {
79
+ stream: new ReadableStream({
80
+ start(controller) {
81
+ controller.enqueue({ type: "stream-start", warnings: [] });
82
+ controller.enqueue({ type: "text-start", id: "text_1" });
83
+ controller.enqueue({ type: "text-delta", id: "text_1", delta: "done" });
84
+ controller.enqueue({ type: "text-end", id: "text_1" });
85
+ controller.enqueue({
86
+ type: "finish",
87
+ finishReason: { unified: "stop", raw: "stop" },
88
+ usage: create_usage(),
89
+ });
90
+ controller.close();
91
+ },
92
+ }),
93
+ };
94
+ }
95
+
96
+ test("unrestricted Shell 审批保留当前 Turn 并等待用户决定", async () => {
97
+ const project_root = await fs.mkdtemp(
98
+ path.join(os.tmpdir(), "downcity-session-shell-approval-"),
99
+ );
100
+ let stream_count = 0;
101
+ const model = new MockLanguageModelV3({
102
+ modelId: "session-shell-approval-model",
103
+ doStream: async (options) => {
104
+ if (!Array.isArray(options.tools) || options.tools.length === 0) {
105
+ return create_final_text_stream();
106
+ }
107
+ stream_count += 1;
108
+ return stream_count === 1
109
+ ? create_tool_call_stream()
110
+ : create_final_text_stream();
111
+ },
112
+ doGenerate: async () => ({
113
+ content: [{ type: "text", text: "Approval test" }],
114
+ finishReason: { unified: "stop", raw: "stop" },
115
+ usage: create_usage(),
116
+ warnings: [],
117
+ }),
118
+ });
119
+ const agent = new Agent({
120
+ id: "session_shell_approval_agent",
121
+ path: project_root,
122
+ model,
123
+ shell: new Shell(),
124
+ });
125
+
126
+ try {
127
+ const session = await agent.sessions.create({
128
+ sessionId: "session_shell_approval",
129
+ });
130
+ let approval_snapshot;
131
+ let approval_result;
132
+ const unsubscribe = session.subscribe((mutation) => {
133
+ if (
134
+ mutation.variant !== "part" ||
135
+ mutation.type !== "tool" ||
136
+ mutation.part.state !== "approval-required" ||
137
+ !mutation.part.approval
138
+ ) return;
139
+ approval_snapshot = mutation.part.approval;
140
+ approval_result = session.resolve_approval({
141
+ approval_id: mutation.part.approval.approval_id,
142
+ decision: "approved",
143
+ });
144
+ });
145
+
146
+ const turn = await session.prompt({ query: "run unrestricted command" });
147
+ const result = await turn.finished;
148
+ unsubscribe();
149
+
150
+ assert.equal(result.success, true, result.error);
151
+ assert.equal(stream_count, 2);
152
+ const messages = await session.messages();
153
+ const tool_part = messages.items
154
+ .flatMap((message) => message.type === "assistant" ? message.parts : [])
155
+ .find((part) => part.type === "tool" && part.tool_call_id === "call_unrestricted");
156
+ assert.ok(approval_snapshot, JSON.stringify(messages.items));
157
+ assert.equal(approval_snapshot.session_id, session.id);
158
+ assert.equal(approval_snapshot.turn_id, turn.id);
159
+ assert.equal(approval_snapshot.tool_call_id, "call_unrestricted");
160
+ assert.deepEqual(await approval_result, {
161
+ success: true,
162
+ approval_id: approval_snapshot.approval_id,
163
+ decision: "approved",
164
+ });
165
+ assert.equal(tool_part?.state, "completed");
166
+ assert.equal(tool_part?.output?.output, "approval-ok");
167
+ } finally {
168
+ await agent.dispose();
169
+ await fs.rm(project_root, { recursive: true, force: true });
170
+ }
171
+ });
@@ -9,8 +9,8 @@
9
9
  import test from "node:test";
10
10
  import assert from "node:assert/strict";
11
11
 
12
- import { createInstructionSystemBlocks } from "../bin/agent/local/AgentInstructions.js";
13
- import { buildSessionSystemBlocks } from "../bin/session/SessionSystemBuilder.js";
12
+ import { createInstructionSystemBlocks } from "../bin/agent/AgentInstructions.js";
13
+ import { build_session_system_blocks } from "../bin/session/SessionSystem.js";
14
14
 
15
15
  test("instruction blocks keep Downcity core after custom instruction", () => {
16
16
  const blocks = createInstructionSystemBlocks(
@@ -37,19 +37,19 @@ test("instruction blocks keep Downcity core after custom instruction", () => {
37
37
  });
38
38
 
39
39
  test("session system blocks are ordered as instruction, core, plugin, session", async () => {
40
- const blocks = await buildSessionSystemBlocks({
41
- agentId: "agent-test",
42
- projectRoot: "/tmp/downcity-project",
43
- sessionId: "session-test",
44
- createdAt: Date.UTC(2026, 6, 9, 8, 0, 0),
40
+ const blocks = await build_session_system_blocks({
41
+ agent_id: "agent-test",
42
+ project_root: "/tmp/downcity-project",
43
+ session_id: "session-test",
44
+ created_at: Date.UTC(2026, 6, 9, 8, 0, 0),
45
45
  timezone: "Asia/Shanghai",
46
- getInstructionSystemBlocks: () =>
46
+ get_instruction_system_blocks: () =>
47
47
  createInstructionSystemBlocks(
48
48
  ["使用中文回复。"],
49
49
  "/tmp/downcity-project",
50
50
  ),
51
- getManagedPluginSystemBlocks: async () => [],
52
- getPluginSystemBlocks: async () => [
51
+ get_managed_plugin_system_blocks: async () => [],
52
+ get_plugin_system_blocks: async () => [
53
53
  {
54
54
  source: "plugin",
55
55
  name: "task",
@@ -133,6 +133,7 @@ test("Session logs title generation failure without blocking the session", async
133
133
  model: create_failing_title_model(),
134
134
  });
135
135
  const session = await agent.sessions.create();
136
+ await session.set({ model: create_failing_title_model() });
136
137
 
137
138
  try {
138
139
  await session.append_user_message({