@downcity/agent 1.1.199 → 1.1.202

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 (247) hide show
  1. package/bin/agent/local/Agent.d.ts +3 -7
  2. package/bin/agent/local/Agent.d.ts.map +1 -1
  3. package/bin/agent/local/Agent.js +14 -19
  4. package/bin/agent/local/Agent.js.map +1 -1
  5. package/bin/agent/local/services/{AgentSessionManager.d.ts → AgentSessions.d.ts} +12 -17
  6. package/bin/agent/local/services/AgentSessions.d.ts.map +1 -0
  7. package/bin/agent/local/services/{AgentSessionManager.js → AgentSessions.js} +11 -26
  8. package/bin/agent/local/services/AgentSessions.js.map +1 -0
  9. package/bin/agent/remote/RemoteAgent.d.ts +2 -9
  10. package/bin/agent/remote/RemoteAgent.d.ts.map +1 -1
  11. package/bin/agent/remote/RemoteAgent.js +40 -22
  12. package/bin/agent/remote/RemoteAgent.js.map +1 -1
  13. package/bin/agent/remote/RemoteSession.d.ts +5 -5
  14. package/bin/agent/remote/RemoteSession.d.ts.map +1 -1
  15. package/bin/agent/remote/RemoteSession.js +5 -3
  16. package/bin/agent/remote/RemoteSession.js.map +1 -1
  17. package/bin/agent/remote/RemoteTransport.d.ts +2 -2
  18. package/bin/agent/remote/transports/HttpRemoteAgentTransport.d.ts +2 -2
  19. package/bin/agent/remote/transports/HttpRemoteAgentTransport.js +5 -5
  20. package/bin/agent/remote/transports/RpcRemoteAgentTransport.d.ts +2 -2
  21. package/bin/agent/remote/transports/RpcRemoteAgentTransport.js +2 -2
  22. package/bin/executor/Executor.d.ts +7 -7
  23. package/bin/executor/Executor.d.ts.map +1 -1
  24. package/bin/executor/Executor.js +41 -33
  25. package/bin/executor/Executor.js.map +1 -1
  26. package/bin/executor/SessionRunScope.d.ts +1 -1
  27. package/bin/executor/SessionRunScope.d.ts.map +1 -1
  28. package/bin/executor/composer/compaction/SessionCompactionComposer.d.ts +5 -5
  29. package/bin/executor/composer/compaction/SessionCompactionComposer.d.ts.map +1 -1
  30. package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionComposer.js +1 -1
  31. package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionComposer.js.map +1 -1
  32. package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionExecutor.d.ts +4 -5
  33. package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionExecutor.d.ts.map +1 -1
  34. package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionExecutor.js +73 -40
  35. package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionExecutor.js.map +1 -1
  36. package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionFileOperations.d.ts +27 -0
  37. package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionFileOperations.d.ts.map +1 -0
  38. package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionFileOperations.js +181 -0
  39. package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionFileOperations.js.map +1 -0
  40. package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionPrompts.d.ts +45 -0
  41. package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionPrompts.d.ts.map +1 -0
  42. package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionPrompts.js +144 -0
  43. package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionPrompts.js.map +1 -0
  44. package/bin/executor/composer/context/LocalSessionContextComposer.d.ts +3 -3
  45. package/bin/executor/composer/context/LocalSessionContextComposer.d.ts.map +1 -1
  46. package/bin/executor/composer/context/SessionContextComposer.d.ts +3 -3
  47. package/bin/executor/composer/context/SessionContextComposer.d.ts.map +1 -1
  48. package/bin/executor/composer/history/SessionHistoryComposer.d.ts +2 -2
  49. package/bin/executor/composer/history/SessionHistoryComposer.d.ts.map +1 -1
  50. package/bin/executor/composer/history/SessionHistoryWriter.d.ts +5 -5
  51. package/bin/executor/composer/history/SessionHistoryWriter.d.ts.map +1 -1
  52. package/bin/executor/composer/history/SessionHistoryWriter.js +6 -6
  53. package/bin/executor/composer/history/SessionHistoryWriter.js.map +1 -1
  54. package/bin/executor/composer/history/jsonl/JsonlSessionHistoryComposer.d.ts +2 -2
  55. package/bin/executor/composer/history/jsonl/JsonlSessionHistoryComposer.d.ts.map +1 -1
  56. package/bin/executor/composer/history/jsonl/JsonlSessionHistoryComposer.js +5 -4
  57. package/bin/executor/composer/history/jsonl/JsonlSessionHistoryComposer.js.map +1 -1
  58. package/bin/executor/core-engine/CoreEngineMessageState.d.ts +5 -5
  59. package/bin/executor/core-engine/CoreEngineMessageState.d.ts.map +1 -1
  60. package/bin/executor/core-engine/CoreEngineMessageState.js.map +1 -1
  61. package/bin/executor/core-engine/CoreEngineRunner.js.map +1 -1
  62. package/bin/executor/core-engine/CoreEngineSignals.d.ts +4 -4
  63. package/bin/executor/core-engine/CoreEngineSignals.d.ts.map +1 -1
  64. package/bin/executor/core-engine/CoreEngineSignals.js.map +1 -1
  65. package/bin/executor/core-engine/CoreEngineUiStreamCollector.d.ts +3 -3
  66. package/bin/executor/core-engine/CoreEngineUiStreamCollector.d.ts.map +1 -1
  67. package/bin/executor/core-engine/CoreEngineUiStreamCollector.js.map +1 -1
  68. package/bin/executor/messages/AssistantResultPersistence.d.ts +5 -5
  69. package/bin/executor/messages/AssistantResultPersistence.d.ts.map +1 -1
  70. package/bin/executor/messages/AssistantResultPersistence.js +1 -1
  71. package/bin/executor/messages/AssistantResultPersistence.js.map +1 -1
  72. package/bin/executor/messages/SessionAttachmentMapper.d.ts +3 -3
  73. package/bin/executor/messages/SessionAttachmentMapper.d.ts.map +1 -1
  74. package/bin/executor/messages/SessionAttachmentMapper.js.map +1 -1
  75. package/bin/executor/messages/SessionMessageCodec.d.ts +4 -4
  76. package/bin/executor/messages/SessionMessageCodec.d.ts.map +1 -1
  77. package/bin/executor/messages/SessionMessageCodec.js +5 -5
  78. package/bin/executor/messages/SessionMessageCodec.js.map +1 -1
  79. package/bin/executor/messages/SessionMessageLog.d.ts +3 -3
  80. package/bin/executor/messages/SessionMessageLog.d.ts.map +1 -1
  81. package/bin/executor/messages/SessionMessageLog.js.map +1 -1
  82. package/bin/executor/messages/SessionStepEventMapper.d.ts +2 -2
  83. package/bin/executor/messages/SessionStepEventMapper.d.ts.map +1 -1
  84. package/bin/executor/messages/SessionStepEventMapper.js.map +1 -1
  85. package/bin/executor/messages/UserVisibleText.d.ts +3 -3
  86. package/bin/executor/messages/UserVisibleText.d.ts.map +1 -1
  87. package/bin/executor/messages/UserVisibleText.js +3 -3
  88. package/bin/executor/messages/UserVisibleText.js.map +1 -1
  89. package/bin/executor/services/ExecutorInflightService.d.ts +2 -2
  90. package/bin/executor/services/ExecutorInflightService.d.ts.map +1 -1
  91. package/bin/executor/services/ExecutorInflightService.js +11 -7
  92. package/bin/executor/services/ExecutorInflightService.js.map +1 -1
  93. package/bin/executor/store/history/SessionHistoryStore.d.ts +30 -27
  94. package/bin/executor/store/history/SessionHistoryStore.d.ts.map +1 -1
  95. package/bin/executor/store/history/SessionHistoryStore.js +3 -3
  96. package/bin/executor/store/history/jsonl/JsonlSessionHistoryStore.d.ts +21 -20
  97. package/bin/executor/store/history/jsonl/JsonlSessionHistoryStore.d.ts.map +1 -1
  98. package/bin/executor/store/history/jsonl/JsonlSessionHistoryStore.js +114 -72
  99. package/bin/executor/store/history/jsonl/JsonlSessionHistoryStore.js.map +1 -1
  100. package/bin/executor/tools/plugin/PluginToolDefinition.d.ts +1 -7
  101. package/bin/executor/tools/plugin/PluginToolDefinition.d.ts.map +1 -1
  102. package/bin/executor/tools/plugin/PluginToolSchemas.d.ts +4 -6
  103. package/bin/executor/tools/plugin/PluginToolSchemas.d.ts.map +1 -1
  104. package/bin/executor/tools/plugin/PluginToolSchemas.js +24 -10
  105. package/bin/executor/tools/plugin/PluginToolSchemas.js.map +1 -1
  106. package/bin/executor/types/SessionRecords.d.ts +162 -0
  107. package/bin/executor/types/SessionRecords.d.ts.map +1 -0
  108. package/bin/executor/types/SessionRecords.js +52 -0
  109. package/bin/executor/types/SessionRecords.js.map +1 -0
  110. package/bin/executor/types/SessionRun.d.ts +3 -3
  111. package/bin/executor/types/SessionRun.d.ts.map +1 -1
  112. package/bin/index.d.ts +2 -2
  113. package/bin/index.d.ts.map +1 -1
  114. package/bin/index.js.map +1 -1
  115. package/bin/rpc/Client.d.ts +5 -5
  116. package/bin/rpc/Client.js +4 -4
  117. package/bin/session/Session.d.ts +6 -6
  118. package/bin/session/Session.d.ts.map +1 -1
  119. package/bin/session/Session.js +8 -8
  120. package/bin/session/Session.js.map +1 -1
  121. package/bin/session/SessionTitle.d.ts +2 -2
  122. package/bin/session/SessionTitle.d.ts.map +1 -1
  123. package/bin/session/SessionTitle.js +5 -0
  124. package/bin/session/SessionTitle.js.map +1 -1
  125. package/bin/session/browse/Browse.d.ts +12 -12
  126. package/bin/session/browse/Browse.d.ts.map +1 -1
  127. package/bin/session/browse/Browse.js +37 -34
  128. package/bin/session/browse/Browse.js.map +1 -1
  129. package/bin/session/index.d.ts +1 -1
  130. package/bin/session/index.js +1 -1
  131. package/bin/session/runtime/SessionPromptRuntime.d.ts +3 -3
  132. package/bin/session/runtime/SessionPromptRuntime.d.ts.map +1 -1
  133. package/bin/session/services/SessionStateService.d.ts +11 -12
  134. package/bin/session/services/SessionStateService.d.ts.map +1 -1
  135. package/bin/session/services/SessionStateService.js +43 -69
  136. package/bin/session/services/SessionStateService.js.map +1 -1
  137. package/bin/session/services/SessionTurnService.js +3 -3
  138. package/bin/session/services/SessionTurnService.js.map +1 -1
  139. package/bin/session/services/SessionViewService.d.ts +4 -4
  140. package/bin/session/services/SessionViewService.d.ts.map +1 -1
  141. package/bin/session/services/SessionViewService.js +26 -36
  142. package/bin/session/services/SessionViewService.js.map +1 -1
  143. package/bin/session/storage/Persistence.d.ts +4 -4
  144. package/bin/session/storage/Persistence.d.ts.map +1 -1
  145. package/bin/session/storage/RuntimeSessionPort.d.ts +2 -2
  146. package/bin/session/storage/RuntimeSessionPort.d.ts.map +1 -1
  147. package/bin/session/storage/RuntimeSessionPort.js +4 -4
  148. package/bin/session/storage/RuntimeSessionPort.js.map +1 -1
  149. package/bin/types/agent/AgentTypes.d.ts +2 -2
  150. package/bin/types/agent/AgentTypes.d.ts.map +1 -1
  151. package/bin/types/agent/SessionActor.d.ts +11 -11
  152. package/bin/types/agent/SessionActor.d.ts.map +1 -1
  153. package/bin/types/agent/SessionTypes.d.ts +22 -22
  154. package/bin/types/agent/SessionTypes.d.ts.map +1 -1
  155. package/bin/types/executor/SessionRunContext.d.ts +7 -7
  156. package/bin/types/executor/SessionRunContext.d.ts.map +1 -1
  157. package/bin/types/rpc/RpcProtocol.d.ts +6 -6
  158. package/bin/types/runtime/agent/AgentContext.d.ts +7 -7
  159. package/bin/types/runtime/agent/AgentContext.d.ts.map +1 -1
  160. package/bin/types/sdk/AgentSessionAction.d.ts +26 -0
  161. package/bin/types/sdk/AgentSessionAction.d.ts.map +1 -0
  162. package/bin/types/sdk/AgentSessionAction.js +10 -0
  163. package/bin/types/sdk/AgentSessionAction.js.map +1 -0
  164. package/bin/types/sdk/AgentSessionEvent.d.ts +2 -2
  165. package/bin/types/sdk/AgentSessionEvent.d.ts.map +1 -1
  166. package/bin/types/sdk/AgentSessionTurn.d.ts +2 -2
  167. package/bin/types/sdk/AgentSessionTurn.d.ts.map +1 -1
  168. package/package.json +3 -3
  169. package/scripts/agent-ready.test.mjs +1 -1
  170. package/scripts/city-model-tool-loop.test.mjs +36 -4
  171. package/scripts/plugin-tool-bridge.test.mjs +13 -0
  172. package/scripts/session-action-message.test.mjs +199 -0
  173. package/scripts/session-compaction-prompts.test.mjs +97 -0
  174. package/scripts/session-history-archive.test.mjs +8 -8
  175. package/scripts/session-history-inflight.test.mjs +10 -10
  176. package/scripts/session-list-title.test.mjs +9 -9
  177. package/scripts/session-title-event.test.mjs +12 -10
  178. package/src/agent/local/Agent.ts +16 -22
  179. package/src/agent/local/services/{AgentSessionManager.ts → AgentSessions.ts} +16 -32
  180. package/src/agent/remote/RemoteAgent.ts +58 -23
  181. package/src/agent/remote/RemoteSession.ts +10 -8
  182. package/src/agent/remote/RemoteTransport.ts +5 -5
  183. package/src/agent/remote/transports/HttpRemoteAgentTransport.ts +10 -10
  184. package/src/agent/remote/transports/RpcRemoteAgentTransport.ts +6 -6
  185. package/src/executor/Executor.ts +51 -41
  186. package/src/executor/SessionRunScope.ts +1 -1
  187. package/src/executor/composer/compaction/SessionCompactionComposer.ts +5 -5
  188. package/src/executor/composer/compaction/jsonl/JsonlSessionCompactionComposer.ts +1 -1
  189. package/src/executor/composer/compaction/jsonl/JsonlSessionCompactionExecutor.ts +91 -52
  190. package/src/executor/composer/compaction/jsonl/JsonlSessionCompactionFileOperations.ts +197 -0
  191. package/src/executor/composer/compaction/jsonl/JsonlSessionCompactionPrompts.ts +162 -0
  192. package/src/executor/composer/context/LocalSessionContextComposer.ts +5 -5
  193. package/src/executor/composer/context/SessionContextComposer.ts +5 -5
  194. package/src/executor/composer/history/SessionHistoryComposer.ts +2 -2
  195. package/src/executor/composer/history/SessionHistoryWriter.ts +10 -10
  196. package/src/executor/composer/history/jsonl/JsonlSessionHistoryComposer.ts +13 -10
  197. package/src/executor/core-engine/CoreEngineMessageState.ts +8 -8
  198. package/src/executor/core-engine/CoreEngineRunner.ts +7 -7
  199. package/src/executor/core-engine/CoreEngineSignals.ts +7 -7
  200. package/src/executor/core-engine/CoreEngineUiStreamCollector.ts +5 -5
  201. package/src/executor/messages/AssistantResultPersistence.ts +8 -8
  202. package/src/executor/messages/SessionAttachmentMapper.ts +11 -11
  203. package/src/executor/messages/SessionMessageCodec.ts +10 -10
  204. package/src/executor/messages/SessionMessageLog.ts +3 -3
  205. package/src/executor/messages/SessionStepEventMapper.ts +5 -5
  206. package/src/executor/messages/UserVisibleText.ts +9 -9
  207. package/src/executor/services/ExecutorInflightService.ts +13 -9
  208. package/src/executor/store/history/SessionHistoryStore.ts +32 -28
  209. package/src/executor/store/history/jsonl/JsonlSessionHistoryStore.ts +146 -95
  210. package/src/executor/tools/plugin/PluginToolSchemas.ts +24 -10
  211. package/src/executor/types/SessionRecords.ts +217 -0
  212. package/src/executor/types/SessionRun.ts +5 -5
  213. package/src/index.ts +9 -10
  214. package/src/rpc/Client.ts +9 -9
  215. package/src/session/Session.ts +10 -10
  216. package/src/session/SessionTitle.ts +7 -4
  217. package/src/session/browse/Browse.ts +66 -58
  218. package/src/session/index.ts +1 -1
  219. package/src/session/runtime/SessionPromptRuntime.ts +6 -6
  220. package/src/session/services/SessionStateService.ts +61 -86
  221. package/src/session/services/SessionTurnService.ts +7 -7
  222. package/src/session/services/SessionViewService.ts +35 -45
  223. package/src/session/storage/Persistence.ts +6 -6
  224. package/src/session/storage/RuntimeSessionPort.ts +6 -6
  225. package/src/types/agent/AgentTypes.ts +4 -4
  226. package/src/types/agent/SessionActor.ts +12 -12
  227. package/src/types/agent/SessionTypes.ts +22 -22
  228. package/src/types/executor/SessionRunContext.ts +12 -12
  229. package/src/types/rpc/RpcProtocol.ts +6 -6
  230. package/src/types/runtime/agent/AgentContext.ts +8 -8
  231. package/src/types/sdk/AgentSessionAction.ts +35 -0
  232. package/src/types/sdk/AgentSessionEvent.ts +2 -2
  233. package/src/types/sdk/AgentSessionTurn.ts +2 -2
  234. package/tsconfig.tsbuildinfo +1 -1
  235. package/bin/agent/local/services/AgentSessionManager.d.ts.map +0 -1
  236. package/bin/agent/local/services/AgentSessionManager.js.map +0 -1
  237. package/bin/executor/types/SessionMessages.d.ts +0 -118
  238. package/bin/executor/types/SessionMessages.d.ts.map +0 -1
  239. package/bin/executor/types/SessionMessages.js +0 -28
  240. package/bin/executor/types/SessionMessages.js.map +0 -1
  241. package/bin/types/sdk/AgentSessionOperation.d.ts +0 -99
  242. package/bin/types/sdk/AgentSessionOperation.d.ts.map +0 -1
  243. package/bin/types/sdk/AgentSessionOperation.js +0 -10
  244. package/bin/types/sdk/AgentSessionOperation.js.map +0 -1
  245. package/scripts/session-operation-message.test.mjs +0 -197
  246. package/src/executor/types/SessionMessages.ts +0 -148
  247. package/src/types/sdk/AgentSessionOperation.ts +0 -125
