@downcity/agent 1.1.238 → 1.1.259

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 +38 -45
  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 +133 -0
  137. package/bin/session/SessionMessages.d.ts.map +1 -0
  138. package/bin/session/{recorder/SessionRecorder.js → SessionMessages.js} +247 -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} +245 -93
  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 +62 -86
  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} +324 -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,24 +8,57 @@ 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
- async function create_recorder(session_id = "session-recorder-test") {
18
+ /** 可暂停一次 Assistant 草稿写入,用于稳定复现并发写入顺序。 */
19
+ class PausingAssistantMessageStore extends JsonlSessionMessageStore {
20
+ next_assistant_write = null;
21
+
22
+ pause_next_assistant_write() {
23
+ let mark_started;
24
+ let release;
25
+ const started = new Promise((resolve) => {
26
+ mark_started = resolve;
27
+ });
28
+ const wait = new Promise((resolve) => {
29
+ release = resolve;
30
+ });
31
+ this.next_assistant_write = { mark_started, wait };
32
+ return { started, release };
33
+ }
34
+
35
+ async write_assistant_message(message) {
36
+ const pending = this.next_assistant_write;
37
+ if (pending) {
38
+ this.next_assistant_write = null;
39
+ pending.mark_started();
40
+ await pending.wait;
41
+ }
42
+ await super.write_assistant_message(message);
43
+ }
44
+ }
45
+
46
+ async function create_recorder(
47
+ session_id = "session-recorder-test",
48
+ create_store = (options) => new JsonlSessionMessageStore(options),
49
+ ) {
18
50
  const root_path = await fs.mkdtemp(path.join(os.tmpdir(), "downcity-session-recorder-"));
19
51
  const file_path = path.join(root_path, "active.jsonl");
20
52
  const assistant_message_file_path = path.join(root_path, "assistant_message.json");
21
53
  const events = [];
22
- const recorder = new SessionRecorder({
54
+ const store = create_store({ session_id, file_path });
55
+ const recorder = new SessionMessages({
23
56
  session_id,
24
- store: new JsonlSessionMessageStore({ session_id, file_path }),
57
+ store,
25
58
  publish: (mutation) => events.push(mutation),
26
59
  });
27
60
  await recorder.initialize();
28
- return { recorder, events, file_path, assistant_message_file_path };
61
+ return { recorder, store, events, file_path, assistant_message_file_path };
29
62
  }
30
63
 
31
64
  async function read_jsonl(file_path) {
@@ -41,7 +74,7 @@ async function create_seeded_recorder(session_id, messages) {
41
74
  `${messages.map((message) => JSON.stringify(message)).join("\n")}\n`,
42
75
  "utf8",
43
76
  );
44
- const recorder = new SessionRecorder({
77
+ const recorder = new SessionMessages({
45
78
  session_id,
46
79
  store: new JsonlSessionMessageStore({ session_id, file_path }),
47
80
  publish: () => {},
@@ -50,6 +83,20 @@ async function create_seeded_recorder(session_id, messages) {
50
83
  return { recorder, file_path };
51
84
  }
52
85
 
86
+ async function compact_messages(recorder, session_id, model) {
87
+ const plan = await compose_session_compaction({
88
+ session_id,
89
+ snapshot: await recorder.context_snapshot(),
90
+ model,
91
+ });
92
+ if (!plan) return false;
93
+ await recorder.compact_active({
94
+ through_sequence: plan.through_sequence,
95
+ summary: plan.summary,
96
+ });
97
+ return true;
98
+ }
99
+
53
100
  function create_seeded_user_message(session_id, sequence) {
54
101
  return {
55
102
  message_id: `user-${String(sequence)}`,
@@ -110,26 +157,42 @@ test("delta 只更新 Assistant 草稿,完成后才写入 active.jsonl", async
110
157
  assert.equal(history.some((value) => "variant" in value), false);
111
158
  });
112
159
 
113
- test("Tool Part 在文本中间创建后,输入、审批和输出都保持原顺序", async () => {
160
+ test("Tool Runtime 在文本中间保持输入、审批和输出的确定顺序", async () => {
114
161
  const { recorder, events, file_path } = await create_recorder("tool-order-test");
162
+ const approval_broker = new SessionApprovalBroker({
163
+ session_id: "tool-order-test",
164
+ messages: recorder,
165
+ });
115
166
  const writer = await recorder.open_assistant_message({ turn_id: "turn-1", segment_index: 1 });
116
167
  await writer.apply_chunk({ type: "text-start", id: "text-1" });
117
168
  await writer.apply_chunk({ type: "text-delta", id: "text-1", delta: "before" });
118
169
  await writer.apply_chunk({ type: "text-end", id: "text-1" });
119
- await writer.apply_chunk({ type: "tool-input-start", toolCallId: "call-1", toolName: "search" });
170
+ await writer.apply_chunk({ type: "tool-input-start", toolCallId: "call-1", toolName: "shell_exec" });
120
171
  await writer.apply_chunk({
121
172
  type: "tool-input-available",
122
173
  toolCallId: "call-1",
123
- toolName: "search",
124
- input: { query: "downcity" },
174
+ toolName: "shell_exec",
175
+ input: { cmd: "pwd", sandbox: "unrestricted", reason: "Inspect directory" },
125
176
  });
126
177
  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",
178
+ const approval_handle = await approval_broker.request({
179
+ shell_id: "shell-1",
180
+ tool_call_id: "call-1",
181
+ tool_name: "shell_exec",
182
+ session_id: "tool-order-test",
183
+ turn_id: "turn-1",
184
+ command: "pwd",
185
+ cwd: "/workspace",
186
+ reason: "Inspect directory",
187
+ operation: "exec",
188
+ timeout_ms: 60_000,
131
189
  });
132
190
  assert.equal(recorder.get_message(writer.message_id).parts[1].state, "approval-required");
191
+ await approval_broker.resolve({
192
+ approval_id: approval_handle.approval_id,
193
+ decision: "approved",
194
+ });
195
+ assert.equal(await approval_handle.decision, "approved");
133
196
  await writer.apply_chunk({ type: "text-start", id: "text-2" });
134
197
  await writer.apply_chunk({ type: "text-delta", id: "text-2", delta: "after" });
135
198
  await writer.apply_chunk({ type: "text-end", id: "text-2" });
@@ -145,10 +208,158 @@ test("Tool Part 在文本中间创建后,输入、审批和输出都保持原
145
208
  events
146
209
  .filter((event) => event.variant === "part" && event.type === "tool")
147
210
  .map((event) => [event.part.sequence, event.part.state]),
148
- [[2, "input-streaming"], [2, "ready"], [2, "approval-required"], [2, "completed"]],
211
+ [
212
+ [2, "input-streaming"],
213
+ [2, "ready"],
214
+ [2, "approval-required"],
215
+ [2, "running"],
216
+ [2, "completed"],
217
+ ],
218
+ );
219
+ });
220
+
221
+ test("Approval Broker 只接受已经准备完整输入的 Tool", async () => {
222
+ const { recorder, events } = await create_recorder("tool-ready-barrier-test");
223
+ const approval_broker = new SessionApprovalBroker({
224
+ session_id: "tool-ready-barrier-test",
225
+ messages: recorder,
226
+ });
227
+ const writer = await recorder.open_assistant_message({
228
+ turn_id: "turn-ready-barrier",
229
+ segment_index: 1,
230
+ });
231
+ const approval_input = {
232
+ shell_id: "shell-ready-barrier",
233
+ tool_call_id: "call-ready-barrier",
234
+ tool_name: "shell_exec",
235
+ session_id: "tool-ready-barrier-test",
236
+ turn_id: "turn-ready-barrier",
237
+ command: "ls -la /Users/example/Desktop",
238
+ cwd: "/workspace",
239
+ reason: "Inspect requested desktop files",
240
+ operation: "exec",
241
+ timeout_ms: 60_000,
242
+ };
243
+ await assert.rejects(
244
+ approval_broker.request(approval_input),
245
+ /Streaming Tool Part not found/,
246
+ );
247
+ assert.equal(approval_broker.list().length, 0);
248
+
249
+ await writer.prepare_tool_input({
250
+ tool_call_id: "call-ready-barrier",
251
+ tool_name: "shell_exec",
252
+ input: {
253
+ cmd: "ls -la /Users/example/Desktop",
254
+ sandbox: "unrestricted",
255
+ reason: "Inspect requested desktop files",
256
+ },
257
+ });
258
+ const approval_handle = await approval_broker.request(approval_input);
259
+
260
+ const tool = recorder.get_message(writer.message_id).parts[0];
261
+ assert.equal(tool.state, "approval-required");
262
+ assert.equal(tool.approval.approval_id, approval_handle.approval_id);
263
+ assert.equal(tool.approval.command, approval_input.command);
264
+ assert.equal(tool.input.cmd, "ls -la /Users/example/Desktop");
265
+ await approval_broker.resolve({
266
+ approval_id: approval_handle.approval_id,
267
+ decision: "denied",
268
+ });
269
+ assert.equal(await approval_handle.decision, "denied");
270
+ await writer.apply_chunk({
271
+ type: "tool-output-available",
272
+ toolCallId: "call-ready-barrier",
273
+ output: { success: false, approval_status: "denied" },
274
+ });
275
+ assert.equal(recorder.get_message(writer.message_id).parts[0].state, "failed");
276
+ assert.deepEqual(
277
+ events
278
+ .filter((event) => event.variant === "part" && event.type === "tool")
279
+ .map((event) => event.part.state),
280
+ ["ready", "approval-required", "failed"],
149
281
  );
150
282
  });
151
283
 
284
+ test("流式更新与 Approval 共享 Assistant revision 写队列", async () => {
285
+ const session_id = "approval-revision-queue-test";
286
+ const { recorder, store, events } = await create_recorder(
287
+ session_id,
288
+ (options) => new PausingAssistantMessageStore(options),
289
+ );
290
+ const approval_broker = new SessionApprovalBroker({ session_id, messages: recorder });
291
+ const writer = await recorder.open_assistant_message({
292
+ turn_id: "turn-approval-race",
293
+ segment_index: 1,
294
+ });
295
+ await writer.prepare_tool_input({
296
+ tool_call_id: "call-approval-race",
297
+ tool_name: "shell_exec",
298
+ input: {
299
+ cmd: "ls -la ~",
300
+ sandbox: "unrestricted",
301
+ reason: "验证审批写入顺序",
302
+ },
303
+ });
304
+ await writer.apply_chunk({ type: "text-start", id: "text-race" });
305
+ await writer.apply_chunk({ type: "text-delta", id: "text-race", delta: "准备执行" });
306
+
307
+ const gate = store.pause_next_assistant_write();
308
+ const stream_write = writer.apply_chunk({
309
+ type: "text-delta",
310
+ id: "text-race",
311
+ delta: "命令",
312
+ });
313
+ await gate.started;
314
+ const approval_write = approval_broker.request({
315
+ shell_id: "shell-approval-race",
316
+ tool_call_id: "call-approval-race",
317
+ tool_name: "shell_exec",
318
+ session_id,
319
+ turn_id: "turn-approval-race",
320
+ command: "ls -la ~",
321
+ cwd: "/workspace",
322
+ reason: "验证审批写入顺序",
323
+ operation: "exec",
324
+ timeout_ms: 60_000,
325
+ });
326
+
327
+ // 让 Approval 路径有机会进入写入;旧实现会在这里基于同一 revision 提交。
328
+ await new Promise((resolve) => setImmediate(resolve));
329
+ gate.release();
330
+ const [, approval_handle] = await Promise.all([stream_write, approval_write]);
331
+
332
+ const assistant = recorder.get_message(writer.message_id);
333
+ const tool = assistant.parts.find((part) => part.type === "tool");
334
+ const text_part = assistant.parts.find((part) => part.type === "text");
335
+ assert.equal(assistant.revision, 6);
336
+ assert.equal(tool.state, "approval-required");
337
+ assert.equal(tool.approval.approval_id, approval_handle.approval_id);
338
+ assert.equal(tool.input.cmd, "ls -la ~");
339
+ assert.equal(text_part.text, "准备执行命令");
340
+ assert.deepEqual(
341
+ events
342
+ .filter((event) => event.message_id === writer.message_id)
343
+ .map((event) => event.revision),
344
+ [1, 2, 3, 4, 5, 6],
345
+ );
346
+ assert.equal(
347
+ events.some(
348
+ (event) =>
349
+ event.variant === "part" &&
350
+ event.type === "tool" &&
351
+ event.part.state === "approval-required",
352
+ ),
353
+ true,
354
+ );
355
+
356
+ await approval_broker.resolve({
357
+ approval_id: approval_handle.approval_id,
358
+ decision: "denied",
359
+ });
360
+ assert.equal(await approval_handle.decision, "denied");
361
+ });
362
+
152
363
  test("不同模型 step 重复使用 Text chunk ID 时仍保持真实 Part 顺序", async () => {
153
364
  const { recorder, file_path } = await create_recorder("reused-text-id-order-test");
154
365
  const writer = await recorder.open_assistant_message({ turn_id: "turn-1", segment_index: 1 });
@@ -248,7 +459,7 @@ test("重启时将 Assistant 草稿收口为 stopped,并将运行中 Action
248
459
  await recorder.open_action_message({ message_id: "running-action", action_type: "fork", title: "Forking" });
249
460
 
250
461
  const recovered_events = [];
251
- const recovered = new SessionRecorder({
462
+ const recovered = new SessionMessages({
252
463
  session_id: "recovery-test",
253
464
  store: new JsonlSessionMessageStore({ session_id: "recovery-test", file_path }),
254
465
  publish: (mutation) => recovered_events.push(mutation),
@@ -292,7 +503,6 @@ test("compact 把 Active 前缀关闭为带累计 Summary 的 Segment", async ()
292
503
  parts: [{ part_id: `user-${String(index)}`, type: "text", text: `message ${String(index)}`, state: "done" }],
293
504
  });
294
505
  }
295
- const history_store = new SessionRecorderHistoryStore({ session_id: "compact-test", recorder });
296
506
  const model = new MockLanguageModelV3({
297
507
  modelId: "compact-model",
298
508
  doGenerate: async () => ({
@@ -305,12 +515,7 @@ test("compact 把 Active 前缀关闭为带累计 Summary 的 Segment", async ()
305
515
  warnings: [],
306
516
  }),
307
517
  });
308
- const result = await history_store.compact({
309
- model,
310
- system: [],
311
- force: true,
312
- });
313
- assert.equal(result.compacted, true);
518
+ assert.equal(await compact_messages(recorder, "compact-test", model), true);
314
519
  assert.equal((await fs.readFile(file_path, "utf8")).includes("message 1"), false);
315
520
  const active = await recorder.list_messages({ include_internal: true });
316
521
  assert.deepEqual(active.items.map((message) => message.sequence), []);
@@ -322,7 +527,10 @@ test("compact 把 Active 前缀关闭为带累计 Summary 的 Segment", async ()
322
527
  });
323
528
  assert.deepEqual(segment.items.map((message) => message.sequence), [1, 2, 3, 4, 5, 6]);
324
529
  assert.equal(segment.source, "segment");
325
- assert.equal((await history_store.list_records()).length, 1);
530
+ assert.equal(
531
+ to_executor_history("compact-test", await recorder.context_snapshot()).length,
532
+ 1,
533
+ );
326
534
  await assert.rejects(
327
535
  recorder.list_messages({ before_sequence: 0 }),
328
536
  /before_sequence must be a positive integer/,
@@ -356,14 +564,13 @@ test("重启后从最新 Segment Summary 与 Active 恢复模型上下文", asyn
356
564
  },
357
565
  });
358
566
 
359
- const restarted = new SessionRecorder({
567
+ const restarted = new SessionMessages({
360
568
  session_id,
361
569
  store: new JsonlSessionMessageStore({ session_id, file_path }),
362
570
  publish: () => {},
363
571
  });
364
572
  await restarted.initialize();
365
- const context_store = new SessionRecorderHistoryStore({ session_id, recorder: restarted });
366
- const context = await context_store.list_records();
573
+ const context = to_executor_history(session_id, await restarted.context_snapshot());
367
574
  assert.deepEqual(
368
575
  context.map((message) => message.parts[0]?.text),
369
576
  ["summary through 4", "message 5", "message 6"],
@@ -414,7 +621,7 @@ test("Compact 两步提交中断后会清理 Active 与 Segment 的重叠前缀"
414
621
  "utf8",
415
622
  );
416
623
 
417
- const restarted = new SessionRecorder({
624
+ const restarted = new SessionMessages({
418
625
  session_id,
419
626
  store: new JsonlSessionMessageStore({ session_id, file_path }),
420
627
  publish: () => {},
@@ -449,7 +656,6 @@ test("连续 Compact 生成按 sequence 连续的 Segment 与累计 Summary", as
449
656
  };
450
657
  },
451
658
  });
452
- const history_store = new SessionRecorderHistoryStore({ session_id, recorder });
453
659
  const append_messages = async (start, end) => {
454
660
  for (let index = start; index <= end; index += 1) {
455
661
  await recorder.append_user_message({
@@ -464,16 +670,12 @@ test("连续 Compact 生成按 sequence 连续的 Segment 与累计 Summary", as
464
670
  });
465
671
  }
466
672
  };
467
- const compact = async () => await history_store.compact({
468
- model,
469
- system: [],
470
- force: true,
471
- });
673
+ const compact = async () => await compact_messages(recorder, session_id, model);
472
674
 
473
675
  await append_messages(1, 8);
474
- assert.equal((await compact()).compacted, true);
676
+ assert.equal(await compact(), true);
475
677
  await append_messages(9, 12);
476
- assert.equal((await compact()).compacted, true);
678
+ assert.equal(await compact(), true);
477
679
 
478
680
  assert.equal(prompts.length, 2);
479
681
  assert.equal(prompts[1].includes("<previous-summary>"), true);
@@ -487,7 +689,7 @@ test("连续 Compact 生成按 sequence 连续的 Segment 与累计 Summary", as
487
689
  before_sequence: latest_segment.start_sequence,
488
690
  });
489
691
  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();
692
+ const context = to_executor_history(session_id, await recorder.context_snapshot());
491
693
  assert.equal(context[0].parts[0]?.text, "Summary 2");
492
694
  });
493
695
 
@@ -512,14 +714,7 @@ test("Summary 生成失败时使用确定性 Summary 完成归档", async () =>
512
714
  throw new Error("summary unavailable");
513
715
  },
514
716
  });
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 });
717
+ assert.equal(await compact_messages(recorder, session_id, model), true);
523
718
  assert.deepEqual((await recorder.list_messages()).items, []);
524
719
  const segment_entries = await fs.readdir(path.join(path.dirname(file_path), "segments"));
525
720
  assert.equal(segment_entries.length, 1);
@@ -554,52 +749,9 @@ test("内部上下文读取完整快照并保留第 500 条之后的最新消息
554
749
  assert.equal(previous.start_sequence, 1);
555
750
  assert.equal(previous.end_sequence, 499);
556
751
 
557
- const history_store = new SessionRecorderHistoryStore({ session_id, recorder });
558
- const context = await history_store.list_records();
752
+ const context = to_executor_history(session_id, await recorder.context_snapshot());
559
753
  assert.deepEqual(
560
754
  context.map((message) => message.parts[0]?.text),
561
755
  ["summary through 499", "message 500", "message 501"],
562
756
  );
563
757
  });
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
+ });