@downcity/agent 1.1.222 → 1.1.226

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 (166) hide show
  1. package/bin/agent/local/Agent.d.ts +1 -34
  2. package/bin/agent/local/Agent.d.ts.map +1 -1
  3. package/bin/agent/local/Agent.js +1 -44
  4. package/bin/agent/local/Agent.js.map +1 -1
  5. package/bin/agent/local/services/AgentAssemblyService.d.ts.map +1 -1
  6. package/bin/agent/local/services/AgentAssemblyService.js +35 -2
  7. package/bin/agent/local/services/AgentAssemblyService.js.map +1 -1
  8. package/bin/agent/local/services/AgentSessions.d.ts +6 -0
  9. package/bin/agent/local/services/AgentSessions.d.ts.map +1 -1
  10. package/bin/agent/local/services/AgentSessions.js +42 -0
  11. package/bin/agent/local/services/AgentSessions.js.map +1 -1
  12. package/bin/agent/remote/RemoteAgent.d.ts +1 -35
  13. package/bin/agent/remote/RemoteAgent.d.ts.map +1 -1
  14. package/bin/agent/remote/RemoteAgent.js +1 -37
  15. package/bin/agent/remote/RemoteAgent.js.map +1 -1
  16. package/bin/agent/remote/RemoteSession.d.ts +24 -45
  17. package/bin/agent/remote/RemoteSession.d.ts.map +1 -1
  18. package/bin/agent/remote/RemoteSession.js +74 -121
  19. package/bin/agent/remote/RemoteSession.js.map +1 -1
  20. package/bin/agent/remote/RemoteTransport.d.ts +11 -27
  21. package/bin/agent/remote/RemoteTransport.d.ts.map +1 -1
  22. package/bin/agent/remote/transports/HttpRemoteAgentTransport.d.ts +7 -21
  23. package/bin/agent/remote/transports/HttpRemoteAgentTransport.d.ts.map +1 -1
  24. package/bin/agent/remote/transports/HttpRemoteAgentTransport.js +11 -47
  25. package/bin/agent/remote/transports/HttpRemoteAgentTransport.js.map +1 -1
  26. package/bin/agent/remote/transports/RpcRemoteAgentTransport.d.ts +7 -20
  27. package/bin/agent/remote/transports/RpcRemoteAgentTransport.d.ts.map +1 -1
  28. package/bin/agent/remote/transports/RpcRemoteAgentTransport.js +8 -17
  29. package/bin/agent/remote/transports/RpcRemoteAgentTransport.js.map +1 -1
  30. package/bin/executor/store/history/jsonl/JsonlSessionHistoryStore.js +2 -2
  31. package/bin/executor/store/history/jsonl/JsonlSessionHistoryStore.js.map +1 -1
  32. package/bin/executor/types/SessionHistoryPaths.d.ts +1 -1
  33. package/bin/index.d.ts +3 -3
  34. package/bin/index.d.ts.map +1 -1
  35. package/bin/index.js +1 -1
  36. package/bin/index.js.map +1 -1
  37. package/bin/rpc/Client.d.ts +7 -36
  38. package/bin/rpc/Client.d.ts.map +1 -1
  39. package/bin/rpc/Client.js +28 -78
  40. package/bin/rpc/Client.js.map +1 -1
  41. package/bin/session/Session.d.ts +16 -8
  42. package/bin/session/Session.d.ts.map +1 -1
  43. package/bin/session/Session.js +66 -21
  44. package/bin/session/Session.js.map +1 -1
  45. package/bin/session/browse/Browse.d.ts.map +1 -1
  46. package/bin/session/browse/Browse.js +49 -18
  47. package/bin/session/browse/Browse.js.map +1 -1
  48. package/bin/session/recorder/JsonlSessionMessageStore.d.ts +30 -24
  49. package/bin/session/recorder/JsonlSessionMessageStore.d.ts.map +1 -1
  50. package/bin/session/recorder/JsonlSessionMessageStore.js +163 -59
  51. package/bin/session/recorder/JsonlSessionMessageStore.js.map +1 -1
  52. package/bin/session/recorder/SessionMessageCodec.d.ts.map +1 -1
  53. package/bin/session/recorder/SessionMessageCodec.js +6 -1
  54. package/bin/session/recorder/SessionMessageCodec.js.map +1 -1
  55. package/bin/session/recorder/SessionRecorder.d.ts +23 -11
  56. package/bin/session/recorder/SessionRecorder.d.ts.map +1 -1
  57. package/bin/session/recorder/SessionRecorder.js +187 -112
  58. package/bin/session/recorder/SessionRecorder.js.map +1 -1
  59. package/bin/session/recorder/SessionRecorderCompaction.d.ts.map +1 -1
  60. package/bin/session/recorder/SessionRecorderCompaction.js +1 -0
  61. package/bin/session/recorder/SessionRecorderCompaction.js.map +1 -1
  62. package/bin/session/recorder/SessionRecorderHistoryStore.d.ts +5 -5
  63. package/bin/session/recorder/SessionRecorderHistoryStore.d.ts.map +1 -1
  64. package/bin/session/recorder/SessionRecorderHistoryStore.js +5 -5
  65. package/bin/session/recorder/SessionRecorderHistoryStore.js.map +1 -1
  66. package/bin/session/runtime/SessionEventHub.d.ts +12 -5
  67. package/bin/session/runtime/SessionEventHub.d.ts.map +1 -1
  68. package/bin/session/runtime/SessionEventHub.js +11 -6
  69. package/bin/session/runtime/SessionEventHub.js.map +1 -1
  70. package/bin/session/runtime/SessionPromptRuntime.d.ts +2 -2
  71. package/bin/session/runtime/SessionPromptRuntime.d.ts.map +1 -1
  72. package/bin/session/runtime/SessionPromptRuntime.js +35 -17
  73. package/bin/session/runtime/SessionPromptRuntime.js.map +1 -1
  74. package/bin/session/services/SessionStateService.d.ts +2 -2
  75. package/bin/session/services/SessionStateService.d.ts.map +1 -1
  76. package/bin/session/services/SessionStateService.js +6 -2
  77. package/bin/session/services/SessionStateService.js.map +1 -1
  78. package/bin/session/services/SessionTurnService.d.ts +2 -7
  79. package/bin/session/services/SessionTurnService.d.ts.map +1 -1
  80. package/bin/session/services/SessionTurnService.js +2 -8
  81. package/bin/session/services/SessionTurnService.js.map +1 -1
  82. package/bin/session/storage/Paths.d.ts +1 -1
  83. package/bin/session/storage/Paths.d.ts.map +1 -1
  84. package/bin/session/storage/Paths.js +2 -2
  85. package/bin/session/storage/Paths.js.map +1 -1
  86. package/bin/session/storage/RuntimeSessionPort.d.ts +3 -4
  87. package/bin/session/storage/RuntimeSessionPort.d.ts.map +1 -1
  88. package/bin/session/storage/RuntimeSessionPort.js +2 -2
  89. package/bin/session/storage/RuntimeSessionPort.js.map +1 -1
  90. package/bin/types/agent/SessionActor.d.ts +11 -7
  91. package/bin/types/agent/SessionActor.d.ts.map +1 -1
  92. package/bin/types/rpc/RpcProtocol.d.ts +35 -62
  93. package/bin/types/rpc/RpcProtocol.d.ts.map +1 -1
  94. package/bin/types/runtime/agent/AgentContext.d.ts +4 -4
  95. package/bin/types/runtime/agent/AgentContext.d.ts.map +1 -1
  96. package/bin/types/runtime/agent/AgentContext.js.map +1 -1
  97. package/bin/types/session/SessionApproval.d.ts +97 -0
  98. package/bin/types/session/SessionApproval.d.ts.map +1 -0
  99. package/bin/types/session/SessionApproval.js +7 -0
  100. package/bin/types/session/SessionApproval.js.map +1 -0
  101. package/bin/types/session/SessionMessage.d.ts +10 -4
  102. package/bin/types/session/SessionMessage.d.ts.map +1 -1
  103. package/bin/types/session/SessionMutation.d.ts +116 -0
  104. package/bin/types/session/SessionMutation.d.ts.map +1 -0
  105. package/bin/types/session/SessionMutation.js +19 -0
  106. package/bin/types/session/SessionMutation.js.map +1 -0
  107. package/bin/types/session/SessionOptions.d.ts +9 -0
  108. package/bin/types/session/SessionOptions.d.ts.map +1 -1
  109. package/package.json +3 -3
  110. package/scripts/remote-session-reconnect.test.mjs +7 -3
  111. package/scripts/session-history-inflight.test.mjs +2 -2
  112. package/scripts/session-prompt-runtime.test.mjs +3 -3
  113. package/scripts/session-recorder.test.mjs +141 -140
  114. package/src/agent/local/Agent.ts +1 -55
  115. package/src/agent/local/services/AgentAssemblyService.ts +39 -3
  116. package/src/agent/local/services/AgentSessions.ts +47 -0
  117. package/src/agent/remote/RemoteAgent.ts +1 -54
  118. package/src/agent/remote/RemoteSession.ts +105 -163
  119. package/src/agent/remote/RemoteTransport.ts +23 -34
  120. package/src/agent/remote/transports/HttpRemoteAgentTransport.ts +33 -90
  121. package/src/agent/remote/transports/RpcRemoteAgentTransport.ts +22 -39
  122. package/src/executor/store/history/jsonl/JsonlSessionHistoryStore.ts +2 -2
  123. package/src/executor/types/SessionHistoryPaths.ts +1 -1
  124. package/src/index.ts +20 -12
  125. package/src/rpc/Client.ts +48 -106
  126. package/src/session/Session.ts +91 -34
  127. package/src/session/browse/Browse.ts +51 -22
  128. package/src/session/recorder/JsonlSessionMessageStore.ts +170 -86
  129. package/src/session/recorder/SessionMessageCodec.ts +6 -1
  130. package/src/session/recorder/SessionRecorder.ts +228 -134
  131. package/src/session/recorder/SessionRecorderCompaction.ts +1 -0
  132. package/src/session/recorder/SessionRecorderHistoryStore.ts +5 -5
  133. package/src/session/runtime/SessionEventHub.ts +25 -12
  134. package/src/session/runtime/SessionPromptRuntime.ts +37 -19
  135. package/src/session/services/SessionStateService.ts +8 -6
  136. package/src/session/services/SessionTurnService.ts +3 -14
  137. package/src/session/storage/Paths.ts +2 -2
  138. package/src/session/storage/RuntimeSessionPort.ts +8 -11
  139. package/src/types/agent/SessionActor.ts +23 -20
  140. package/src/types/rpc/RpcProtocol.ts +34 -71
  141. package/src/types/runtime/agent/AgentContext.ts +7 -11
  142. package/src/types/session/SessionApproval.ts +108 -0
  143. package/src/types/session/SessionMessage.ts +10 -4
  144. package/src/types/session/SessionMutation.ts +141 -0
  145. package/src/types/session/SessionOptions.ts +25 -0
  146. package/tsconfig.tsbuildinfo +1 -1
  147. package/bin/session/recorder/SessionMessageReducer.d.ts +0 -12
  148. package/bin/session/recorder/SessionMessageReducer.d.ts.map +0 -1
  149. package/bin/session/recorder/SessionMessageReducer.js +0 -109
  150. package/bin/session/recorder/SessionMessageReducer.js.map +0 -1
  151. package/bin/session/runtime/SessionMessageEventHub.d.ts +0 -15
  152. package/bin/session/runtime/SessionMessageEventHub.d.ts.map +0 -1
  153. package/bin/session/runtime/SessionMessageEventHub.js +0 -28
  154. package/bin/session/runtime/SessionMessageEventHub.js.map +0 -1
  155. package/bin/types/sdk/AgentSessionEvent.d.ts +0 -303
  156. package/bin/types/sdk/AgentSessionEvent.d.ts.map +0 -1
  157. package/bin/types/sdk/AgentSessionEvent.js +0 -9
  158. package/bin/types/sdk/AgentSessionEvent.js.map +0 -1
  159. package/bin/types/session/SessionMessageMutation.d.ts +0 -92
  160. package/bin/types/session/SessionMessageMutation.d.ts.map +0 -1
  161. package/bin/types/session/SessionMessageMutation.js +0 -21
  162. package/bin/types/session/SessionMessageMutation.js.map +0 -1
  163. package/src/session/recorder/SessionMessageReducer.ts +0 -155
  164. package/src/session/runtime/SessionMessageEventHub.ts +0 -35
  165. package/src/types/sdk/AgentSessionEvent.ts +0 -372
  166. package/src/types/session/SessionMessageMutation.ts +0 -121
