@downcity/agent 1.1.22 → 1.1.23

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 (107) hide show
  1. package/README.md +6 -5
  2. package/bin/core/AgentContextTypes.d.ts +21 -2
  3. package/bin/core/AgentContextTypes.d.ts.map +1 -1
  4. package/bin/index.d.ts +5 -1
  5. package/bin/index.d.ts.map +1 -1
  6. package/bin/index.js.map +1 -1
  7. package/bin/runtime/server/http/Server.d.ts +1 -1
  8. package/bin/runtime/server/http/Server.d.ts.map +1 -1
  9. package/bin/runtime/server/http/Server.js +4 -0
  10. package/bin/runtime/server/http/Server.js.map +1 -1
  11. package/bin/runtime/server/http/control/ExecuteBySession.js +1 -1
  12. package/bin/runtime/server/http/control/ExecuteBySession.js.map +1 -1
  13. package/bin/runtime/server/http/control/StreamBySession.d.ts +3 -3
  14. package/bin/runtime/server/http/control/StreamBySession.js +6 -6
  15. package/bin/runtime/server/http/control/StreamBySession.js.map +1 -1
  16. package/bin/runtime/server/http/execute/execute.js +1 -1
  17. package/bin/runtime/server/http/execute/execute.js.map +1 -1
  18. package/bin/runtime/server/http/sdk/Router.d.ts +14 -0
  19. package/bin/runtime/server/http/sdk/Router.d.ts.map +1 -0
  20. package/bin/runtime/server/http/sdk/Router.js +18 -0
  21. package/bin/runtime/server/http/sdk/Router.js.map +1 -0
  22. package/bin/runtime/server/http/sdk/SessionRoutes.d.ts +15 -0
  23. package/bin/runtime/server/http/sdk/SessionRoutes.d.ts.map +1 -0
  24. package/bin/runtime/server/http/sdk/SessionRoutes.js +190 -0
  25. package/bin/runtime/server/http/sdk/SessionRoutes.js.map +1 -0
  26. package/bin/sdk/AgentSdkTypes.d.ts +1 -124
  27. package/bin/sdk/AgentSdkTypes.d.ts.map +1 -1
  28. package/bin/sdk/RemoteAgent.d.ts +27 -8
  29. package/bin/sdk/RemoteAgent.d.ts.map +1 -1
  30. package/bin/sdk/RemoteAgent.js +266 -38
  31. package/bin/sdk/RemoteAgent.js.map +1 -1
  32. package/bin/sdk/Session.d.ts +31 -10
  33. package/bin/sdk/Session.d.ts.map +1 -1
  34. package/bin/sdk/Session.js +181 -73
  35. package/bin/sdk/Session.js.map +1 -1
  36. package/bin/sdk/SessionEventMapper.d.ts +32 -0
  37. package/bin/sdk/SessionEventMapper.d.ts.map +1 -0
  38. package/bin/sdk/{StreamEvents.js → SessionEventMapper.js} +43 -28
  39. package/bin/sdk/SessionEventMapper.js.map +1 -0
  40. package/bin/sdk/session/ServicePort.d.ts +51 -4
  41. package/bin/sdk/session/ServicePort.d.ts.map +1 -1
  42. package/bin/sdk/session/ServicePort.js +17 -10
  43. package/bin/sdk/session/ServicePort.js.map +1 -1
  44. package/bin/sdk/session/runtime/SessionEventHub.d.ts +24 -0
  45. package/bin/sdk/session/runtime/SessionEventHub.d.ts.map +1 -0
  46. package/bin/sdk/session/runtime/SessionEventHub.js +39 -0
  47. package/bin/sdk/session/runtime/SessionEventHub.js.map +1 -0
  48. package/bin/sdk/session/runtime/SessionPromptRuntime.d.ts +68 -0
  49. package/bin/sdk/session/runtime/SessionPromptRuntime.d.ts.map +1 -0
  50. package/bin/sdk/session/runtime/SessionPromptRuntime.js +170 -0
  51. package/bin/sdk/session/runtime/SessionPromptRuntime.js.map +1 -0
  52. package/bin/service/builtins/chat/runtime/ChatQueueWorker.js +1 -1
  53. package/bin/service/builtins/chat/runtime/ChatQueueWorker.js.map +1 -1
  54. package/bin/service/builtins/chat/runtime/ChatSession.d.ts +1 -1
  55. package/bin/service/builtins/chat/runtime/ChatSession.js +1 -1
  56. package/bin/service/builtins/contact/runtime/ChatRuntime.js +1 -1
  57. package/bin/service/builtins/contact/runtime/ChatRuntime.js.map +1 -1
  58. package/bin/types/sdk/AgentSessionEvent.d.ts +160 -0
  59. package/bin/types/sdk/AgentSessionEvent.d.ts.map +1 -0
  60. package/bin/types/sdk/AgentSessionEvent.js +9 -0
  61. package/bin/types/sdk/AgentSessionEvent.js.map +1 -0
  62. package/bin/types/sdk/AgentSessionPrompt.d.ts +21 -0
  63. package/bin/types/sdk/AgentSessionPrompt.d.ts.map +1 -0
  64. package/bin/types/sdk/AgentSessionPrompt.js +9 -0
  65. package/bin/types/sdk/AgentSessionPrompt.js.map +1 -0
  66. package/bin/types/sdk/AgentSessionTurn.d.ts +59 -0
  67. package/bin/types/sdk/AgentSessionTurn.d.ts.map +1 -0
  68. package/bin/types/sdk/AgentSessionTurn.js +10 -0
  69. package/bin/types/sdk/AgentSessionTurn.js.map +1 -0
  70. package/bin/types/sdk/AgentUiChunkEvent.d.ts +100 -0
  71. package/bin/types/sdk/AgentUiChunkEvent.d.ts.map +1 -0
  72. package/bin/types/sdk/AgentUiChunkEvent.js +9 -0
  73. package/bin/types/sdk/AgentUiChunkEvent.js.map +1 -0
  74. package/package.json +2 -1
  75. package/scripts/session-prompt-runtime.test.mjs +167 -0
  76. package/src/core/AgentContextTypes.ts +24 -2
  77. package/src/index.ts +11 -3
  78. package/src/runtime/server/http/Server.ts +5 -1
  79. package/src/runtime/server/http/control/ExecuteBySession.ts +1 -1
  80. package/src/runtime/server/http/control/StreamBySession.ts +11 -11
  81. package/src/runtime/server/http/execute/execute.ts +1 -1
  82. package/src/runtime/server/http/sdk/Router.ts +22 -0
  83. package/src/runtime/server/http/sdk/SessionRoutes.ts +232 -0
  84. package/src/sdk/AgentSdkTypes.ts +1 -137
  85. package/src/sdk/RemoteAgent.ts +368 -49
  86. package/src/sdk/Session.ts +235 -86
  87. package/src/sdk/{StreamEvents.ts → SessionEventMapper.ts} +50 -40
  88. package/src/sdk/session/ServicePort.ts +74 -12
  89. package/src/sdk/session/runtime/SessionEventHub.ts +47 -0
  90. package/src/sdk/session/runtime/SessionPromptRuntime.ts +269 -0
  91. package/src/service/builtins/chat/runtime/ChatQueueWorker.ts +1 -1
  92. package/src/service/builtins/chat/runtime/ChatSession.ts +1 -1
  93. package/src/service/builtins/contact/runtime/ChatRuntime.ts +1 -1
  94. package/src/session/README.md +8 -7
  95. package/src/types/sdk/AgentSessionEvent.ts +195 -0
  96. package/src/types/sdk/AgentSessionPrompt.ts +21 -0
  97. package/src/types/sdk/AgentSessionTurn.ts +65 -0
  98. package/src/types/sdk/AgentUiChunkEvent.ts +108 -0
  99. package/tsconfig.tsbuildinfo +1 -1
  100. package/bin/sdk/AsyncQueue.d.ts +0 -26
  101. package/bin/sdk/AsyncQueue.d.ts.map +0 -1
  102. package/bin/sdk/AsyncQueue.js +0 -75
  103. package/bin/sdk/AsyncQueue.js.map +0 -1
  104. package/bin/sdk/StreamEvents.d.ts +0 -36
  105. package/bin/sdk/StreamEvents.d.ts.map +0 -1
  106. package/bin/sdk/StreamEvents.js.map +0 -1
  107. package/src/sdk/AsyncQueue.ts +0 -92