@@ -1,19 +1,19 @@
1
1
  /**
2
- * SessionHistoryStore:会话历史事实源接口。
2
+ * SessionHistoryStore:会话 record 事实源接口。
3
3
  *
4
4
  * 关键点(中文)
5
- * - Store 负责消息、meta、archive、lock 等持久化能力。
6
- * - Composer 只负责把 Store 中的历史组装成本轮模型输入。
5
+ * - Store 负责 records、meta、archive、lock 等持久化能力。
6
+ * - Composer 只负责把 Store 中的模型消息 record 组装成本轮模型输入。
7
7
  * - 这个接口刻意独立于 Composer,避免把“落盘事实源”误当成“组装策略”。
8
8
  */
9
9
 
10
10
  import type { LanguageModel } from "ai";
11
11
  import type {
12
- SessionMessageV1,
12
+ SessionActionRecordV1,
13
+ SessionRecordV1,
13
14
  SessionMetadataV1,
14
- } from "@/executor/types/SessionMessages.js";
15
+ } from "@/executor/types/SessionRecords.js";
15
16
  import type { SessionSystemMessage } from "@/executor/types/SessionPrompts.js";
16
- import type { AgentSessionOperationRecord } from "@/types/sdk/AgentSessionOperation.js";
17
17
 
18
18
  /**
19
19
  * compact 输入参数。
@@ -50,9 +50,9 @@ export type SessionHistoryCompactInput = {
50
50
  compactRatio: number;
51
51
 
52
52
  /**
53
- * 可选 operation 发布回调。
53
+ * 可选 action 发布回调。
54
54
  */