@@ -1,5 +1,5 @@
1
1
  /**
2
- * SessionEventHub:Session 级事件分发器。
2
+ * SessionEventHub:统一 Session Mutation 分发器。
3
3
  *
4
4
  * 关键点(中文)
5
5
  * - 收口 `Session.subscribe()` 的订阅/取消订阅能力。
@@ -7,24 +7,36 @@
7
7
  */
8
8
 
9
9
  import type {
10
- AgentSessionEvent,
11
- AgentSessionSubscriber,
12
- AgentSessionUnsubscribe,
13
- } from "@/types/sdk/AgentSessionEvent.js";
10
+ SessionMutation,
11
+ SessionMutationReply,
12
+ SessionMutationSubscriber,
13
+ SessionMutationUnsubscribe,
14
+ } from "@/types/session/SessionMutation.js";
15
+
16
+ /** SessionEventHub 构造参数。 */
17
+ export interface SessionEventHubOptions {
18
+ /** 为当前 Mutation 创建绑定 Session 和 Tool Part 的回复入口。 */
19
+ create_reply: (mutation: SessionMutation) => SessionMutationReply;
20
+ }
14
21
 
15
22
  /**
16
23
  * SessionEventHub:最小事件总线实现。
17
24
  */
18
25
  export class SessionEventHub {
19
- private readonly subscribers = new Map<number, AgentSessionSubscriber>();
20
- private nextSubscriberId = 1;
26
+ private readonly subscribers = new Map<number, SessionMutationSubscriber>();
27
+ private readonly create_reply: SessionEventHubOptions["create_reply"];
28
+ private next_subscriber_id = 1;
29
+
30
+ constructor(options: SessionEventHubOptions) {
31
+ this.create_reply = options.create_reply;
32
+ }
21
33
 
22
34
  /**
23
35
  * 注册一个新的 Session 事件订阅者。
24
36
  */
25
- subscribe(subscriber: AgentSessionSubscriber): AgentSessionUnsubscribe {
26
- const id = this.nextSubscriberId;
27
- this.nextSubscriberId += 1;
37
+ subscribe(subscriber: SessionMutationSubscriber): SessionMutationUnsubscribe {
38
+ const id = this.next_subscriber_id;
39
+ this.next_subscriber_id += 1;
28
40
  this.subscribers.set(id, subscriber);
29
41
 
30
42
  return () => {
@@ -35,10 +47,11 @@ export class SessionEventHub {
35
47
  /**
36
48
  * 广播一条 Session 事件。
37
49
  */
38
- publish(event: AgentSessionEvent): void {
50
+ publish(mutation: SessionMutation): void {
51
+ const reply = this.create_reply(mutation);
39
52
  for (const subscriber of this.subscribers.values()) {
40
53
  try {
41
- subscriber(event);
54
+ Promise.resolve(subscriber(mutation, reply)).catch(() => undefined);
42
55
  } catch {
43
56
  // ignore single subscriber failures
44
57
  }
@@ -13,7 +13,7 @@ import type {
13
13
  SessionRecordV1,
14
14
  SessionMessageRecordV1,
15
15
  } from "@/executor/types/SessionRecords.js";
16
- import type { AgentSessionEvent } from "@/types/sdk/AgentSessionEvent.js";
16
+ import type { SessionMutation } from "@/types/session/SessionMutation.js";
17
17
  import type { AgentSessionPromptInput } from "@/types/sdk/AgentSessionPrompt.js";
18
18
  import type { AgentSessionStopResult } from "@/types/sdk/AgentSessionStop.js";
19
19
  import type {
@@ -89,7 +89,7 @@ export interface SessionPromptRuntimeOptions {
89
89
  /**
90
90
  * 广播 session 事件。
91
91
  */
92
- publish: (event: AgentSessionEvent) => void;
92
+ publish: (mutation: SessionMutation) => void;
93
93
 
94
94
  /**
95
95
  * 构造并持久化一条 user 消息。
@@ -226,8 +226,13 @@ export class SessionPromptRuntime {
226
226
  const activeTurn = createActiveTurnState(turnId);
227
227
  this.activeTurn = activeTurn;
228
228
  this.publish({
229
- type: "turn-start",
230
- turnId,
229
+ mutation_id: nanoid(),
230
+ variant: "turn",
231
+ type: "start",
232
+ session_id: this.sessionId,
233
+ turn_id: turnId,
234
+ status: "running",
235
+ created_at: Date.now(),
231
236
  });
232
237
  current.deferredHandle.resolve(createTurnHandle(activeTurn));
233
238
 
@@ -255,10 +260,14 @@ export class SessionPromptRuntime {
255
260
  };
256
261
  activeTurn.result = finalResult;
257
262
  this.publish({
258
- type: "turn-finish",
259
- turnId,
263
+ mutation_id: nanoid(),
264
+ variant: "turn",
265
+ type: "finish",
266
+ session_id: this.sessionId,
267
+ turn_id: turnId,
268
+ status: stopped ? "stopped" : finalResult.success ? "completed" : "failed",
269
+ created_at: Date.now(),
260
270
  text: finalResult.text,
261
- success: finalResult.success,
262
271
  ...(finalResult.error ? { error: finalResult.error } : {}),
263
272
  });
264
273
  activeTurn.deferredFinished.resolve(finalResult);
@@ -286,16 +295,16 @@ export class SessionPromptRuntime {
286
295
  } catch {
287
296
  // Error Message 写入失败不能阻止 turn handle 收口。
288
297
  }
289
- this.publish({
290
- type: "error",
291
- message,
292
- });
293
298
  }
294
299
  this.publish({
295
- type: "turn-finish",
296
- turnId,
300
+ mutation_id: nanoid(),
301
+ variant: "turn",
302
+ type: "finish",
303
+ session_id: this.sessionId,
304
+ turn_id: turnId,
305
+ status: activeTurn.abortController.signal.aborted ? "stopped" : "failed",
306
+ created_at: Date.now(),
297
307
  text: "",
298
- success: false,
299
308
  error: message,
300
309
  });
301
310
  activeTurn.deferredFinished.resolve(finalResult);
@@ -326,14 +335,23 @@ export class SessionPromptRuntime {
326
335
  cancelledTurn.result = finalResult;
327
336
  cancelledTurn.deferredFinished.resolve(finalResult);
328
337
  this.publish({
329
- type: "turn-start",
330
- turnId,
338
+ mutation_id: nanoid(),
339
+ variant: "turn",
340
+ type: "start",
341
+ session_id: this.sessionId,
342
+ turn_id: turnId,
343
+ status: "running",
344
+ created_at: Date.now(),
331
345
  });
332
346
  this.publish({
333
- type: "turn-finish",
334
- turnId,
347
+ mutation_id: nanoid(),
348
+ variant: "turn",
349
+ type: "finish",
350
+ session_id: this.sessionId,
351
+ turn_id: turnId,
352
+ status: "failed",
353
+ created_at: Date.now(),
335
354
  text: "",
336
- success: false,
337
355
  error: QUEUED_PROMPT_CANCELLED_MESSAGE,
338
356
  });
339
357
  item.deferredHandle.resolve(createTurnHandle(cancelledTurn));
@@ -26,9 +26,7 @@ import type {
26
26
  AgentSessionConfigSnapshot,
27
27
  AgentSessionSetInput,
28
28
  } from "@/types/agent/SessionTypes.js";
29
- import type {
30
- AgentSessionEvent,
31
- } from "@/types/sdk/AgentSessionEvent.js";
29
+ import type { SessionMutation } from "@/types/session/SessionMutation.js";
32
30
  import type { AgentSessionPromptInput } from "@/types/sdk/AgentSessionPrompt.js";
33
31
  import type {
34
32
  SessionActionRecordInputV1,
@@ -102,7 +100,7 @@ type SessionStateServiceOptions = {
102
100
  /**
103
101
  * 发布 session 事件。
104
102
  */
105
- publish_event: (event: AgentSessionEvent) => void;
103
+ publish_event: (mutation: SessionMutation) => void;
106
104
  };
107
105
 
108
106
  type SessionSetOptions = {
@@ -372,6 +370,7 @@ export class SessionStateService {
372
370
  ? from_ui_assistant_parts(params.message.parts)
373
371
  : [{
374
372
  part_id: `external-assistant-text:${Date.now()}`,
373
+ sequence: 1,
375
374
  type: "text" as const,
376
375
  text: String(params.fallbackText || "").trim(),
377
376
  state: "done" as const,
@@ -442,8 +441,11 @@ export class SessionStateService {
442
441
  const next_title = String(next_metadata.title || "").trim();
443
442
  if (!next_title || next_title === before_title) return;
444
443
  this.publish_event({
445
- type: "session-title",
446
- sessionId: this.session_id,
444
+ mutation_id: generateId(),
445
+ variant: "session",
446
+ type: "title",
447
+ session_id: this.session_id,
448
+ created_at: Date.now(),
447
449
  title: next_title,
448
450
  });
449
451
  }
@@ -9,11 +9,7 @@
9
9
 
10
10
  import { extractTextFromParts, extractTextFromUiMessage } from "@/executor/messages/UIMessageTransformer.js";
11
11
  import type { Executor } from "@executor/Executor.js";
12
- import type { AgentSessionEvent } from "@/types/sdk/AgentSessionEvent.js";
13
- import type {
14
- AgentSessionSubscriber,
15
- AgentSessionUnsubscribe,
16
- } from "@/types/sdk/AgentSessionEvent.js";
12
+ import type { SessionMutation } from "@/types/session/SessionMutation.js";
17
13
  import { isAgentSessionPromptInputEmpty } from "@/types/sdk/AgentSessionPrompt.js";
18
14
  import type { AgentSessionPromptInput } from "@/types/sdk/AgentSessionPrompt.js";
19
15
  import type { AgentSessionStopResult } from "@/types/sdk/AgentSessionStop.js";
@@ -118,15 +114,8 @@ export class SessionTurnService {
118
114
  /**
119
115
  * 发布一条 session 事件。
120
116
  */
121
- publish_event(event: AgentSessionEvent): void {
122
- this.event_hub.publish(event);
123
- }
124
-
125
- /**
126
- * 订阅当前 session 的未来事件。
127
- */
128
- subscribe(subscriber: AgentSessionSubscriber): AgentSessionUnsubscribe {
129
- return this.event_hub.subscribe(subscriber);
117
+ publish_event(mutation: SessionMutation): void {
118
+ this.event_hub.publish(mutation);
130
119
  }
131
120
 
132
121
  /**
@@ -212,13 +212,13 @@ export function getSdkAgentSessionArchiveFilePath(
212
212
  * - step / tool 过程会持续重写这个文件,避免中途中断后过程完全丢失。
213
213
  * - 完成后再把最终 assistant 合并进 `messages.jsonl`,并清理该文件。
214
214
  */
215
- export function getSdkAgentSessionInflightPath(
215
+ export function getSdkAgentSessionAssistantMessagePath(
216
216
  projectRoot: string,
217
217
  agentId: string,
218
218
  sessionId: string,
219
219
  ): string {
220
220
  return path.join(
221
221
  getSdkAgentSessionMessagesDirPath(projectRoot, agentId, sessionId),
222
- "inflight.json",
222
+ "assistant_message.json",
223
223
  );
224
224
  }
@@ -11,12 +11,9 @@ import type { SessionHistoryStore } from "@/executor/store/history/SessionHistor
11
11
  import type { AgentSessionPromptInput } from "@/types/sdk/AgentSessionPrompt.js";
12
12
  import type { AgentSessionStopResult } from "@/types/sdk/AgentSessionStop.js";
13
13
  import type {
14
- AgentSessionEvent,
15
- } from "@/types/sdk/AgentSessionEvent.js";
16
- import type {
17
- SessionMessageMutationSubscriber,
18
- SessionMessageMutationUnsubscribe,
19
- } from "@/types/session/SessionMessageMutation.js";
14
+ SessionMutationSubscriber,
15
+ SessionMutationUnsubscribe,
16
+ } from "@/types/session/SessionMutation.js";
20
17
  import type { AgentSessionTurnHandle } from "@/types/sdk/AgentSessionTurn.js";
21
18
 
22
19
  /**
@@ -43,12 +40,12 @@ export interface CreateRuntimeSessionPortParams {
43
40
  * 订阅当前 session 的 future 事件。
44
41
  */
45
42
  subscribe: (
46
- subscriber: SessionMessageMutationSubscriber,
47
- ) => SessionMessageMutationUnsubscribe;
43
+ subscriber: SessionMutationSubscriber,
44
+ ) => SessionMutationUnsubscribe;
48
45
  /**
49
46
  * 发布一条 session runtime 事件。
50
47
  */
51
- publishEvent: (event: AgentSessionEvent) => void;
48
+ publishEvent: SessionPort["publishEvent"];
52
49
  /**
53
50
  * 追加 user 消息到底层历史。
54
51
  */
@@ -92,8 +89,8 @@ export function createRuntimeSessionPort(
92
89
  subscribe: (subscriber) => {
93
90
  return params.subscribe(subscriber);
94
91
  },
95
- publishEvent: (event) => {
96
- params.publishEvent(event);
92
+ publishEvent: async (event) => {
93
+ await params.publishEvent(event);
97
94
  },
98
95
  append_user_message: async (messageParams) => {
99
96
  await params.append_user_message(messageParams);
@@ -22,15 +22,16 @@ import type {
22
22
  AgentSessionSystemSnapshot,
23
23
  } from "@/types/agent/SessionTypes.js";
24
24
  import type {
25
- AgentSessionSubscriber,
26
- AgentSessionUnsubscribe,
27
- } from "@/types/sdk/AgentSessionEvent.js";
25
+ SessionMutationSubscriber,
26
+ SessionMutationUnsubscribe,
27
+ } from "@/types/session/SessionMutation.js";
28
28
  import type {
29
- ListSessionMessageChangesInput,
30
- SessionMessageMutationPage,
31
- SessionMessageMutationSubscriber,
32
- SessionMessageMutationUnsubscribe,
33
- } from "@/types/session/SessionMessageMutation.js";
29
+ ResolveSessionApprovalInput,
30
+ SessionApproval,
31
+ SessionApprovalModeSnapshot,
32
+ SessionApprovalResult,
33
+ SetSessionApprovalModeInput,
34
+ } from "@/types/session/SessionApproval.js";
34
35
  import type {
35
36
  ListSessionMessagesInput,
36
37
  SessionMessagePage,
@@ -80,24 +81,26 @@ export interface AgentSessionActor {
80
81
 
81
82
  /** 订阅当前 session 的未来事件。 */
82
83
  subscribe(
83
- subscriber: SessionMessageMutationSubscriber,
84
- ): SessionMessageMutationUnsubscribe;
85
-
86
- /** 订阅远程 transport 使用的 Message 与 turn lifecycle 事件。 */
87
- subscribe_transport(
88
- subscriber: AgentSessionSubscriber,
89
- ): AgentSessionUnsubscribe;
84
+ subscriber: SessionMutationSubscriber,
85
+ ): SessionMutationUnsubscribe;
90
86
 
91
87
  /** 读取当前 session messages 分页。 */
92
88
  messages(input?: ListSessionMessagesInput): Promise<SessionMessagePage>;
93
89
 
94
- /** 读取指定 cursor 后的 Message Mutation。 */
95
- message_changes(
96
- input: ListSessionMessageChangesInput,
97
- ): Promise<SessionMessageMutationPage>;
98
-
99
90
  /** 读取当前 session 生效的 system 快照。 */
100
91
  system(): Promise<AgentSessionSystemSnapshot>;
92
+
93
+ /** 列出当前 Session 的 pending 工具审批。 */
94
+ approvals(): Promise<SessionApproval[]>;
95
+
96
+ /** 读取当前 Session 的工具审批模式。 */
97
+ approval_mode(): Promise<SessionApprovalModeSnapshot>;
98
+
99
+ /** 更新当前 Session 的工具审批模式。 */
100
+ set_approval_mode(input: SetSessionApprovalModeInput): Promise<SessionApprovalModeSnapshot>;
101
+
102
+ /** 处理当前 Session 的 pending 工具审批。 */
103
+ resolve_approval(input: ResolveSessionApprovalInput): Promise<SessionApprovalResult>;
101
104
  }
102
105
 
103
106
  /**
@@ -18,14 +18,16 @@ import type {
18
18
  AgentSessionSystemSnapshot,
19
19
  AgentSessionSetInput,
20
20
  } from "@/types/agent/SessionTypes.js";
21
- import type { AgentSessionEvent } from "@/types/sdk/AgentSessionEvent.js";
21
+ import type { SessionMutation } from "@/types/session/SessionMutation.js";
22
+ import type {
23
+ ResolveSessionApprovalInput,
24
+ SetSessionApprovalModeInput,
25
+ } from "@/types/session/SessionApproval.js";
22
26
  import type { AgentSessionPromptInput } from "@/types/sdk/AgentSessionPrompt.js";
23
27
  import type { AgentSessionStopResult } from "@/types/sdk/AgentSessionStop.js";
24
28
  import type { ListSessionMessagesInput } from "@/types/session/SessionMessage.js";
25
- import type { ListSessionMessageChangesInput } from "@/types/session/SessionMessageMutation.js";
26
29
  import type { JsonObject, JsonValue } from "@/types/common/Json.js";
27
30
  import type { PluginControlAction } from "@/types/plugin/PluginState.js";
28
- import type { ShellApprovalMode } from "@downcity/shell";
29
31
 
30
32
  /**
31
33
  * RPC 请求。
@@ -140,15 +142,34 @@ export type RpcRequest =
140
142
  | {
141
143
  /** 请求 id,用于匹配响应。 */
142
144
  id: string;
143
- /** 读取 session message mutations。 */
144
- method: "sdk.sessions.message_changes";
145
- /** changes 查询参数。 */
146
- params: {
147
- /** 目标 session id。 */
148
- sessionId: string;
149
- /** Mutation 增量参数。 */
150
- input: ListSessionMessageChangesInput;
151
- };
145
+ /** 列出指定 Session 的 pending 工具审批。 */
146
+ method: "sdk.sessions.approvals";
147
+ /** 目标 Session 参数。 */
148
+ params: { sessionId: string };
149
+ }
150
+ | {
151
+ /** 请求 id,用于匹配响应。 */
152
+ id: string;
153
+ /** 读取指定 Session 的工具审批模式。 */
154
+ method: "sdk.sessions.approvalMode";
155
+ /** 目标 Session 参数。 */
156
+ params: { sessionId: string };
157
+ }
158
+ | {
159
+ /** 请求 id,用于匹配响应。 */
160
+ id: string;
161
+ /** 更新指定 Session 的工具审批模式。 */
162
+ method: "sdk.sessions.setApprovalMode";
163
+ /** Session 与审批模式参数。 */
164
+ params: { sessionId: string; input: SetSessionApprovalModeInput };
165
+ }
166
+ | {
167
+ /** 请求 id,用于匹配响应。 */
168
+ id: string;
169
+ /** 处理指定 Session 的 pending 工具审批。 */
170
+ method: "sdk.sessions.resolveApproval";
171
+ /** Session 与审批决策参数。 */
172
+ params: { sessionId: string; input: ResolveSessionApprovalInput };
152
173
  }
153
174
  | {
154
175
  /** 请求 id,用于匹配响应。 */
@@ -302,64 +323,6 @@ export type RpcRequest =
302
323
  /** action payload。 */
303
324
  payload?: JsonValue;
304
325
  };
305
- }
306
- | {
307
- /** 请求 id,用于匹配响应。 */
308
- id: string;
309
- /** 列出 shell approvals。 */
310
- method: "internal.shell.approvals";
311
- }
312
- | {
313
- /** 请求 id,用于匹配响应。 */
314
- id: string;
315
- /** 列出 shell approval 模式。 */
316
- method: "internal.shell.approvalModes";
317
- }
318
- | {
319
- /** 请求 id,用于匹配响应。 */
320
- id: string;
321
- /** 读取 shell approval 模式。 */
322
- method: "internal.shell.approvalMode";
323
- /** session 参数。 */
324
- params: {
325
- /** session id。 */
326
- sessionId: string;
327
- };
328
- }
329
- | {
330
- /** 请求 id,用于匹配响应。 */
331
- id: string;
332
- /** 设置 shell approval 模式。 */
333
- method: "internal.shell.setApprovalMode";
334
- /** session 模式参数。 */
335
- params: {
336
- /** session id。 */
337
- sessionId: string;
338
- /** approval 模式。 */
339
- mode: ShellApprovalMode;
340
- };
341
- }
342
- | {
343
- /** 请求 id,用于匹配响应。 */
344
- id: string;
345
- /** 批准 shell approval。 */
346
- method: "internal.shell.approve";
347
- /** approval 参数。 */
348
- params: {
349
- /** approval id。 */
350
- approvalId: string;
351
- };
352
- }
353
- | {
354
- /** 请求 id,用于匹配响应。 */
355
- id: string;
356
- /** 拒绝 shell approval。 */
357
- method: "internal.shell.deny";
358
- /** approval 参数。 */
359
- params: {
360
- /** approval id。 */
361
- approvalId: string;
362
- };
363
326
  };
364
327
 
365
328
  /**
@@ -410,7 +373,7 @@ export interface RpcEventFrame {
410
373
  /** 当前订阅 id。 */
411
374
  subscriptionId: string;
412
375
  /** session 事件。 */
413
- event: AgentSessionEvent;
376
+ event: SessionMutation;
414
377
  }
415
378
 
416
379
  /**
@@ -29,14 +29,10 @@ import type { SessionHistoryStore } from "@/executor/store/history/SessionHistor
29
29
  import type { AgentSessionPromptInput } from "@/types/sdk/AgentSessionPrompt.js";
30
30
  import type { AgentSessionStopResult } from "@/types/sdk/AgentSessionStop.js";
31
31
  import type {
32
- AgentSessionEvent,
33
- AgentSessionSubscriber,
34
- AgentSessionUnsubscribe,
35
- } from "@/types/sdk/AgentSessionEvent.js";
36
- import type {
37
- SessionMessageMutationSubscriber,
38
- SessionMessageMutationUnsubscribe,
39
- } from "@/types/session/SessionMessageMutation.js";
32
+ SessionMutationSubscriber,
33
+ SessionMutationUnsubscribe,
34
+ } from "@/types/session/SessionMutation.js";
35
+ import type { SessionApprovalRuntimeEvent } from "@/types/session/SessionApproval.js";
40
36
  import type { AgentSessionTurnHandle } from "@/types/sdk/AgentSessionTurn.js";
41
37
 
42
38
  /**
@@ -140,8 +136,8 @@ export interface SessionPort {
140
136
  * - 当前 Message snapshot 通过公开 SDK `session.messages()` 读取。
141
137
  */
142
138
  subscribe(
143
- subscriber: SessionMessageMutationSubscriber,
144
- ): SessionMessageMutationUnsubscribe;
139
+ subscriber: SessionMutationSubscriber,
140
+ ): SessionMutationUnsubscribe;
145
141
  /**
146
142
  * 发布一条 session runtime 事件。
147
143
  *
@@ -149,7 +145,7 @@ export interface SessionPort {
149
145
  * - plugin runtime 用它把审批、外部进度等非模型 chunk 事件推送给订阅方。
150
146
  * - 历史消息持久化仍由 append_user_message / append_assistant_message 负责。
151
147
  */
152
- publishEvent(event: AgentSessionEvent): void;
148
+ publishEvent(event: SessionApprovalRuntimeEvent): Promise<void>;
153
149
  /**
154
150
  * 追加一条 user 消息。
155
151
  */
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Session 级工具审批类型。
3
+ *
4
+ * 审批由具体工具运行时执行,但归属、查询和决策能力统一通过 Session 暴露。
5
+ */
6
+
7
+ /** Session 工具审批的最终人工决策。 */
8
+ export type SessionApprovalDecision = "approved" | "denied";
9
+
10
+ /** Session 工具审批模式。 */
11
+ export type SessionApprovalMode = "ask" | "always-allow";
12
+
13
+ /** 当前 Session 的待审批工具请求。 */
14
+ export interface SessionApproval {
15
+ /** 当前审批请求的稳定唯一标识。 */
16
+ approval_id: string;
17
+ /** 当前审批所属 Session 标识。 */
18
+ session_id: string;
19
+ /** 当前审批所属 Turn 标识。 */
20
+ turn_id?: string;
21
+ /** 当前审批对应的工具调用标识。 */
22
+ tool_call_id?: string;
23
+ /** 当前审批对应的工具注册名称。 */
24
+ tool_name: string;
25
+ /** 请求执行的命令或输入文本。 */
26
+ command: string;
27
+ /** 当前工具执行工作目录。 */
28
+ cwd: string;
29
+ /** 工具申请 unrestricted 权限的原因。 */
30
+ reason: string;
31
+ /** 当前审批对应的工具操作类型。 */
32
+ operation: "exec" | "start" | "write";
33
+ /** 当前审批创建时间戳(ms)。 */
34
+ created_at: number;
35
+ }
36
+
37
+ /** 提交 Session 工具审批决策的参数。 */
38
+ export interface ResolveSessionApprovalInput {
39
+ /** 需要处理的审批请求标识。 */
40
+ approval_id: string;
41
+ /** 对当前审批请求作出的最终决定。 */
42
+ decision: SessionApprovalDecision;
43
+ }
44
+
45
+ /** Session 工具审批决策结果。 */
46
+ export interface SessionApprovalResult {
47
+ /** 是否成功命中并处理 pending 审批。 */
48
+ success: boolean;
49
+ /** 已尝试处理的审批请求标识。 */
50
+ approval_id: string;
51
+ /** 已提交的最终审批决定。 */
52
+ decision: SessionApprovalDecision;
53
+ }
54
+
55
+ /** 当前 Session 的审批模式快照。 */
56
+ export interface SessionApprovalModeSnapshot {
57
+ /** 当前审批模式所属 Session 标识。 */
58
+ session_id: string;
59
+ /** 当前 Session 生效的审批模式。 */
60
+ mode: SessionApprovalMode;
61
+ }
62
+
63
+ /** 更新当前 Session 审批模式的参数。 */
64
+ export interface SetSessionApprovalModeInput {
65
+ /** 需要设置的新审批模式。 */
66
+ mode: SessionApprovalMode;
67
+ }
68
+
69
+ /** Shell Runtime 发给 Session 的工具审批请求。 */
70
+ export interface SessionToolApprovalRequest {
71
+ /** Runtime 事件类型固定为工具审批请求。 */
72
+ type: "tool-approval-request";
73
+ /** 当前审批所属 Turn 标识。 */
74
+ turn_id: string;
75
+ /** 当前审批对应的工具调用标识。 */
76
+ tool_call_id: string;
77
+ /** 当前审批对应的工具注册名称。 */
78
+ tool_name: string;
79
+ /** 当前审批请求的稳定唯一标识。 */
80
+ approval_id: string;
81
+ /** 请求执行的命令或输入文本。 */
82
+ command: string;
83
+ /** 当前工具执行工作目录。 */
84
+ cwd: string;
85
+ /** 工具申请 unrestricted 权限的原因。 */
86
+ reason: string;
87
+ /** 当前审批对应的工具操作类型。 */
88
+ operation: "exec" | "start" | "write";
89
+ }
90
+
91
+ /** Shell Runtime 发给 Session 的工具审批结果。 */
92
+ export interface SessionToolApprovalResult {
93
+ /** Runtime 事件类型固定为工具审批结果。 */
94
+ type: "tool-approval-result";
95
+ /** 当前审批所属 Turn 标识。 */
96
+ turn_id: string;
97
+ /** 当前审批对应的工具调用标识。 */
98
+ tool_call_id: string;
99
+ /** 当前审批请求的稳定唯一标识。 */
100
+ approval_id: string;
101
+ /** 当前审批的最终结果,超时由 Runtime 标记为 expired。 */
102
+ decision: SessionApprovalDecision | "expired";
103
+ }
104
+
105
+ /** Session 内部接收的工具审批 Runtime 事件。 */
106
+ export type SessionApprovalRuntimeEvent =
107
+ | SessionToolApprovalRequest
108
+ | SessionToolApprovalResult;