@@ -0,0 +1,160 @@
1
+ /**
2
+ * Agent Session 事件类型定义。
3
+ *
4
+ * 关键点(中文)
5
+ * - `subscribe()` 暴露的是 session 级长期事件序列,而不是单次执行的局部结果。
6
+ * - 事件只表达“当前 turn 正在发生什么”,不负责历史回放。
7
+ */
8
+ import type { JsonValue } from "../../types/common/Json.js";
9
+ /**
10
+ * 单个 turn 开始事件。
11
+ */
12
+ export interface AgentSessionTurnStartEvent {
13
+ /**
14
+ * 当前事件类型。
15
+ */
16
+ type: "turn-start";
17
+ /**
18
+ * 当前 turn 的稳定标识。
19
+ *
20
+ * 说明(中文)
21
+ * - 同一个 turn 内的全部增量事件都会复用这个 turnId。
22
+ * - 当 Session 排队进入下一轮时,会生成新的 turnId。
23
+ */
24
+ turnId: string;
25
+ }
26
+ /**
27
+ * 普通文本增量事件。
28
+ */
29
+ export interface AgentSessionTextDeltaEvent {
30
+ /**
31
+ * 当前事件类型。
32
+ */
33
+ type: "text-delta";
34
+ /**
35
+ * 当前文本所属 turn。
36
+ */
37
+ turnId: string;
38
+ /**
39
+ * 当前这次新增的可见文本片段。
40
+ */
41
+ text: string;
42
+ }
43
+ /**
44
+ * reasoning 文本增量事件。
45
+ */
46
+ export interface AgentSessionReasoningDeltaEvent {
47
+ /**
48
+ * 当前事件类型。
49
+ */
50
+ type: "reasoning-delta";
51
+ /**
52
+ * 当前 reasoning 所属 turn。
53
+ */
54
+ turnId: string;
55
+ /**
56
+ * 当前这次新增的 reasoning 文本片段。
57
+ */
58
+ text: string;
59
+ }
60
+ /**
61
+ * 工具调用事件。
62
+ */
63
+ export interface AgentSessionToolCallEvent {
64
+ /**
65
+ * 当前事件类型。
66
+ */
67
+ type: "tool-call";
68
+ /**
69
+ * 当前工具调用所属 turn。
70
+ */
71
+ turnId: string;
72
+ /**
73
+ * 当前工具调用唯一标识。
74
+ */
75
+ toolCallId: string;
76
+ /**
77
+ * 当前工具名称。
78
+ */
79
+ toolName: string;
80
+ /**
81
+ * 当前工具输入参数。
82
+ */
83
+ args: JsonValue;
84
+ }
85
+ /**
86
+ * 工具结果事件。
87
+ */
88
+ export interface AgentSessionToolResultEvent {
89
+ /**
90
+ * 当前事件类型。
91
+ */
92
+ type: "tool-result";
93
+ /**
94
+ * 当前工具结果所属 turn。
95
+ */
96
+ turnId: string;
97
+ /**
98
+ * 当前工具调用唯一标识。
99
+ */
100
+ toolCallId: string;
101
+ /**
102
+ * 当前工具名称。
103
+ */
104
+ toolName: string;
105
+ /**
106
+ * 当前工具输出结果。
107
+ */
108
+ result: JsonValue;
109
+ }
110
+ /**
111
+ * 单个 turn 完成事件。
112
+ */
113
+ export interface AgentSessionTurnFinishEvent {
114
+ /**
115
+ * 当前事件类型。
116
+ */
117
+ type: "turn-finish";
118
+ /**
119
+ * 当前已完成 turn 的稳定标识。
120
+ */
121
+ turnId: string;
122
+ /**
123
+ * 当前 turn 最终可见文本。
124
+ */
125
+ text: string;
126
+ /**
127
+ * 当前 turn 是否成功结束。
128
+ */
129
+ success: boolean;
130
+ /**
131
+ * 当前 turn 失败时的错误文本。
132
+ */
133
+ error?: string;
134
+ }
135
+ /**
136
+ * Session 级错误事件。
137
+ */
138
+ export interface AgentSessionErrorEvent {
139
+ /**
140
+ * 当前事件类型。
141
+ */
142
+ type: "error";
143
+ /**
144
+ * 当前错误文本。
145
+ */
146
+ message: string;
147
+ }
148
+ /**
149
+ * Session 订阅可见事件联合类型。
150
+ */
151
+ export type AgentSessionEvent = AgentSessionTurnStartEvent | AgentSessionTextDeltaEvent | AgentSessionReasoningDeltaEvent | AgentSessionToolCallEvent | AgentSessionToolResultEvent | AgentSessionTurnFinishEvent | AgentSessionErrorEvent;
152
+ /**
153
+ * Session 事件订阅回调。
154
+ */
155
+ export type AgentSessionSubscriber = (event: AgentSessionEvent) => void;
156
+ /**
157
+ * 取消 Session 订阅的返回函数。
158
+ */
159
+ export type AgentSessionUnsubscribe = () => void;
160
+ //# sourceMappingURL=AgentSessionEvent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AgentSessionEvent.d.ts","sourceRoot":"","sources":["../../../src/types/sdk/AgentSessionEvent.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAExD;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC;;OAEG;IACH,IAAI,EAAE,YAAY,CAAC;IAEnB;;;;;;OAMG;IACH,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC;;OAEG;IACH,IAAI,EAAE,YAAY,CAAC;IAEnB;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,+BAA+B;IAC9C;;OAEG;IACH,IAAI,EAAE,iBAAiB,CAAC;IAExB;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC;;OAEG;IACH,IAAI,EAAE,WAAW,CAAC;IAElB;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,IAAI,EAAE,SAAS,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C;;OAEG;IACH,IAAI,EAAE,aAAa,CAAC;IAEpB;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,MAAM,EAAE,SAAS,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C;;OAEG;IACH,IAAI,EAAE,aAAa,CAAC;IAEpB;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,OAAO,EAAE,OAAO,CAAC;IAEjB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC;;OAEG;IACH,IAAI,EAAE,OAAO,CAAC;IAEd;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,MAAM,iBAAiB,GACzB,0BAA0B,GAC1B,0BAA0B,GAC1B,+BAA+B,GAC/B,yBAAyB,GACzB,2BAA2B,GAC3B,2BAA2B,GAC3B,sBAAsB,CAAC;AAE3B;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC;AAExE;;GAEG;AACH,MAAM,MAAM,uBAAuB,GAAG,MAAM,IAAI,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Agent Session 事件类型定义。
3
+ *
4
+ * 关键点(中文)
5
+ * - `subscribe()` 暴露的是 session 级长期事件序列,而不是单次执行的局部结果。
6
+ * - 事件只表达“当前 turn 正在发生什么”,不负责历史回放。
7
+ */
8
+ export {};
9
+ //# sourceMappingURL=AgentSessionEvent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AgentSessionEvent.js","sourceRoot":"","sources":["../../../src/types/sdk/AgentSessionEvent.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Agent Session prompt 输入类型定义。
3
+ *
4
+ * 关键点(中文)
5
+ * - `prompt()` 是 Session actor 模型下唯一的输入入口。
6
+ * - 首条输入、运行中补充输入、排队到下一轮的输入,调用侧都使用同一结构。
7
+ */
8
+ /**
9
+ * Session prompt 输入。
10
+ */
11
+ export interface AgentSessionPromptInput {
12
+ /**
13
+ * 当前这次要追加到 Session 的用户文本。
14
+ *
15
+ * 说明(中文)
16
+ * - 调用侧永远只传“新的用户输入”。
17
+ * - 它是否并入当前 turn,还是排到下一 turn,由 Session 内部决定。
18
+ */
19
+ query: string;
20
+ }
21
+ //# sourceMappingURL=AgentSessionPrompt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AgentSessionPrompt.d.ts","sourceRoot":"","sources":["../../../src/types/sdk/AgentSessionPrompt.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC;;;;;;OAMG;IACH,KAAK,EAAE,MAAM,CAAC;CACf"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Agent Session prompt 输入类型定义。
3
+ *
4
+ * 关键点(中文)
5
+ * - `prompt()` 是 Session actor 模型下唯一的输入入口。
6
+ * - 首条输入、运行中补充输入、排队到下一轮的输入,调用侧都使用同一结构。
7
+ */
8
+ export {};
9
+ //# sourceMappingURL=AgentSessionPrompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AgentSessionPrompt.js","sourceRoot":"","sources":["../../../src/types/sdk/AgentSessionPrompt.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Agent Session turn 句柄与结果类型定义。
3
+ *
4
+ * 关键点(中文)
5
+ * - `session.prompt()` 返回的是“已绑定到某个 turn”的句柄,而不是一次性文本结果。
6
+ * - 同一个 turn 可以吸收多条 prompt,因此多个 prompt 可能返回相同 `id` 的 turn handle。
7
+ * - 增量过程继续通过 `session.subscribe()` 观察;turn handle 只负责等待最终完成结果。
8
+ */
9
+ /**
10
+ * 单个 Session turn 的最终结果。
11
+ */
12
+ export interface AgentSessionTurnResult {
13
+ /**
14
+ * 当前已完成 turn 的稳定标识。
15
+ */
16
+ turnId: string;
17
+ /**
18
+ * 当前 turn 最终可见文本。
19
+ */
20
+ text: string;
21
+ /**
22
+ * 当前 turn 是否成功结束。
23
+ */
24
+ success: boolean;
25
+ /**
26
+ * 当前 turn 失败时的错误文本。
27
+ */
28
+ error?: string;
29
+ }
30
+ /**
31
+ * 单个 Session turn 的等待句柄。
32
+ */
33
+ export interface AgentSessionTurnHandle {
34
+ /**
35
+ * 当前句柄绑定到的 turnId。
36
+ *
37
+ * 说明(中文)
38
+ * - `prompt()` 只有在确定当前输入被并入哪个 turn 后才会返回。
39
+ * - 因此这里总是最终可用的 turnId,而不是临时 receipt id。
40
+ */
41
+ id: string;
42
+ /**
43
+ * 当前 turn 已完成后的最终结果快照。
44
+ *
45
+ * 说明(中文)
46
+ * - 在 `finished` 兑现之前这里为 `null`。
47
+ * - 兑现之后会变成与 `finished` 相同的最终结果对象。
48
+ */
49
+ result: AgentSessionTurnResult | null;
50
+ /**
51
+ * 等待当前 turn 完成的 Promise。
52
+ *
53
+ * 关键点(中文)
54
+ * - 这里无论 turn 成功还是失败都会 resolve。
55
+ * - 调用方应读取返回结果中的 `success` / `error` 判断最终状态。
56
+ */
57
+ finished: Promise<AgentSessionTurnResult>;
58
+ }
59
+ //# sourceMappingURL=AgentSessionTurn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AgentSessionTurn.d.ts","sourceRoot":"","sources":["../../../src/types/sdk/AgentSessionTurn.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,OAAO,EAAE,OAAO,CAAC;IAEjB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;;;;OAMG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;;;;;OAMG;IACH,MAAM,EAAE,sBAAsB,GAAG,IAAI,CAAC;IAEtC;;;;;;OAMG;IACH,QAAQ,EAAE,OAAO,CAAC,sBAAsB,CAAC,CAAC;CAC3C"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Agent Session turn 句柄与结果类型定义。
3
+ *
4
+ * 关键点(中文)
5
+ * - `session.prompt()` 返回的是“已绑定到某个 turn”的句柄,而不是一次性文本结果。
6
+ * - 同一个 turn 可以吸收多条 prompt,因此多个 prompt 可能返回相同 `id` 的 turn handle。
7
+ * - 增量过程继续通过 `session.subscribe()` 观察;turn handle 只负责等待最终完成结果。
8
+ */
9
+ export {};
10
+ //# sourceMappingURL=AgentSessionTurn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AgentSessionTurn.js","sourceRoot":"","sources":["../../../src/types/sdk/AgentSessionTurn.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Agent UI chunk 事件类型定义。
3
+ *
4
+ * 关键点(中文)
5
+ * - 这是内部传输/映射层事件,不是 Session 的公开订阅事件。
6
+ * - 它用于把底层 AI SDK `UIMessageChunk` 归一化,再按不同宿主场景转成最终输出。
7
+ */
8
+ import type { JsonValue } from "../../types/common/Json.js";
9
+ /**
10
+ * 内部 UI chunk 事件。
11
+ */
12
+ export type AgentUiChunkEvent = {
13
+ /**
14
+ * 文本增量事件。
15
+ */
16
+ type: "text-delta";
17
+ /**
18
+ * 当前追加的文本片段。
19
+ */
20
+ text: string;
21
+ } | {
22
+ /**
23
+ * reasoning 增量事件。
24
+ */
25
+ type: "reasoning-delta";
26
+ /**
27
+ * 当前追加的 reasoning 文本片段。
28
+ */
29
+ text: string;
30
+ } | {
31
+ /**
32
+ * 工具调用可用事件。
33
+ */
34
+ type: "tool-call";
35
+ /**
36
+ * 当前工具调用唯一标识。
37
+ */
38
+ toolCallId: string;
39
+ /**
40
+ * 工具名称。
41
+ */
42
+ toolName: string;
43
+ /**
44
+ * 工具输入参数。
45
+ */
46
+ args: JsonValue;
47
+ } | {
48
+ /**
49
+ * 工具调用结果事件。
50
+ */
51
+ type: "tool-result";
52
+ /**
53
+ * 当前工具调用唯一标识。
54
+ */
55
+ toolCallId: string;
56
+ /**
57
+ * 工具名称。
58
+ */
59
+ toolName: string;
60
+ /**
61
+ * 工具输出结果。
62
+ */
63
+ result: JsonValue;
64
+ } | {
65
+ /**
66
+ * 工具调用失败事件。
67
+ */
68
+ type: "tool-error";
69
+ /**
70
+ * 当前工具调用唯一标识。
71
+ */
72
+ toolCallId: string;
73
+ /**
74
+ * 工具名称。
75
+ */
76
+ toolName: string;
77
+ /**
78
+ * 错误文本。
79
+ */
80
+ error: string;
81
+ } | {
82
+ /**
83
+ * 运行结束事件。
84
+ */
85
+ type: "finish";
86
+ /**
87
+ * 最终完成原因(若底层可提供)。
88
+ */
89
+ finishReason?: string;
90
+ } | {
91
+ /**
92
+ * 运行错误事件。
93
+ */
94
+ type: "error";
95
+ /**
96
+ * 错误文本。
97
+ */
98
+ error: string;
99
+ };
100
+ //# sourceMappingURL=AgentUiChunkEvent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AgentUiChunkEvent.d.ts","sourceRoot":"","sources":["../../../src/types/sdk/AgentUiChunkEvent.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAExD;;GAEG;AACH,MAAM,MAAM,iBAAiB,GACzB;IACE;;OAEG;IACH,IAAI,EAAE,YAAY,CAAC;IACnB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;CACd,GACD;IACE;;OAEG;IACH,IAAI,EAAE,iBAAiB,CAAC;IACxB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;CACd,GACD;IACE;;OAEG;IACH,IAAI,EAAE,WAAW,CAAC;IAClB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,IAAI,EAAE,SAAS,CAAC;CACjB,GACD;IACE;;OAEG;IACH,IAAI,EAAE,aAAa,CAAC;IACpB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,MAAM,EAAE,SAAS,CAAC;CACnB,GACD;IACE;;OAEG;IACH,IAAI,EAAE,YAAY,CAAC;IACnB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;CACf,GACD;IACE;;OAEG;IACH,IAAI,EAAE,QAAQ,CAAC;IACf;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GACD;IACE;;OAEG;IACH,IAAI,EAAE,OAAO,CAAC;IACd;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;CACf,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Agent UI chunk 事件类型定义。
3
+ *
4
+ * 关键点(中文)
5
+ * - 这是内部传输/映射层事件,不是 Session 的公开订阅事件。
6
+ * - 它用于把底层 AI SDK `UIMessageChunk` 归一化,再按不同宿主场景转成最终输出。
7
+ */
8
+ export {};
9
+ //# sourceMappingURL=AgentUiChunkEvent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AgentUiChunkEvent.js","sourceRoot":"","sources":["../../../src/types/sdk/AgentUiChunkEvent.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@downcity/agent",
3
- "version": "1.1.22",
3
+ "version": "1.1.23",
4
4
  "type": "module",