55
- onOperation?: (operation: AgentSessionOperationRecord) => Promise<void>;
55
+ onAction?: (action: SessionActionRecordV1) => Promise<void>;
56
56
  };
57
57
 
58
58
  /**
@@ -65,39 +65,43 @@ export interface SessionHistoryStore {
65
65
  readonly sessionId: string;
66
66
 
67
67
  /**
68
- * 追加一条消息到历史。
68
+ * 写入一条 session record。
69
+ *
70
+ * 说明(中文)
71
+ * - 模型消息会追加到 JSONL。
72
+ * - action record 会按稳定 ID upsert 为同一条 record。
69
73
  */
70
- append(message: SessionMessageV1): Promise<void>;
74
+ write_record(message: SessionRecordV1): Promise<void>;
71
75
 
72
76
  /**
73
77
  * 读取当前运行中的 assistant 快照。
74
78
  */
75
- readInflight(): Promise<SessionMessageV1 | null>;
79
+ read_inflight(): Promise<SessionRecordV1 | null>;
76
80
 
77
81
  /**
78
82
  * 写入当前运行中的 assistant 快照。
79
83
  */
80
- writeInflight(message: SessionMessageV1): Promise<void>;
84
+ write_inflight(message: SessionRecordV1): Promise<void>;
81
85
 
