@downcity/agent 1.1.217 → 1.1.222

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 (147) hide show
  1. package/bin/agent/local/services/AgentSessions.d.ts.map +1 -1
  2. package/bin/agent/local/services/AgentSessions.js +1 -4
  3. package/bin/agent/local/services/AgentSessions.js.map +1 -1
  4. package/bin/agent/remote/RemoteSession.d.ts +9 -3
  5. package/bin/agent/remote/RemoteSession.d.ts.map +1 -1
  6. package/bin/agent/remote/RemoteSession.js +19 -4
  7. package/bin/agent/remote/RemoteSession.js.map +1 -1
  8. package/bin/agent/remote/RemoteTransport.d.ts +7 -3
  9. package/bin/agent/remote/RemoteTransport.d.ts.map +1 -1
  10. package/bin/agent/remote/transports/HttpRemoteAgentTransport.d.ts +5 -2
  11. package/bin/agent/remote/transports/HttpRemoteAgentTransport.d.ts.map +1 -1
  12. package/bin/agent/remote/transports/HttpRemoteAgentTransport.js +25 -11
  13. package/bin/agent/remote/transports/HttpRemoteAgentTransport.js.map +1 -1
  14. package/bin/agent/remote/transports/RpcRemoteAgentTransport.d.ts +5 -2
  15. package/bin/agent/remote/transports/RpcRemoteAgentTransport.d.ts.map +1 -1
  16. package/bin/agent/remote/transports/RpcRemoteAgentTransport.js +5 -2
  17. package/bin/agent/remote/transports/RpcRemoteAgentTransport.js.map +1 -1
  18. package/bin/executor/types/SessionRecords.d.ts +2 -0
  19. package/bin/executor/types/SessionRecords.d.ts.map +1 -1
  20. package/bin/executor/types/SessionRecords.js.map +1 -1
  21. package/bin/index.d.ts +5 -2
  22. package/bin/index.d.ts.map +1 -1
  23. package/bin/index.js +1 -0
  24. package/bin/index.js.map +1 -1
  25. package/bin/rpc/Client.d.ts +11 -4
  26. package/bin/rpc/Client.d.ts.map +1 -1
  27. package/bin/rpc/Client.js +14 -3
  28. package/bin/rpc/Client.js.map +1 -1
  29. package/bin/session/Session.d.ts +13 -3
  30. package/bin/session/Session.d.ts.map +1 -1
  31. package/bin/session/Session.js +47 -18
  32. package/bin/session/Session.js.map +1 -1
  33. package/bin/session/recorder/JsonlSessionMessageStore.d.ts +45 -0
  34. package/bin/session/recorder/JsonlSessionMessageStore.d.ts.map +1 -0
  35. package/bin/session/recorder/JsonlSessionMessageStore.js +127 -0
  36. package/bin/session/recorder/JsonlSessionMessageStore.js.map +1 -0
  37. package/bin/session/recorder/SessionMessageCodec.d.ts +20 -0
  38. package/bin/session/recorder/SessionMessageCodec.d.ts.map +1 -0
  39. package/bin/session/recorder/SessionMessageCodec.js +252 -0
  40. package/bin/session/recorder/SessionMessageCodec.js.map +1 -0
  41. package/bin/session/recorder/SessionMessageReducer.d.ts +12 -0
  42. package/bin/session/recorder/SessionMessageReducer.d.ts.map +1 -0
  43. package/bin/session/recorder/SessionMessageReducer.js +109 -0
  44. package/bin/session/recorder/SessionMessageReducer.js.map +1 -0
  45. package/bin/session/recorder/SessionRecorder.d.ts +177 -0
  46. package/bin/session/recorder/SessionRecorder.d.ts.map +1 -0
  47. package/bin/session/recorder/SessionRecorder.js +610 -0
  48. package/bin/session/recorder/SessionRecorder.js.map +1 -0
  49. package/bin/session/recorder/SessionRecorderCompaction.d.ts +18 -0
  50. package/bin/session/recorder/SessionRecorderCompaction.d.ts.map +1 -0
  51. package/bin/session/recorder/SessionRecorderCompaction.js +141 -0
  52. package/bin/session/recorder/SessionRecorderCompaction.js.map +1 -0
  53. package/bin/session/recorder/SessionRecorderHistoryStore.d.ts +66 -0
  54. package/bin/session/recorder/SessionRecorderHistoryStore.d.ts.map +1 -0
  55. package/bin/session/recorder/SessionRecorderHistoryStore.js +195 -0
  56. package/bin/session/recorder/SessionRecorderHistoryStore.js.map +1 -0
  57. package/bin/session/runtime/SessionMessageEventHub.d.ts +15 -0
  58. package/bin/session/runtime/SessionMessageEventHub.d.ts.map +1 -0
  59. package/bin/session/runtime/SessionMessageEventHub.js +28 -0
  60. package/bin/session/runtime/SessionMessageEventHub.js.map +1 -0
  61. package/bin/session/runtime/SessionPromptRuntime.d.ts +7 -13
  62. package/bin/session/runtime/SessionPromptRuntime.d.ts.map +1 -1
  63. package/bin/session/runtime/SessionPromptRuntime.js +13 -13
  64. package/bin/session/runtime/SessionPromptRuntime.js.map +1 -1
  65. package/bin/session/services/SessionStateService.d.ts +7 -3
  66. package/bin/session/services/SessionStateService.d.ts.map +1 -1
  67. package/bin/session/services/SessionStateService.js +132 -72
  68. package/bin/session/services/SessionStateService.js.map +1 -1
  69. package/bin/session/services/SessionTurnService.d.ts +4 -0
  70. package/bin/session/services/SessionTurnService.d.ts.map +1 -1
  71. package/bin/session/services/SessionTurnService.js +82 -52
  72. package/bin/session/services/SessionTurnService.js.map +1 -1
  73. package/bin/session/services/SessionViewService.d.ts +8 -3
  74. package/bin/session/services/SessionViewService.d.ts.map +1 -1
  75. package/bin/session/services/SessionViewService.js +10 -5
  76. package/bin/session/services/SessionViewService.js.map +1 -1
  77. package/bin/session/storage/Persistence.d.ts +6 -0
  78. package/bin/session/storage/Persistence.d.ts.map +1 -1
  79. package/bin/session/storage/Persistence.js +7 -0
  80. package/bin/session/storage/Persistence.js.map +1 -1
  81. package/bin/session/storage/RuntimeSessionPort.d.ts +3 -2
  82. package/bin/session/storage/RuntimeSessionPort.d.ts.map +1 -1
  83. package/bin/session/storage/RuntimeSessionPort.js.map +1 -1
  84. package/bin/types/agent/SessionActor.d.ts +10 -4
  85. package/bin/types/agent/SessionActor.d.ts.map +1 -1
  86. package/bin/types/rpc/RpcProtocol.d.ts +20 -6
  87. package/bin/types/rpc/RpcProtocol.d.ts.map +1 -1
  88. package/bin/types/runtime/agent/AgentContext.d.ts +4 -3
  89. package/bin/types/runtime/agent/AgentContext.d.ts.map +1 -1
  90. package/bin/types/runtime/agent/AgentContext.js.map +1 -1
  91. package/bin/types/sdk/AgentSessionEvent.d.ts +2 -1
  92. package/bin/types/sdk/AgentSessionEvent.d.ts.map +1 -1
  93. package/bin/types/session/SessionMessage.d.ts +217 -0
  94. package/bin/types/session/SessionMessage.d.ts.map +1 -0
  95. package/bin/types/session/SessionMessage.js +8 -0
  96. package/bin/types/session/SessionMessage.js.map +1 -0
  97. package/bin/types/session/SessionMessageMutation.d.ts +92 -0
  98. package/bin/types/session/SessionMessageMutation.d.ts.map +1 -0
  99. package/bin/types/session/SessionMessageMutation.js +21 -0
  100. package/bin/types/session/SessionMessageMutation.js.map +1 -0
  101. package/package.json +3 -3
  102. package/scripts/agent-env.test.mjs +4 -4
  103. package/scripts/session-action-message.test.mjs +98 -27
  104. package/scripts/session-list-title.test.mjs +6 -19
  105. package/scripts/session-prompt-runtime.test.mjs +4 -16
  106. package/scripts/session-recorder.test.mjs +245 -0
  107. package/scripts/session-title-event.test.mjs +10 -18
  108. package/src/agent/local/services/AgentSessions.ts +1 -3
  109. package/src/agent/remote/RemoteSession.ts +35 -7
  110. package/src/agent/remote/RemoteTransport.ts +17 -6
  111. package/src/agent/remote/transports/HttpRemoteAgentTransport.ts +45 -13
  112. package/src/agent/remote/transports/RpcRemoteAgentTransport.ts +19 -6
  113. package/src/executor/types/SessionRecords.ts +2 -0
  114. package/src/index.ts +23 -5
  115. package/src/rpc/Client.ts +29 -8
  116. package/src/session/Session.ts +65 -31
  117. package/src/session/recorder/JsonlSessionMessageStore.ts +162 -0
  118. package/src/session/recorder/SessionMessageCodec.ts +279 -0
  119. package/src/session/recorder/SessionMessageReducer.ts +155 -0
  120. package/src/session/recorder/SessionRecorder.ts +812 -0
  121. package/src/session/recorder/SessionRecorderCompaction.ts +187 -0
  122. package/src/session/recorder/SessionRecorderHistoryStore.ts +276 -0
  123. package/src/session/runtime/SessionMessageEventHub.ts +35 -0
  124. package/src/session/runtime/SessionPromptRuntime.ts +23 -24
  125. package/src/session/services/SessionStateService.ts +151 -80
  126. package/src/session/services/SessionTurnService.ts +88 -59
  127. package/src/session/services/SessionViewService.ts +25 -13
  128. package/src/session/storage/Persistence.ts +13 -0
  129. package/src/session/storage/RuntimeSessionPort.ts +6 -4
  130. package/src/types/agent/SessionActor.ts +26 -6
  131. package/src/types/rpc/RpcProtocol.ts +20 -6
  132. package/src/types/runtime/agent/AgentContext.ts +8 -2
  133. package/src/types/sdk/AgentSessionEvent.ts +2 -0
  134. package/src/types/session/SessionMessage.ts +247 -0
  135. package/src/types/session/SessionMessageMutation.ts +121 -0
  136. package/tsconfig.tsbuildinfo +1 -1
  137. package/bin/session/SessionEventMapper.d.ts +0 -32
  138. package/bin/session/SessionEventMapper.d.ts.map +0 -1
  139. package/bin/session/SessionEventMapper.js +0 -131
  140. package/bin/session/SessionEventMapper.js.map +0 -1
  141. package/bin/types/sdk/InternalUiChunkEvent.d.ts +0 -100
  142. package/bin/types/sdk/InternalUiChunkEvent.d.ts.map +0 -1
  143. package/bin/types/sdk/InternalUiChunkEvent.js +0 -9
  144. package/bin/types/sdk/InternalUiChunkEvent.js.map +0 -1
  145. package/scripts/session-history-archive.test.mjs +0 -188
  146. package/src/session/SessionEventMapper.ts +0 -148
  147. package/src/types/sdk/InternalUiChunkEvent.ts +0 -108