5
5
  "description": "Downcity Agent 运行时 — 执行壳,通过 RPC/HTTP 调用 City 的能力",
6
6
  "main": "./bin/index.js",
@@ -45,6 +45,7 @@
45
45
  "scripts": {
46
46
  "build": "node scripts/agent-compiler.mjs build",
47
47
  "dev": "node scripts/agent-compiler.mjs dev",
48
+ "test:session-runtime": "pnpm build && node --test scripts/session-prompt-runtime.test.mjs",
48
49
  "typecheck": "node scripts/agent-compiler.mjs typecheck"
49
50
  }
50
51
  }
@@ -0,0 +1,167 @@
1
+ /**
2
+ * @file 验证 SessionPromptRuntime 的 actor 队列语义。
3
+ *
4
+ * 关键点(中文)
5
+ * - 测试编译后的 bin 输出,避免把测试文件混入 package 源码导出面。
6
+ * - 重点锁住 prompt merge 与排队到下一 turn 的行为,防止后续重构破坏交互模型。
7
+ */
8
+
9
+ import test from "node:test";
10
+ import assert from "node:assert/strict";
11
+
12
+ import { SessionPromptRuntime } from "../bin/sdk/session/runtime/SessionPromptRuntime.js";
13
+
14
+ function createDeferred() {
15
+ let resolve;
16
+ const promise = new Promise((innerResolve) => {
17
+ resolve = innerResolve;
18
+ });
19
+ return {
20
+ promise,
21
+ resolve,
22
+ };
23
+ }
24
+
25
+ function createUserMessage(query, index) {
26
+ return {
27
+ id: `u:test:${String(index)}`,
28
+ role: "user",
29
+ metadata: {
30
+ v: 1,
31
+ ts: Date.now(),
32
+ sessionId: "test",
33
+ source: "sdk",
34
+ kind: "normal",
35
+ },
36
+ parts: [{ type: "text", text: query }],
37
+ };
38
+ }
39
+
40
+ async function waitUntil(readValue) {
41
+ for (let index = 0; index < 20; index += 1) {
42
+ const value = readValue();
43
+ if (value) return value;
44
+ await new Promise((resolve) => setTimeout(resolve, 0));
45
+ }
46
+ throw new Error("Timed out while waiting for test condition");
47
+ }
48
+
49
+ async function isSettled(promise) {
50
+ const marker = {};
51
+ const result = await Promise.race([
52
+ promise.then(
53
+ () => true,
54
+ () => true,
55
+ ),
56
+ new Promise((resolve) => setTimeout(() => resolve(marker), 0)),
57
+ ]);
58
+ return result !== marker;
59
+ }
60
+
61
+ test("SessionPromptRuntime merges queued prompts at the next step boundary", async () => {
62
+ const events = [];
63
+ const persisted = [];
64
+ const executionFinished = createDeferred();
65
+ let stepMerge = null;
66
+
67
+ const runtime = new SessionPromptRuntime({
68
+ sessionId: "test",
69
+ publish: (event) => {
70
+ events.push(event);
71
+ },
72
+ createAndPersistUserMessage: async (query) => {
73
+ const message = createUserMessage(query, persisted.length + 1);
74
+ persisted.push(message);
75
+ return message;
76
+ },
77
+ executeTurn: async (input) => {
78
+ stepMerge = input.onStepMerge;
79
+ await executionFinished.promise;
80
+ return {
81
+ text: "done",
82
+ success: true,
83
+ };
84
+ },
85
+ });
86
+
87
+ const firstTurn = await runtime.prompt("first");
88
+ const secondTurnPromise = runtime.prompt("second");
89
+ const merge = await waitUntil(() => stepMerge);
90
+
91
+ assert.equal(await isSettled(secondTurnPromise), false);
92
+
93
+ const mergedMessages = await merge();
94
+ const secondTurn = await secondTurnPromise;
95
+
96
+ assert.equal(secondTurn.id, firstTurn.id);
97
+ assert.deepEqual(
98
+ mergedMessages.map((message) => message.parts[0]?.text),
99
+ ["second"],
100
+ );
101
+ assert.deepEqual(
102
+ persisted.map((message) => message.parts[0]?.text),
103
+ ["first", "second"],
104
+ );
105
+
106
+ executionFinished.resolve();
107
+ const result = await firstTurn.finished;
108
+
109
+ assert.equal(result.success, true);
110
+ assert.equal(result.text, "done");
111
+ assert.equal(secondTurn.result, result);
112
+ assert.deepEqual(
113
+ events.map((event) => event.type),
114
+ ["turn-start", "turn-finish"],
115
+ );
116
+ });
117
+
118
+ test("SessionPromptRuntime moves unmerged prompts into the next turn", async () => {
119
+ const events = [];
120
+ const finishQueue = [];
121
+
122
+ const runtime = new SessionPromptRuntime({
123
+ sessionId: "test",
124
+ publish: (event) => {
125
+ events.push(event);
126
+ },
127
+ createAndPersistUserMessage: async (query) => {
128
+ return createUserMessage(query, events.length + 1);
129
+ },
130
+ executeTurn: async (input) => {
131
+ const deferred = createDeferred();
132
+ finishQueue.push({
133
+ query: input.query,
134
+ deferred,
135
+ });
136
+ await deferred.promise;
137
+ return {
138
+ text: `done:${input.query}`,
139
+ success: true,
140
+ };
141
+ },
142
+ });
143
+
144
+ const firstTurn = await runtime.prompt("first");
145
+ const secondTurnPromise = runtime.prompt("second");
146
+ const firstExecution = await waitUntil(() => finishQueue[0]);
147
+
148
+ assert.equal(await isSettled(secondTurnPromise), false);
149
+
150
+ firstExecution.deferred.resolve();
151
+ const firstResult = await firstTurn.finished;
152
+ const secondTurn = await secondTurnPromise;
153
+ const secondExecution = await waitUntil(() => finishQueue[1]);
154
+
155
+ assert.notEqual(secondTurn.id, firstTurn.id);
156
+ assert.equal(firstResult.text, "done:first");
157
+ assert.equal(secondExecution.query, "second");
158
+
159
+ secondExecution.deferred.resolve();
160
+ const secondResult = await secondTurn.finished;
161
+
162
+ assert.equal(secondResult.text, "done:second");
163
+ assert.deepEqual(
164
+ events.map((event) => event.type),
165
+ ["turn-start", "turn-finish", "turn-start", "turn-finish"],
166
+ );
167
+ });
@@ -34,6 +34,12 @@ import type {
34
34
  SessionRunResult,
35
35
  } from "@/session/types/SessionRun.js";