82
86
  /**
83
87
  * 用最终 assistant 收口 inflight 快照。
84
88
  */
85
- finalizeInflight(message?: SessionMessageV1 | null): Promise<void>;
89
+ finalize_inflight(message?: SessionRecordV1 | null): Promise<void>;
86
90
 
87
91
  /**
88
- * 读取完整消息历史。
92
+ * 读取完整 session records。
89
93
  */
90
- list(): Promise<SessionMessageV1[]>;
94
+ list_records(): Promise<SessionRecordV1[]>;
91
95
 
92
96
  /**
93
- * 读取消息区间 [start, end)。
97
+ * 读取 session record 区间 [start, end)。
94
98
  */
95
- slice(start: number, end: number): Promise<SessionMessageV1[]>;
99
+ slice_records(start: number, end: number): Promise<SessionRecordV1[]>;
96
100
 
97
101
  /**
98
- * 读取消息总条数。
102
+ * 读取 session record 总条数。
99
103
  */
100
- size(): Promise<number>;
104
+ record_count(): Promise<number>;
101
105
 
102
106
  /**
103
107
  * 读取元信息。
@@ -131,7 +135,7 @@ export interface SessionHistoryStore {
131
135
  * 可选消息 ID(默认自动生成)。
132
136
  */
133
137
  id?: string;