@@ -9,8 +9,6 @@
9
9
  import type {
10
10
  AgentSessionConfigSnapshot,
11
11
  AgentSessionForkInput,
12
- AgentSessionRecordsInput,
13
- AgentSessionRecordsPage,
14
12
  AgentSessionInfo,
15
13
  AgentSessionSetInput,
16
14
  AgentSessionSystemSnapshot,
@@ -28,6 +26,17 @@ import type {
28
26
  AgentSessionTurnHandle,
29
27
  AgentSessionTurnResult,
30
28
  } from "@/types/sdk/AgentSessionTurn.js";
29
+ import type {
30
+ ListSessionMessagesInput,
31
+ SessionMessagePage,
32
+ } from "@/types/session/SessionMessage.js";
33
+ import {
34
+ is_session_message_mutation,
35
+ type ListSessionMessageChangesInput,
36
+ type SessionMessageMutationPage,
37
+ type SessionMessageMutationSubscriber,
38
+ type SessionMessageMutationUnsubscribe,
39
+ } from "@/types/session/SessionMessageMutation.js";
31
40
  import { SessionEventHub } from "@/session/runtime/SessionEventHub.js";
32
41
  import type {
33
42
  RemoteSessionTransport,
@@ -124,7 +133,9 @@ export class RemoteSession implements RemoteAgentSession {
124
133
  /**
125
134
  * 订阅当前远程 session 的 future 事件。
126
135
  */
127
- subscribe(subscriber: AgentSessionSubscriber): AgentSessionUnsubscribe {
136
+ subscribe(
137
+ subscriber: SessionMessageMutationSubscriber,
138
+ ): SessionMessageMutationUnsubscribe {
128
139
  this.event_subscriber_count += 1;
129
140
  void this.ensure_event_pump().catch((error) => {
130
141
  this.event_hub.publish({
@@ -132,7 +143,9 @@ export class RemoteSession implements RemoteAgentSession {
132
143
  message: error instanceof Error ? error.message : String(error),
133
144
  });
134
145
  });
135
- const unsubscribe = this.event_hub.subscribe(subscriber);
146
+ const unsubscribe = this.event_hub.subscribe((event) => {
147
+ if (is_session_message_mutation(event)) subscriber(event);
148
+ });
136
149
  return () => {
137
150
  unsubscribe();
138
151
  this.event_subscriber_count = Math.max(0, this.event_subscriber_count - 1);
@@ -140,11 +153,23 @@ export class RemoteSession implements RemoteAgentSession {
140
153
  };
141
154
  }
142
155
 
156
+ /** 订阅 transport 使用的 Message 与 lifecycle 事件。 */
157
+ subscribe_transport(subscriber: AgentSessionSubscriber): AgentSessionUnsubscribe {
158
+ return this.event_hub.subscribe(subscriber);
159
+ }
160
+
143
161
  /**
144
162
  * 读取远程消息历史。
145
163
  */
146
- async records(input?: AgentSessionRecordsInput): Promise<AgentSessionRecordsPage> {
147
- return await this.transport.records(this.id, input);
164
+ async messages(input?: ListSessionMessagesInput): Promise<SessionMessagePage> {
165
+ return await this.transport.messages(this.id, input);
166
+ }
167
+
168
+ /** 读取远程增量 Message Mutation。 */
169
+ async message_changes(
170
+ input: ListSessionMessageChangesInput,
171
+ ): Promise<SessionMessageMutationPage> {
172
+ return await this.transport.message_changes(this.id, input);
148
173
  }
149
174
 
150
175
  /**
@@ -197,7 +222,7 @@ export class RemoteSession implements RemoteAgentSession {
197
222
  }
198
223
 
199
224
  private handle_event(event: AgentSessionEvent): void {
200
- if (event.type === "error") {
225
+ if (!is_session_message_mutation(event) && event.type === "error") {
201
226
  this.fail_pending_turns(event.message);
202
227
  }
203
228
  const turn_id = extract_turn_id(event);
@@ -314,6 +339,9 @@ function create_turn_handle(
314
339
  }
315
340
 
316
341
  function extract_turn_id(event: AgentSessionEvent): string | null {
342
+ if (is_session_message_mutation(event)) {
343
+ return event.turn_id || null;
344
+ }
317
345
  switch (event.type) {
318
346
  case "turn-start":
319
347
  case "text-delta":
@@ -15,8 +15,6 @@ import type {
15
15
  AgentArchiveSessionsResult,
16
16
  AgentCleanArchiveResult,
17
17
  AgentSessionForkInput,
18
- AgentSessionRecordsInput,
19
- AgentSessionRecordsPage,
20
18
  AgentSessionInfo,
21
19
  AgentSessionSummaryPage,
22
20
  AgentSessionSystemSnapshot,
@@ -29,6 +27,14 @@ import type {
29
27
  import type { AgentSessionEvent } from "@/types/sdk/AgentSessionEvent.js";
30
28
  import type { AgentSessionPromptInput } from "@/types/sdk/AgentSessionPrompt.js";
31
29
  import type { AgentSessionStopResult } from "@/types/sdk/AgentSessionStop.js";
30
+ import type {
31
+ ListSessionMessagesInput,
32
+ SessionMessagePage,
33
+ } from "@/types/session/SessionMessage.js";
34
+ import type {
35
+ ListSessionMessageChangesInput,
36
+ SessionMessageMutationPage,
37
+ } from "@/types/session/SessionMessageMutation.js";
32
38
  import type {
33
39
  ShellApprovalMode,
34
40
  ShellApprovalDecisionResult,
@@ -69,11 +75,16 @@ export type RemoteSessionTransport = {
69
75
  /** 底层事件连接结束后的通知;主动关闭不触发。 */
70
76
  on_close: (error?: unknown) => void;
71
77
  }): Promise<TransportSubscription>;
72
- /** 读取 history。 */
73
- records(
78
+ /** 读取 Session Message。 */
79
+ messages(
80
+ session_id: string,
81
+ input?: ListSessionMessagesInput,
82
+ ): Promise<SessionMessagePage>;
83
+ /** 读取增量 Message Mutation。 */
84
+ message_changes(
74
85
  session_id: string,
75
- input?: AgentSessionRecordsInput,
76
- ): Promise<AgentSessionRecordsPage>;
86
+ input: ListSessionMessageChangesInput,
87
+ ): Promise<SessionMessageMutationPage>;
77
88
  /** 读取 system snapshot。 */
78
89
  system(session_id: string): Promise<AgentSessionSystemSnapshot>;
79
90
  /** 分叉 session。 */
@@ -15,13 +15,19 @@ import type {
15
15
  AgentArchiveSessionsResult,
16
16
  AgentCleanArchiveResult,
17
17
  AgentSessionForkInput,
18
- AgentSessionRecordsInput,
19
- AgentSessionRecordsPage,
20
18
  AgentSessionInfo,
21
19
  AgentSessionSummaryPage,
22
20
  AgentSessionSystemSnapshot,
23
21
  AgentSessionSetInput,
24
22
  } from "@/types/agent/SessionTypes.js";
23
+ import type {
24
+ ListSessionMessagesInput,
25
+ SessionMessagePage,
26
+ } from "@/types/session/SessionMessage.js";
27
+ import type {
28
+ ListSessionMessageChangesInput,
29
+ SessionMessageMutationPage,
30
+ } from "@/types/session/SessionMessageMutation.js";
25
31
  import type {
26
32
  RemoteAgentPluginActionInput,
27
33
  RemoteAgentPluginActionResult,
@@ -213,32 +219,58 @@ export class HttpRemoteAgentTransport implements RemoteAgentTransport {
213
219
  };
214
220
  }
215
221
 
216
- async records(
222
+ async messages(
217
223
  session_id: string,
218
- input?: AgentSessionRecordsInput,
219
- ): Promise<AgentSessionRecordsPage> {
224
+ input?: ListSessionMessagesInput,
225
+ ): Promise<SessionMessagePage> {
220
226
  const query = new URLSearchParams();
221
227
  if (input?.limit !== undefined) query.set("limit", String(input.limit));
222
228
  if (input?.cursor) query.set("cursor", input.cursor);
223
- if (input?.archive_id) query.set("archive_id", input.archive_id);
224
- if (input?.order) query.set("order", input.order);
225
- if (input?.view) query.set("view", input.view);
229
+ if (input?.before_sequence !== undefined) {
230
+ query.set("before_sequence", String(input.before_sequence));
231
+ }
232
+ if (input?.include_internal) query.set("include_internal", "true");
233
+ if (input?.through_sequence !== undefined) {
234
+ query.set("through_sequence", String(input.through_sequence));
235
+ }
226
236
  const payload = await read_http_json<{
227
237
  success?: boolean;
228
238
  error?: string;
229
- records?: AgentSessionRecordsPage;
239
+ messages?: SessionMessagePage;
230
240
  }>(
231
- `${this.base_url}/api/sdk/sessions/${encodeURIComponent(session_id)}/records${
241
+ `${this.base_url}/api/sdk/sessions/${encodeURIComponent(session_id)}/messages${
232
242
  query.size > 0 ? `?${query.toString()}` : ""
233
243
  }`,
234
244
  {
235
245
  headers: this.headers(),
236
246
  },
237
247
  );
238
- if (!payload.success || !payload.records || !Array.isArray(payload.records.items)) {
239
- throw new Error(String(payload.error || "Remote session records failed"));
248
+ if (!payload.success || !payload.messages || !Array.isArray(payload.messages.items)) {
249
+ throw new Error(String(payload.error || "Remote session messages failed"));
250
+ }
251
+ return payload.messages;
252
+ }
253
+
254
+ async message_changes(
255
+ session_id: string,
256
+ input: ListSessionMessageChangesInput,
257
+ ): Promise<SessionMessageMutationPage> {
258
+ const query = new URLSearchParams({
259
+ after_commit_sequence: String(input.after_commit_sequence),
260
+ });
261
+ if (input.limit !== undefined) query.set("limit", String(input.limit));
262
+ const payload = await read_http_json<{
263
+ success?: boolean;
264
+ error?: string;
265
+ changes?: SessionMessageMutationPage;
266
+ }>(
267
+ `${this.base_url}/api/sdk/sessions/${encodeURIComponent(session_id)}/message-changes?${query.toString()}`,
268
+ { headers: this.headers() },
269
+ );
270
+ if (!payload.success || !payload.changes) {
271
+ throw new Error(String(payload.error || "Remote session message changes failed"));
240
272
  }
241
- return payload.records;
273
+ return payload.changes;
242
274
  }
243
275
 
244
276
  async system(session_id: string): Promise<AgentSessionSystemSnapshot> {
@@ -15,13 +15,19 @@ import type {
15
15
  AgentArchiveSessionsResult,
16
16
  AgentCleanArchiveResult,
17
17
  AgentSessionForkInput,
18
- AgentSessionRecordsInput,
19
- AgentSessionRecordsPage,
20
18
  AgentSessionInfo,
21
19
  AgentSessionSummaryPage,
22
20
  AgentSessionSystemSnapshot,
23
21
  AgentSessionSetInput,
24
22
  } from "@/types/agent/SessionTypes.js";
23
+ import type {
24
+ ListSessionMessagesInput,
25
+ SessionMessagePage,
26
+ } from "@/types/session/SessionMessage.js";
27
+ import type {
28
+ ListSessionMessageChangesInput,
29
+ SessionMessageMutationPage,
30
+ } from "@/types/session/SessionMessageMutation.js";
25
31
  import type {
26
32
  RemoteAgentPluginActionInput,
27
33
  RemoteAgentPluginActionResult,
@@ -101,16 +107,23 @@ export class RpcRemoteAgentTransport implements RemoteAgentTransport {
101
107
  };
102
108
  }
103
109
 
104
- async records(
110
+ async messages(
105
111
  session_id: string,
106
- input?: AgentSessionRecordsInput,
107
- ): Promise<AgentSessionRecordsPage> {
108
- return await this.client.get_session_records({
112
+ input?: ListSessionMessagesInput,
113
+ ): Promise<SessionMessagePage> {
114
+ return await this.client.get_session_messages({
109
115
  session_id,
110
116
  input,
111
117
  });
112
118
  }
113
119
 
120
+ async message_changes(
121
+ session_id: string,
122
+ input: ListSessionMessageChangesInput,
123
+ ): Promise<SessionMessageMutationPage> {
124
+ return await this.client.get_session_message_changes({ session_id, input });
125
+ }
126
+
114
127
  async system(session_id: string): Promise<AgentSessionSystemSnapshot> {
115
128
  return await this.client.get_session_system(session_id);
116
129
  }
@@ -65,6 +65,8 @@ export type SessionMetadataV1 = {
65
65
  ts: number;
66
66
  /** 当前消息所属的 session ID。 */
67
67
  sessionId: string;
68
+ /** 当前消息所属 turn。 */
69
+ turnId?: string;
68
70
  /** 当前消息是普通消息还是摘要消息。 */
69
71
  kind?: SessionMessageKind;
70
72
  /** 当前消息来自入站、出站还是 compact。 */
package/src/index.ts CHANGED
@@ -27,9 +27,6 @@ export type {
27
27
  AgentListSessionsInput,
28
28
  AgentSessionConfigSnapshot,
29
29
  AgentSessionForkInput,
30
- AgentSessionRecordsInput,
31
- AgentSessionRecordsPage,
32
- AgentSessionRecordsView,
33
30
  AgentSessionInfo,
34
31
  AgentSessionSetInput,
35
32
  AgentSessionSummary,
@@ -38,8 +35,29 @@ export type {
38
35
  AgentSessionSystemBlockSource,
39
36
  AgentSessionSystemSessionInfo,
40
37
  AgentSessionSystemSnapshot,
41
- AgentSessionTimelineEvent,
42
38
  } from "./types/agent/SessionTypes.js";
39
+ export type {
40
+ ListSessionMessagesInput,
41
+ SessionActionMessage,
42
+ SessionAssistantMessage,
43
+ SessionAssistantMessagePart,
44
+ SessionAssistantToolPart,
45
+ SessionErrorMessage,
46
+ SessionMessage,
47
+ SessionMessagePage,
48
+ SessionUserMessage,
49
+ SessionUserMessagePart,
50
+ } from "./types/session/SessionMessage.js";
51
+ export {
52
+ is_session_message_mutation,
53
+ } from "./types/session/SessionMessageMutation.js";
54
+ export type {
55
+ ListSessionMessageChangesInput,
56
+ SessionMessageMutation,
57
+ SessionMessageMutationPage,
58
+ SessionMessageMutationSubscriber,
59
+ SessionMessageMutationUnsubscribe,
60
+ } from "./types/session/SessionMessageMutation.js";
43
61
  export type {
44
62
  AgentOptions,
45
63
  AgentSessionConstructor,
@@ -67,7 +85,7 @@ export type {
67
85
  AgentSessionActionRecord,
68
86
  AgentSessionActionState,
69
87
  } from "./types/sdk/AgentSessionAction.js";
70
- export type { AgentSessionPromptInput, SessionUserMessagePart } from "./types/sdk/AgentSessionPrompt.js";
88
+ export type { AgentSessionPromptInput } from "./types/sdk/AgentSessionPrompt.js";
71
89
  export type { AgentSessionStopResult } from "./types/sdk/AgentSessionStop.js";
72
90
  export type {
73
91
  AgentSessionTurnHandle,
package/src/rpc/Client.ts CHANGED
@@ -16,13 +16,19 @@ import type {
16
16
  AgentArchiveSessionResult,
17
17
  AgentArchiveSessionsResult,
18
18
  AgentCleanArchiveResult,
19
- AgentSessionRecordsInput,
20
- AgentSessionRecordsPage,
21
19
  AgentSessionInfo,
22
20
  AgentSessionSummaryPage,
23
21
  AgentSessionSystemSnapshot,
24
22
  AgentSessionSetInput,
25
23
  } from "@/types/agent/SessionTypes.js";
24
+ import type {
25
+ ListSessionMessagesInput,
26
+ SessionMessagePage,
27
+ } from "@/types/session/SessionMessage.js";
28
+ import type {
29
+ ListSessionMessageChangesInput,
30
+ SessionMessageMutationPage,
31
+ } from "@/types/session/SessionMessageMutation.js";
26
32
  import type { JsonValue } from "@/types/common/Json.js";
27
33
  import type { JsonObject } from "@/types/common/Json.js";
28
34
  import type { AgentSessionStopResult } from "@/types/sdk/AgentSessionStop.js";
@@ -219,18 +225,33 @@ export class RpcClient {
219
225
  /**
220
226
  * 读取 session records。
221
227
  */
222
- async get_session_records(params: {
228
+ async get_session_messages(params: {
229
+ session_id: string;
230
+ input?: ListSessionMessagesInput;
231
+ }): Promise<SessionMessagePage> {
232
+ const data = await this.request<{ messages: SessionMessagePage }>({
233
+ method: "sdk.sessions.messages",
234
+ params: {
235
+ sessionId: params.session_id,
236
+ input: params.input,
237
+ },
238
+ });
239
+ return data.messages;
240
+ }
241
+
242
+ /** 读取指定 cursor 后的 Session Message Mutation。 */
243
+ async get_session_message_changes(params: {
223
244
  session_id: string;
224
- input?: AgentSessionRecordsInput;
225
- }): Promise<AgentSessionRecordsPage> {
226
- const data = await this.request<{ records: AgentSessionRecordsPage }>({
227
- method: "sdk.sessions.records",
245
+ input: ListSessionMessageChangesInput;
246
+ }): Promise<SessionMessageMutationPage> {
247
+ const data = await this.request<{ changes: SessionMessageMutationPage }>({
248
+ method: "sdk.sessions.message_changes",
228
249
  params: {
229
250
  sessionId: params.session_id,
230
251
  input: params.input,
231
252
  },
232
253
  });
233
- return data.records;
254
+ return data.changes;
234
255
  }
235
256
 
236
257
  /**
@@ -10,12 +10,12 @@
10
10
  import { Executor } from "@executor/Executor.js";
11
11
  import type { Tool } from "ai";
12
12
  import { JsonlSessionHistoryComposer } from "@executor/composer/history/jsonl/JsonlSessionHistoryComposer.js";
13
- import { JsonlSessionHistoryStore } from "@/executor/store/history/jsonl/JsonlSessionHistoryStore.js";
13
+ import { SessionRecorderHistoryStore } from "@/session/recorder/SessionRecorderHistoryStore.js";
14
+ import { JsonlSessionMessageStore } from "@/session/recorder/JsonlSessionMessageStore.js";
15
+ import { SessionRecorder } from "@/session/recorder/SessionRecorder.js";
14
16
  import type {
15
17
  AgentSessionConfigSnapshot,
16
18
  AgentSessionForkInput,
17
- AgentSessionRecordsInput,
18
- AgentSessionRecordsPage,
19
19
  AgentSessionInfo,
20
20
  AgentSessionSetInput,
21
21
  AgentSessionSystemBlock,
@@ -23,9 +23,7 @@ import type {
23
23
  } from "@/types/agent/SessionTypes.js";
24
24
  import type { AgentSession } from "@/types/agent/SessionActor.js";
25
25
  import {
26
- getSdkAgentSessionArchiveDirPath,
27
26
  getSdkAgentSessionDirPath,
28
- getSdkAgentSessionInflightPath,
29
27
  } from "@/session/storage/Paths.js";
30
28
  import { resolveSystemTimezone } from "@/session/storage/Metadata.js";
31
29
  import { createRuntimeSessionPort } from "@/session/storage/RuntimeSessionPort.js";
@@ -35,10 +33,21 @@ import type {
35
33
  AgentSessionSubscriber,
36
34
  AgentSessionUnsubscribe,
37
35
  } from "@/types/sdk/AgentSessionEvent.js";
36
+ import type {
37
+ ListSessionMessageChangesInput,
38
+ SessionMessageMutationPage,
39
+ SessionMessageMutationSubscriber,
40
+ SessionMessageMutationUnsubscribe,
41
+ } from "@/types/session/SessionMessageMutation.js";
42
+ import type {
43
+ ListSessionMessagesInput,
44
+ SessionMessagePage,
45
+ } from "@/types/session/SessionMessage.js";
38
46
  import type { AgentSessionPromptInput } from "@/types/sdk/AgentSessionPrompt.js";
39
47
  import type { AgentSessionStopResult } from "@/types/sdk/AgentSessionStop.js";
40
48
  import type { AgentSessionTurnHandle } from "@/types/sdk/AgentSessionTurn.js";
41
49
  import { SessionEventHub } from "@/session/runtime/SessionEventHub.js";
50
+ import { SessionMessageEventHub } from "@/session/runtime/SessionMessageEventHub.js";
42
51
  import { SessionStateService } from "@/session/services/SessionStateService.js";
43
52
  import { SessionTurnService } from "@/session/services/SessionTurnService.js";
44
53
  import { SessionViewService } from "@/session/services/SessionViewService.js";
@@ -69,10 +78,13 @@ export class Session implements AgentSession {
69
78
  private readonly getPluginSystemBlocks: SessionOptions["getPluginSystemBlocks"];
70
79
  private readonly ensureConfiguredHook?: SessionOptions["ensureConfigured"];
71
80
  private readonly composers?: SessionComposerOptions;
72
- private readonly historyStore: JsonlSessionHistoryStore;
81
+ private readonly historyStore: SessionRecorderHistoryStore;
82
+ private readonly messageStore: JsonlSessionMessageStore;
83
+ private readonly recorder: SessionRecorder;
73
84
  private readonly historyComposer: SessionHistoryComposer;
74
85
  private readonly executor: Executor;
75
86
  private readonly eventHub = new SessionEventHub();
87
+ private readonly messageEventHub = new SessionMessageEventHub();
76
88
  private readonly localState: SessionLocalState;
77
89
  private readonly stateService: SessionStateService;
78
90
  private readonly turnService: SessionTurnService;
@@ -100,6 +112,14 @@ export class Session implements AgentSession {
100
112
  throw new Error("Session requires a non-empty projectRoot");
101
113
  }
102
114
 
115
+ this.messageStore = this.create_message_store();
116
+ this.recorder = new SessionRecorder({
117
+ session_id: this.id,
118
+ store: this.messageStore,
119
+ publish: (mutation) => {
120
+ this.messageEventHub.publish(mutation);
121
+ },
122
+ });
103
123
  this.historyStore = this.create_history_store();
104
124
  this.localState = this.create_local_state();
105
125
  const composer_context = this.create_composer_context();
@@ -118,6 +138,7 @@ export class Session implements AgentSession {
118
138
  project_root: this.projectRoot,
119
139
  session_id: this.id,
120
140
  history_store: this.historyStore,
141
+ recorder: this.recorder,
121
142
  executor: this.executor,
122
143
  state: this.localState,
123
144
  logger: this.logger,
@@ -137,12 +158,14 @@ export class Session implements AgentSession {
137
158
  executor: this.executor,
138
159
  state_service: this.stateService,
139
160
  event_hub: this.eventHub,
161
+ recorder: this.recorder,
140
162
  });
141
163
  this.viewService = new SessionViewService<this>({
142
164
  agent_id: this.agentId,
143
165
  project_root: this.projectRoot,
144
166
  session_id: this.id,
145
167
  history_store: this.historyStore,
168
+ recorder: this.recorder,
146
169
  state_service: this.stateService,
147
170
  logger: this.logger,
148
171
  is_executing: () => this.isExecuting(),
@@ -158,6 +181,7 @@ export class Session implements AgentSession {
158
181
  return {
159
182
  session,
160
183
  history_store: session.historyStore,
184
+ recorder: session.recorder,
161
185
  state_service: session.stateService,
162
186
  };
163
187
  },
@@ -168,6 +192,7 @@ export class Session implements AgentSession {
168
192
  * 初始化当前 session。
169
193
  */
170
194
  async initialize(): Promise<this> {
195
+ await this.recorder.initialize();
171
196
  await this.stateService.initialize();
172
197
  return this;
173
198
  }
@@ -203,8 +228,20 @@ export class Session implements AgentSession {
203
228
  /**
204
229
  * 订阅当前 Session 的未来事件。
205
230
  */
206
- subscribe(subscriber: AgentSessionSubscriber): AgentSessionUnsubscribe {
207
- return this.turnService.subscribe(subscriber);
231
+ subscribe(
232
+ subscriber: SessionMessageMutationSubscriber,
233
+ ): SessionMessageMutationUnsubscribe {
234
+ return this.messageEventHub.subscribe(subscriber);
235
+ }
236
+
237
+ /** 订阅远程 transport 所需的 Message 与 lifecycle 事件。 */
238
+ subscribe_transport(subscriber: AgentSessionSubscriber): AgentSessionUnsubscribe {
239
+ const unsubscribe_message = this.messageEventHub.subscribe(subscriber);
240
+ const unsubscribe_lifecycle = this.turnService.subscribe(subscriber);
241
+ return () => {
242
+ unsubscribe_message();
243
+ unsubscribe_lifecycle();
244
+ };
208
245
  }
209
246
 
210
247
  /**
@@ -239,8 +276,15 @@ export class Session implements AgentSession {
239
276
  /**
240
277
  * 读取当前 session records 分页。
241
278
  */
242
- async records(input?: AgentSessionRecordsInput): Promise<AgentSessionRecordsPage> {
243
- return await this.viewService.records(input);
279
+ async messages(input?: ListSessionMessagesInput): Promise<SessionMessagePage> {
280
+ return await this.recorder.list_messages(input);
281
+ }
282
+
283
+ /** 读取当前 Session 的增量 Message Mutation。 */
284
+ async message_changes(
285
+ input: ListSessionMessageChangesInput,
286
+ ): Promise<SessionMessageMutationPage> {
287
+ return await this.recorder.list_message_changes(input);
244
288
  }
245
289
 
246
290
  /**
@@ -329,33 +373,23 @@ export class Session implements AgentSession {
329
373
  return new SessionClass(options) as this;
330
374
  }
331
375
 
332
- private create_history_store(): JsonlSessionHistoryStore {
376
+ private create_message_store(): JsonlSessionMessageStore {
333
377
  const session_dir_path = getSdkAgentSessionDirPath(
334
378
  this.projectRoot,
335
379
  this.agentId,
336
380
  this.id,
337
381
  );
338
382
  const messages_dir_path = `${session_dir_path}/messages`;
339
- return new JsonlSessionHistoryStore({
340
- rootPath: this.projectRoot,
341
- agentId: this.agentId,
342
- sessionId: this.id,
343
- paths: {
344
- sessionDirPath: session_dir_path,
345
- messagesDirPath: messages_dir_path,
346
- messagesFilePath: `${messages_dir_path}/messages.jsonl`,
347
- metaFilePath: `${messages_dir_path}/meta.json`,
348
- archiveDirPath: getSdkAgentSessionArchiveDirPath(
349
- this.projectRoot,
350
- this.agentId,
351
- this.id,
352
- ),
353
- inflightFilePath: getSdkAgentSessionInflightPath(
354
- this.projectRoot,
355
- this.agentId,
356
- this.id,
357
- ),
358
- },
383
+ return new JsonlSessionMessageStore({
384
+ session_id: this.id,
385
+ file_path: `${messages_dir_path}/messages.jsonl`,
386
+ });
387
+ }
388
+
389
+ private create_history_store(): SessionRecorderHistoryStore {
390
+ return new SessionRecorderHistoryStore({
391
+ session_id: this.id,
392
+ recorder: this.recorder,
359
393
  });
360
394
  }
361
395