36
36
  import type { SessionHistoryStore } from "@/session/store/history/SessionHistoryStore.js";
37
+ import type { AgentSessionPromptInput } from "@/types/sdk/AgentSessionPrompt.js";
38
+ import type {
39
+ AgentSessionSubscriber,
40
+ AgentSessionUnsubscribe,
41
+ } from "@/types/sdk/AgentSessionEvent.js";
42
+ import type { AgentSessionTurnHandle } from "@/types/sdk/AgentSessionTurn.js";
37
43
 
38
44
  /**
39
45
  * 跨 service 调用参数。
@@ -116,9 +122,9 @@ export interface SessionPort {
116
122
  */
117
123
  getHistoryStore(): SessionHistoryStore;
118
124
  /**
119
- * 执行当前 session 的一次请求。
125
+ * 执行当前 session 的一次内部请求。
120
126
  */
121
- run(params: {
127
+ execute(params: {
122
128
  /**
123
129
  * 本轮输入文本。
124
130
  */
@@ -132,6 +138,22 @@ export interface SessionPort {
132
138
  */
133
139
  onAssistantStepCallback?: SessionAssistantStepCallback;
134
140
  }): Promise<SessionRunResult>;
141
+ /**
142
+ * 向当前 session actor 追加一条新的 prompt。
143
+ *
144
+ * 关键点(中文)
145
+ * - 这是面向 SDK / transport 的统一交互输入入口。
146
+ * - 返回值只有在当前输入被绑定到某个 turn 后才会兑现。
147
+ */
148
+ prompt(input: AgentSessionPromptInput): Promise<AgentSessionTurnHandle>;
149
+ /**
150
+ * 订阅当前 session 后续产生的 future 事件。
151
+ *
152
+ * 关键点(中文)
153
+ * - 只广播订阅之后产生的事件。
154
+ * - 历史消息仍通过 `getHistoryStore()` / SDK `history()` 读取。
155
+ */
156
+ subscribe(subscriber: AgentSessionSubscriber): AgentSessionUnsubscribe;
135
157
  /**
136
158
  * 清理当前 session 的 executor 缓存。
137
159
  */
package/src/index.ts CHANGED
@@ -24,15 +24,23 @@ export type {
24
24
  AgentSessionConfigSnapshot,
25
25
  AgentSessionForkInput,
26
26
  AgentSessionMetadata,
27
- AgentSessionRunInput,
28
- AgentSessionRunResult,
29
27
  AgentSessionSetInput,
30
- AgentSessionStreamEvent,
31
28
  AgentSessionSystemBlock,
32
29
  AgentSessionSystemBlockSource,
33
30
  AgentSessionSystemSessionInfo,
34
31
  AgentSessionSystemSnapshot,
35
32
  } from "./sdk/AgentSdkTypes.js";
33
+ export type {
34
+ AgentSessionEvent,
35
+ AgentSessionSubscriber,
36
+ AgentSessionUnsubscribe,
37
+ } from "./types/sdk/AgentSessionEvent.js";
38
+ export type { AgentSessionPromptInput } from "./types/sdk/AgentSessionPrompt.js";
39
+ export type {
40
+ AgentSessionTurnHandle,
41
+ AgentSessionTurnResult,
42
+ } from "./types/sdk/AgentSessionTurn.js";
43
+ export type { AgentUiChunkEvent } from "./types/sdk/AgentUiChunkEvent.js";
36
44
  export type {
37
45
  AgentRuntime as AgentCoreRuntime,
38
46
  AgentRuntimeBase as AgentCoreRuntimeBase,