134
- }): SessionMessageV1;
138
+ }): SessionRecordV1;
135
139
 
136
140
  /**
137
141
  * 构造 assistant 文本消息。
@@ -162,26 +166,26 @@ export interface SessionHistoryStore {
162
166
  * 消息来源(egress/compact)。
163
167
  */
164
168
  source?: "egress" | "compact";
165
- }): SessionMessageV1;
169
+ }): SessionRecordV1;
166
170
 
167
171
  /**
168
- * 构造 operation 消息。
172
+ * 构造 action 消息。
169
173
  */
170
- operation(input: {
174
+ action(input: {
171
175
  /**
172
- * 当前 operation 结构化记录。
176
+ * 当前 action 结构化记录。
173
177
  */
174
- operation: AgentSessionOperationRecord;
178
+ action: SessionActionRecordV1;
175
179
 
176
180
  /**
177
- * 消息元信息(除 schema 字段、kind、source 与 operation 字段)。
181
+ * 消息元信息(除 schema 字段)。
178
182
  */
179
- metadata: Omit<SessionMetadataV1, "v" | "ts" | "kind" | "source" | "operation"> &
183
+ metadata: Pick<SessionMetadataV1, "sessionId"> &
180
184
  Partial<Pick<SessionMetadataV1, "ts">>;
181
185
 
182
186
  /**
183
187
  * 可选消息 ID(默认自动生成)。
184
188
  */
185
189
  id?: string;
186
- }): SessionMessageV1;
190
+ }): SessionActionRecordV1;
187
191
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * JsonlSessionHistoryStore:基于 JSONL 的 session history 事实源。
2
+ * JsonlSessionHistoryStore:基于 JSONL 的 session records 事实源。
3
3
  *
4
4
  * 关键点(中文)
5
5
  * - 负责 `.downcity/.../messages/messages.jsonl`、`meta.json`、archive 与文件锁。
@@ -18,10 +18,15 @@ import { generateId } from "@/utils/Id.js";
18
18
  import { getLogger } from "@/utils/logger/Logger.js";
19
19
  import { compactSessionMessagesIfNeeded } from "@executor/composer/compaction/jsonl/JsonlSessionCompactionExecutor.js";
20
20
  import type {
21
- SessionMessageV1,
21
+ SessionActionRecordV1,
22
+ SessionRecordV1,
22
23
  SessionMetadataV1,
23
- } from "@/executor/types/SessionMessages.js";
24
- import type { AgentSessionOperationRecord } from "@/types/sdk/AgentSessionOperation.js";
24
+ } from "@/executor/types/SessionRecords.js";
25
+ import {
26
+ is_session_action_record,
27
+ is_session_message_record,
28
+ to_session_action_record,
29
+ } from "@/executor/types/SessionRecords.js";
25
30
  import type { SessionSystemMessage } from "@/executor/types/SessionPrompts.js";
26
31
  import type { SessionHistoryMetaV1 } from "@/executor/types/SessionHistoryMeta.js";
27
32
  import type { SessionHistoryPathOverrides } from "@/executor/types/SessionHistoryPaths.js";
@@ -214,19 +219,62 @@ export class JsonlSessionHistoryStore implements SessionHistoryStore {
214
219
 
215
220
  private normalizePersistedMessage(
216
221
  input: unknown,
217
- ): SessionMessageV1 | null {
222
+ ): SessionRecordV1 | null {
218
223
  if (!input || typeof input !== "object") return null;
219
- const candidate = input as Partial<SessionMessageV1>;
224
+ if ((input as { type?: unknown }).type === "action") {
225
+ return this.normalize_action_record(input);
226
+ }
227
+ const candidate = input as { role?: unknown; parts?: unknown };
220
228
  const role = String(candidate.role || "");
221
- if (role !== "user" && role !== "assistant" && role !== "operation") {
229
+ if (role !== "user" && role !== "assistant") {
222
230
  return null;
223
231
  }
224
232
  if (!Array.isArray(candidate.parts)) return null;
225
- return candidate as SessionMessageV1;
233
+ return input as SessionRecordV1;
226
234
  }
227
235
 
228
- private hasStructuredAssistantParts(message: SessionMessageV1 | null): boolean {
229
- if (!message || message.role !== "assistant" || !Array.isArray(message.parts)) {
236
+ private normalize_action_record(input: unknown): SessionActionRecordV1 | null {
237
+ if (!input || typeof input !== "object") return null;
238
+ const candidate = input as Partial<SessionActionRecordV1>;
239
+ const id = String(candidate.id || "").trim();
240
+ const title = String(candidate.title || "").trim();
241
+ const state = String(candidate.state || "").trim();
242
+ if (!id || !title) return null;
243
+ if (state !== "running" && state !== "completed" && state !== "failed") {
244
+ return null;
245
+ }
246
+ const metadata_input =
247
+ candidate.metadata && typeof candidate.metadata === "object"
248
+ ? candidate.metadata
249
+ : {};
250
+ const metadata_candidate = metadata_input as Partial<SessionActionRecordV1["metadata"]>;
251
+ const session_id =
252
+ String(metadata_candidate.sessionId || "").trim() || this.sessionId;
253
+ const description = String(candidate.description || "").trim();
254
+ return {
255
+ type: "action",
256
+ id,
257
+ title,
258
+ ...(description ? { description } : {}),
259
+ state,
260
+ metadata: {
261
+ v: 1,
262
+ ts:
263
+ typeof metadata_candidate.ts === "number"
264
+ ? metadata_candidate.ts
265
+ : Date.now(),
266
+ sessionId: session_id,
267
+ ...(metadata_candidate.turnId ? { turnId: metadata_candidate.turnId } : {}),
268
+ },
269
+ };
270
+ }
271
+
272
+ private hasStructuredAssistantParts(message: SessionRecordV1 | null): boolean {
273
+ if (
274
+ !is_session_message_record(message) ||
275
+ message.role !== "assistant" ||
276
+ !Array.isArray(message.parts)
277
+ ) {
230
278
  return false;
231
279
  }
232
280
  return message.parts.some((part) => {
@@ -237,9 +285,11 @@ export class JsonlSessionHistoryStore implements SessionHistoryStore {
237
285
  }
238
286
 
239
287
  private mergeInflightWithFinal(
240
- inflight: SessionMessageV1,
241
- finalMessage: SessionMessageV1,
242
- ): SessionMessageV1 {
288
+ inflight: SessionRecordV1,
289
+ finalMessage: SessionRecordV1,
290
+ ): SessionRecordV1 {
291
+ if (!is_session_message_record(finalMessage)) return inflight;
292
+ if (!is_session_message_record(inflight)) return finalMessage;
243
293
  const final_parts = Array.isArray(finalMessage.parts)
244
294
  ? finalMessage.parts.filter((part) => part && typeof part === "object")
245
295
  : [];
@@ -345,7 +395,7 @@ export class JsonlSessionHistoryStore implements SessionHistoryStore {
345
395
  await fs.writeJson(this.getMetaFilePath(), normalized, { spaces: 2 });
346
396
  }
347
397
 
348
- private async readInflightUnsafe(): Promise<SessionMessageV1 | null> {
398
+ private async read_inflight_unsafe(): Promise<SessionRecordV1 | null> {
349
399
  const file = this.getInflightFilePath();
350
400
  try {
351
401
  const raw = await fs.readJson(file);
@@ -355,9 +405,12 @@ export class JsonlSessionHistoryStore implements SessionHistoryStore {
355
405
  }
356
406
  }
357
407
 
358
- private async writeInflightUnsafe(message: SessionMessageV1): Promise<void> {
408
+ private async write_inflight_unsafe(message: SessionRecordV1): Promise<void> {
359
409
  const normalized = this.normalizePersistedMessage(message);
360
- if (!normalized || normalized.role !== "assistant") {
410
+ if (
411
+ !is_session_message_record(normalized) ||
412
+ normalized.role !== "assistant"
413
+ ) {
361
414
  throw new Error("inflight assistant must be an assistant UIMessage");
362
415
  }
363
416
  const file = this.getInflightFilePath();
@@ -371,7 +424,7 @@ export class JsonlSessionHistoryStore implements SessionHistoryStore {
371
424
  await fs.remove(this.getInflightFilePath());
372
425
  }
373
426
 
374
- private async appendMessageUnsafe(message: SessionMessageV1): Promise<void> {
427
+ private async appendMessageUnsafe(message: SessionRecordV1): Promise<void> {
375
428
  await fs.appendFile(
376
429
  this.getMessagesFilePath(),
377
430
  JSON.stringify(message) + "\n",
@@ -379,6 +432,44 @@ export class JsonlSessionHistoryStore implements SessionHistoryStore {
379
432
  );
380
433
  }
381
434
 
435
+ private async rewriteMessagesUnsafe(messages: SessionRecordV1[]): Promise<void> {
436
+ const file = this.getMessagesFilePath();
437
+ const temp = `${file}.${process.pid}.${Date.now()}.tmp`;
438
+ const payload =
439
+ messages.length > 0
440
+ ? messages.map((message) => JSON.stringify(message)).join("\n") + "\n"
441
+ : "";
442
+ await fs.writeFile(temp, payload, "utf8");
443
+ await fs.move(temp, file, { overwrite: true });
444
+ }
445
+
446
+ private async upsert_action_record_unsafe(
447
+ message: SessionActionRecordV1,
448
+ ): Promise<void> {
449
+ const file = this.getMessagesFilePath();
450
+ const raw = await fs.readFile(file, "utf8").catch(() => "");
451
+ const messages: SessionRecordV1[] = [];
452
+ let replaced = false;
453
+
454
+ for (const line of raw.split("\n").filter(Boolean)) {
455
+ try {
456
+ const current = this.normalizePersistedMessage(JSON.parse(line));
457
+ if (!current) continue;
458
+ if (is_session_action_record(current) && current.id === message.id) {
459
+ messages.push(message);
460
+ replaced = true;
461
+ continue;
462
+ }
463
+ messages.push(current);
464
+ } catch {
465
+ // 关键点(中文):重写 action 时顺手跳过损坏行,避免坏 JSON 阻断状态更新。
466
+ }
467
+ }
468
+
469
+ if (!replaced) messages.push(message);
470
+ await this.rewriteMessagesUnsafe(messages);
471
+ }
472
+
382
473
  private async withWriteLock<T>(fn: () => Promise<T>): Promise<T> {
383
474
  await this.ensureLayout();
384
475
  const lockPath = this.getLockFilePath();
@@ -438,44 +529,6 @@ export class JsonlSessionHistoryStore implements SessionHistoryStore {
438
529
  return system.filter((item) => item && typeof item === "object");
439
530
  }
440
531
 
441
- private normalizeOperation(
442
- operation: AgentSessionOperationRecord,
443
- ): AgentSessionOperationRecord {
444
- const operation_id = String(operation.operationId || "").trim() || generateId();
445
- const name = String(operation.name || "").trim() || "operation";
446
- const status = String(operation.status || "").trim();
447
- const normalized_status: AgentSessionOperationRecord["status"] =
448
- status === "started" ||
449
- status === "progress" ||
450
- status === "finished" ||
451
- status === "skipped" ||
452
- status === "failed"
453
- ? status
454
- : "progress";
455
- return {
456
- operationId: operation_id,
457
- name,
458
- status: normalized_status,
459
- ...(typeof operation.turnId === "string" && operation.turnId.trim()
460
- ? { turnId: operation.turnId.trim() }
461
- : {}),
462
- ...(typeof operation.label === "string" && operation.label.trim()
463
- ? { label: operation.label.trim() }
464
- : {}),
465
- ...(typeof operation.reason === "string" && operation.reason.trim()
466
- ? { reason: operation.reason.trim() }
467
- : {}),
468
- ...(typeof operation.progress === "number" && Number.isFinite(operation.progress)
469
- ? { progress: Math.max(0, Math.min(1, operation.progress)) }
470
- : {}),
471
- ...(operation.result !== undefined ? { result: operation.result } : {}),
472
- ...(typeof operation.error === "string" && operation.error.trim()
473
- ? { error: operation.error.trim() }
474
- : {}),
475
- ...(operation.visible === false ? { visible: false } : {}),
476
- };
477
- }
478
-
479
532
  async compact(input: SessionHistoryCompactInput): Promise<{
480
533
  compacted: boolean;
481
534
  reason?: string;
@@ -485,7 +538,7 @@ export class JsonlSessionHistoryStore implements SessionHistoryStore {
485
538
  rootPath: this.rootPath,
486
539
  sessionId: this.sessionId,
487
540
  withWriteLock: (fn) => this.withWriteLock(fn),
488
- loadAll: () => this.list(),
541
+ loadAll: () => this.list_records(),
489
542
  createSummaryMessage: ({ text, archiveId, sourceRange }) => ({
490
543
  id: `a:${this.sessionId}:${generateId()}`,
491
544
  role: "assistant",
@@ -512,20 +565,24 @@ export class JsonlSessionHistoryStore implements SessionHistoryStore {
512
565
  maxInputTokensApprox: input.maxInputTokensApprox,
513
566
  archiveOnCompact: input.archiveOnCompact,
514
567
  compactRatio: input.compactRatio,
515
- ...(input.onOperation ? { onOperation: input.onOperation } : {}),
568
+ ...(input.onAction ? { onAction: input.onAction } : {}),
516
569
  },
517
570
  );
518
571
  }
519
572
 
520
- async append(message: SessionMessageV1): Promise<void> {
573
+ async write_record(message: SessionRecordV1): Promise<void> {
521
574
  await this.withWriteLock(async () => {
522
575
  const normalized = this.normalizePersistedMessage(message);
523
576
  if (!normalized) return;
577
+ if (is_session_action_record(normalized)) {
578
+ await this.upsert_action_record_unsafe(normalized);
579
+ return;
580
+ }
524
581
 
525
582
  // 关键点(中文):若上一次 assistant 在运行中中断,新的 user 到来前先把残留快照收口到正式历史,
526
- // 避免 `list()` 时旧 inflight 跑到新 user 后面,打乱时序。
527
- if (normalized.role === "user") {
528
- const current_inflight = await this.readInflightUnsafe();
583
+ // 避免 `list_records()` 时旧 inflight 跑到新 user 后面,打乱时序。
584
+ if (is_session_message_record(normalized) && normalized.role === "user") {
585
+ const current_inflight = await this.read_inflight_unsafe();
529
586
  if (current_inflight) {
530
587
  await this.appendMessageUnsafe(current_inflight);
531
588
  await this.removeInflightUnsafe();
@@ -543,11 +600,11 @@ export class JsonlSessionHistoryStore implements SessionHistoryStore {
543
600
  * - 一次锁、一次 IO,适合 fork 等需要拷贝整段历史的场景。
544
601
  * - 不处理 inflight,调用方需自行确保历史已经收口。
545
602
  */
546
- async appendMany(messages: SessionMessageV1[]): Promise<void> {
603
+ async write_records(messages: SessionRecordV1[]): Promise<void> {
547
604
  if (!Array.isArray(messages) || messages.length === 0) return;
548
605
  const normalized_list = messages
549
606
  .map((message) => this.normalizePersistedMessage(message))
550
- .filter((message): message is SessionMessageV1 => message !== null);
607
+ .filter((message): message is SessionRecordV1 => message !== null);
551
608
  if (normalized_list.length === 0) return;
552
609
 
553
610
  const payload = normalized_list
@@ -558,20 +615,20 @@ export class JsonlSessionHistoryStore implements SessionHistoryStore {
558
615
  });
559
616
  }
560
617
 
561
- async readInflight(): Promise<SessionMessageV1 | null> {
618
+ async read_inflight(): Promise<SessionRecordV1 | null> {
562
619
  await this.ensureLayout();
563
- return this.readInflightUnsafe();
620
+ return this.read_inflight_unsafe();
564
621
  }
565
622
 
566
- async writeInflight(message: SessionMessageV1): Promise<void> {
623
+ async write_inflight(message: SessionRecordV1): Promise<void> {
567
624
  await this.withWriteLock(async () => {
568
- await this.writeInflightUnsafe(message);
625
+ await this.write_inflight_unsafe(message);
569
626
  });
570
627
  }
571
628
 
572
- async finalizeInflight(message?: SessionMessageV1 | null): Promise<void> {
629
+ async finalize_inflight(message?: SessionRecordV1 | null): Promise<void> {
573
630
  await this.withWriteLock(async () => {
574
- const current_inflight = await this.readInflightUnsafe();
631
+ const current_inflight = await this.read_inflight_unsafe();
575
632
  const normalized_message = this.normalizePersistedMessage(message);
576
633
  const final_message =
577
634
  current_inflight && normalized_message
@@ -586,12 +643,12 @@ export class JsonlSessionHistoryStore implements SessionHistoryStore {
586
643
  });
587
644
  }
588
645
 
589
- async list(): Promise<SessionMessageV1[]> {
646
+ async list_records(): Promise<SessionRecordV1[]> {
590
647
  await this.ensureLayout();
591
648
  const file = this.getMessagesFilePath();
592
649
  const raw = await fs.readFile(file, "utf8");
593
650
  const lines = raw.split("\n").filter(Boolean);
594
- const out: SessionMessageV1[] = [];
651
+ const out: SessionRecordV1[] = [];
595
652
  for (const line of lines) {
596
653
  try {
597
654
  const obj = this.normalizePersistedMessage(JSON.parse(line));
@@ -601,22 +658,22 @@ export class JsonlSessionHistoryStore implements SessionHistoryStore {
601
658
  // ignore invalid lines
602
659
  }
603
660
  }
604
- const current_inflight = await this.readInflightUnsafe();
661
+ const current_inflight = await this.read_inflight_unsafe();
605
662
  if (current_inflight) {
606
663
  out.push(current_inflight);
607
664
  }
608
665
  return out;
609
666
  }
610
667
 
611
- async slice(start: number, end: number): Promise<SessionMessageV1[]> {
612
- const msgs = await this.list();
668
+ async slice_records(start: number, end: number): Promise<SessionRecordV1[]> {
669
+ const msgs = await this.list_records();
613
670
  const startIndex = Math.max(0, Math.floor(start));
614
671
  const endIndex = Math.max(startIndex, Math.floor(end));
615
672
  return msgs.slice(startIndex, endIndex);
616
673
  }
617
674
 
618
- async size(): Promise<number> {
619
- const msgs = await this.list();
675
+ async record_count(): Promise<number> {
676
+ const msgs = await this.list_records();
620
677
  return msgs.length;
621
678
  }
622
679
 
@@ -633,7 +690,7 @@ export class JsonlSessionHistoryStore implements SessionHistoryStore {
633
690
  metadata: Omit<SessionMetadataV1, "v" | "ts"> &
634
691
  Partial<Pick<SessionMetadataV1, "ts">>;
635
692
  id?: string;
636
- }): SessionMessageV1 {
693
+ }): SessionRecordV1 {
637
694
  const { ts, ...metadata } = input.metadata;
638
695
  const md: SessionMetadataV1 = {
639
696
  v: 1,
@@ -658,7 +715,7 @@ export class JsonlSessionHistoryStore implements SessionHistoryStore {
658
715
  id?: string;
659
716
  kind?: "normal" | "summary";
660
717
  source?: "egress" | "compact";
661
- }): SessionMessageV1 {
718
+ }): SessionRecordV1 {
662
719
  const { ts, ...metadata } = input.metadata;
663
720
  const md: SessionMetadataV1 = {
664
721
  v: 1,
@@ -676,29 +733,23 @@ export class JsonlSessionHistoryStore implements SessionHistoryStore {
676
733
  };
677
734
  }
678
735
 
679
- operation(input: {
680
- operation: AgentSessionOperationRecord;
681
- metadata: Omit<SessionMetadataV1, "v" | "ts" | "kind" | "source" | "operation"> &
736
+ action(input: {
737
+ action: SessionActionRecordV1;
738
+ metadata: Pick<SessionMetadataV1, "sessionId"> &
682
739
  Partial<Pick<SessionMetadataV1, "ts">>;
683
740
  id?: string;
684
- }): SessionMessageV1 {
685
- const operation = this.normalizeOperation(input.operation);
686
- const label = String(
687
- operation.label || `${operation.name}: ${operation.status}`,
688
- ).trim();
741
+ }): SessionActionRecordV1 {
689
742
  const { ts, ...metadata } = input.metadata;
743
+ const message = to_session_action_record(
744
+ input.id ? { ...input.action, id: input.id } : input.action,
745
+ metadata.sessionId || this.sessionId,
746
+ );
690
747
  return {
691
- id: input.id || `op:${this.sessionId}:${operation.operationId}:${generateId()}`,
692
- role: "operation",
748
+ ...message,
693
749
  metadata: {
694
- v: 1,
695
- ts: typeof ts === "number" ? ts : Date.now(),
696
- ...metadata,
697
- source: "operation",
698
- kind: "operation",
699
- operation,
750
+ ...message.metadata,
751
+ ts: typeof ts === "number" ? ts : message.metadata.ts,
700
752
  },
701
- parts: [{ type: "text", text: label }],
702
753
  };
703
754
  }
704
755
  }
@@ -3,20 +3,34 @@
3
3
  *
4
4
  * 关键点(中文)
5
5
  * - plugin_call 是 agent 内置的最低层 plugin action 桥。
6
- * - schema 只描述模型需要提交的目标 pluginaction JSON payload
6
+ * - plugin_call.payload 是透传给具体 plugin action JSON object
7
+ * - 这里不用 Zod 表达 payload 的开放对象语义,避免 AI SDK zodSchema
8
+ * 转换后把 additionalProperties 收窄为 false。
7
9
  */
8
10
 
11
+ import { jsonSchema } from "ai";
9
12
  import { z } from "zod";
10
13
 
11
- export const plugin_call_input_schema = z.object({
12
- plugin: z.string().describe("Registered plugin name to call, for example image."),
13
- action: z.string().describe("Plugin action name to execute, for example image_create."),
14
- payload: z
15
- .object({})
16
- .passthrough()
17
- .optional()
18
- .default({})
19
- .describe("JSON payload passed to the plugin action."),
14
+ export const plugin_call_input_schema = jsonSchema({
15
+ type: "object",
16
+ required: ["plugin", "action"],
17
+ additionalProperties: false,
18
+ properties: {
19
+ plugin: {
20
+ type: "string",
21
+ description: "Registered plugin name to call, for example image.",
22
+ },
23
+ action: {
24
+ type: "string",
25
+ description: "Plugin action name to execute, for example image_create.",
26
+ },
27
+ payload: {
28
+ type: "object",
29
+ additionalProperties: true,
30
+ default: {},
31
+ description: "JSON payload passed to the plugin action.",
32
+ },
33
+ },
20
34
  });
21
35
 
22
36
  export const plugin_read_input_schema = z.object({