@downcity/agent 1.1.129 → 1.1.148

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 (228) hide show
  1. package/README.md +2 -2
  2. package/bin/agent/local/Agent.d.ts +40 -26
  3. package/bin/agent/local/Agent.d.ts.map +1 -1
  4. package/bin/agent/local/Agent.js +65 -41
  5. package/bin/agent/local/Agent.js.map +1 -1
  6. package/bin/agent/local/ProjectSetup.js +2 -2
  7. package/bin/agent/local/ProjectSetup.js.map +1 -1
  8. package/bin/agent/local/services/AgentAssemblyService.d.ts +2 -7
  9. package/bin/agent/local/services/AgentAssemblyService.d.ts.map +1 -1
  10. package/bin/agent/local/services/AgentAssemblyService.js +34 -22
  11. package/bin/agent/local/services/AgentAssemblyService.js.map +1 -1
  12. package/bin/agent/local/services/AgentBackgroundService.d.ts +55 -0
  13. package/bin/agent/local/services/AgentBackgroundService.d.ts.map +1 -0
  14. package/bin/agent/local/services/AgentBackgroundService.js +86 -0
  15. package/bin/agent/local/services/AgentBackgroundService.js.map +1 -0
  16. package/bin/agent/local/services/AgentSessionManager.d.ts +16 -7
  17. package/bin/agent/local/services/AgentSessionManager.d.ts.map +1 -1
  18. package/bin/agent/local/services/AgentSessionManager.js +83 -8
  19. package/bin/agent/local/services/AgentSessionManager.js.map +1 -1
  20. package/bin/agent/remote/RemoteAgent.d.ts +9 -13
  21. package/bin/agent/remote/RemoteAgent.d.ts.map +1 -1
  22. package/bin/agent/remote/RemoteAgent.js +23 -24
  23. package/bin/agent/remote/RemoteAgent.js.map +1 -1
  24. package/bin/agent/remote/RemoteSession.d.ts +11 -4
  25. package/bin/agent/remote/RemoteSession.d.ts.map +1 -1
  26. package/bin/agent/remote/RemoteSession.js +15 -3
  27. package/bin/agent/remote/RemoteSession.js.map +1 -1
  28. package/bin/agent/remote/RemoteTransport.d.ts +9 -1
  29. package/bin/agent/remote/RemoteTransport.d.ts.map +1 -1
  30. package/bin/agent/remote/transports/HttpRemoteAgentTransport.d.ts +7 -3
  31. package/bin/agent/remote/transports/HttpRemoteAgentTransport.d.ts.map +1 -1
  32. package/bin/agent/remote/transports/HttpRemoteAgentTransport.js +65 -2
  33. package/bin/agent/remote/transports/HttpRemoteAgentTransport.js.map +1 -1
  34. package/bin/agent/remote/transports/RpcRemoteAgentTransport.d.ts +5 -1
  35. package/bin/agent/remote/transports/RpcRemoteAgentTransport.d.ts.map +1 -1
  36. package/bin/agent/remote/transports/RpcRemoteAgentTransport.js +12 -0
  37. package/bin/agent/remote/transports/RpcRemoteAgentTransport.js.map +1 -1
  38. package/bin/config/AgentInitializer.d.ts +2 -2
  39. package/bin/config/AgentInitializer.js +2 -2
  40. package/bin/executor/Executor.d.ts +5 -0
  41. package/bin/executor/Executor.d.ts.map +1 -1
  42. package/bin/executor/Executor.js +34 -0
  43. package/bin/executor/Executor.js.map +1 -1
  44. package/bin/executor/composer/system/default/InitPrompts.d.ts +1 -1
  45. package/bin/executor/composer/system/default/InitPrompts.js +1 -1
  46. package/bin/executor/composer/system/default/SystemDomain.js +2 -2
  47. package/bin/executor/composer/system/default/SystemDomain.js.map +1 -1
  48. package/bin/executor/core-engine/CoreEngineRunner.d.ts.map +1 -1
  49. package/bin/executor/core-engine/CoreEngineRunner.js +16 -0
  50. package/bin/executor/core-engine/CoreEngineRunner.js.map +1 -1
  51. package/bin/executor/messages/ChatMessageMarkupTypes.d.ts +1 -1
  52. package/bin/executor/messages/ChatMessageMarkupTypes.js +1 -1
  53. package/bin/executor/store/history/jsonl/JsonlSessionHistoryStore.d.ts +8 -0
  54. package/bin/executor/store/history/jsonl/JsonlSessionHistoryStore.d.ts.map +1 -1
  55. package/bin/executor/store/history/jsonl/JsonlSessionHistoryStore.js +22 -0
  56. package/bin/executor/store/history/jsonl/JsonlSessionHistoryStore.js.map +1 -1
  57. package/bin/executor/types/SessionExecutor.d.ts +8 -0
  58. package/bin/executor/types/SessionExecutor.d.ts.map +1 -1
  59. package/bin/index.d.ts +4 -4
  60. package/bin/index.d.ts.map +1 -1
  61. package/bin/index.js +1 -2
  62. package/bin/index.js.map +1 -1
  63. package/bin/plugin/core/Activation.d.ts +0 -2
  64. package/bin/plugin/core/Activation.d.ts.map +1 -1
  65. package/bin/plugin/core/Activation.js +1 -1
  66. package/bin/plugin/core/Activation.js.map +1 -1
  67. package/bin/plugin/core/PluginCommandRequest.d.ts +1 -1
  68. package/bin/plugin/core/PluginCommandRequest.js +1 -1
  69. package/bin/plugin/core/PluginStateController.d.ts +0 -5
  70. package/bin/plugin/core/PluginStateController.d.ts.map +1 -1
  71. package/bin/plugin/core/PluginStateController.js +1 -5
  72. package/bin/plugin/core/PluginStateController.js.map +1 -1
  73. package/bin/plugin/types/PluginApi.d.ts +1 -1
  74. package/bin/plugin/types/PluginApi.js +1 -1
  75. package/bin/rpc/Client.d.ts +17 -1
  76. package/bin/rpc/Client.d.ts.map +1 -1
  77. package/bin/rpc/Client.js +47 -0
  78. package/bin/rpc/Client.js.map +1 -1
  79. package/bin/session/Session.d.ts +5 -0
  80. package/bin/session/Session.d.ts.map +1 -1
  81. package/bin/session/Session.js +7 -0
  82. package/bin/session/Session.js.map +1 -1
  83. package/bin/session/browse/Browse.d.ts +9 -1
  84. package/bin/session/browse/Browse.d.ts.map +1 -1
  85. package/bin/session/browse/Browse.js +81 -3
  86. package/bin/session/browse/Browse.js.map +1 -1
  87. package/bin/session/index.d.ts +3 -3
  88. package/bin/session/index.d.ts.map +1 -1
  89. package/bin/session/index.js +3 -3
  90. package/bin/session/index.js.map +1 -1
  91. package/bin/session/runtime/SessionPromptRuntime.d.ts +13 -0
  92. package/bin/session/runtime/SessionPromptRuntime.d.ts.map +1 -1
  93. package/bin/session/runtime/SessionPromptRuntime.js +82 -5
  94. package/bin/session/runtime/SessionPromptRuntime.js.map +1 -1
  95. package/bin/session/services/SessionTurnService.d.ts +5 -0
  96. package/bin/session/services/SessionTurnService.d.ts.map +1 -1
  97. package/bin/session/services/SessionTurnService.js +10 -1
  98. package/bin/session/services/SessionTurnService.js.map +1 -1
  99. package/bin/session/services/SessionViewService.d.ts.map +1 -1
  100. package/bin/session/services/SessionViewService.js +1 -7
  101. package/bin/session/services/SessionViewService.js.map +1 -1
  102. package/bin/session/storage/Metadata.d.ts +15 -0
  103. package/bin/session/storage/Metadata.d.ts.map +1 -1
  104. package/bin/session/storage/Metadata.js +15 -1
  105. package/bin/session/storage/Metadata.js.map +1 -1
  106. package/bin/session/storage/Paths.d.ts +24 -0
  107. package/bin/session/storage/Paths.d.ts.map +1 -1
  108. package/bin/session/storage/Paths.js +34 -0
  109. package/bin/session/storage/Paths.js.map +1 -1
  110. package/bin/session/storage/RuntimeSessionPort.d.ts +5 -0
  111. package/bin/session/storage/RuntimeSessionPort.d.ts.map +1 -1
  112. package/bin/session/storage/RuntimeSessionPort.js +4 -0
  113. package/bin/session/storage/RuntimeSessionPort.js.map +1 -1
  114. package/bin/types/agent/AgentOptions.d.ts +0 -63
  115. package/bin/types/agent/AgentOptions.d.ts.map +1 -1
  116. package/bin/types/agent/AgentTypes.d.ts +3 -2
  117. package/bin/types/agent/AgentTypes.d.ts.map +1 -1
  118. package/bin/types/agent/SessionActor.d.ts +13 -4
  119. package/bin/types/agent/SessionActor.d.ts.map +1 -1
  120. package/bin/types/agent/SessionTypes.d.ts +62 -0
  121. package/bin/types/agent/SessionTypes.d.ts.map +1 -1
  122. package/bin/types/config/DowncityConfig.d.ts +1 -1
  123. package/bin/types/executor/SessionRunContext.d.ts +8 -0
  124. package/bin/types/executor/SessionRunContext.d.ts.map +1 -1
  125. package/bin/types/platform/Store.d.ts +2 -2
  126. package/bin/types/platform/Store.js +2 -2
  127. package/bin/types/rpc/RpcProtocol.d.ts +37 -5
  128. package/bin/types/rpc/RpcProtocol.d.ts.map +1 -1
  129. package/bin/types/rpc/RpcProtocol.js +1 -1
  130. package/bin/types/runtime/agent/AgentContext.d.ts +92 -43
  131. package/bin/types/runtime/agent/AgentContext.d.ts.map +1 -1
  132. package/bin/types/runtime/agent/AgentContext.js +97 -5
  133. package/bin/types/runtime/agent/AgentContext.js.map +1 -1
  134. package/bin/types/runtime/platform/Platform.d.ts +8 -8
  135. package/bin/types/runtime/platform/PlatformGateway.d.ts +2 -2
  136. package/bin/types/sdk/AgentSessionStop.d.ts +36 -0
  137. package/bin/types/sdk/AgentSessionStop.d.ts.map +1 -0
  138. package/bin/types/sdk/AgentSessionStop.js +9 -0
  139. package/bin/types/sdk/AgentSessionStop.js.map +1 -0
  140. package/package.json +3 -3
  141. package/scripts/city-model-tool-loop.test.mjs +2 -2
  142. package/scripts/session-prompt-runtime.test.mjs +59 -0
  143. package/src/agent/local/Agent.ts +66 -55
  144. package/src/agent/local/ProjectSetup.ts +2 -2
  145. package/src/agent/local/services/AgentAssemblyService.ts +41 -35
  146. package/src/agent/local/services/AgentBackgroundService.ts +116 -0
  147. package/src/agent/local/services/AgentSessionManager.ts +127 -13
  148. package/src/agent/remote/RemoteAgent.ts +25 -34
  149. package/src/agent/remote/RemoteSession.ts +21 -6
  150. package/src/agent/remote/RemoteTransport.ts +14 -0
  151. package/src/agent/remote/transports/HttpRemoteAgentTransport.ts +100 -2
  152. package/src/agent/remote/transports/RpcRemoteAgentTransport.ts +26 -0
  153. package/src/config/AgentInitializer.ts +2 -2
  154. package/src/executor/Executor.ts +33 -0
  155. package/src/executor/composer/system/default/InitPrompts.ts +1 -1
  156. package/src/executor/composer/system/default/SystemDomain.ts +2 -2
  157. package/src/executor/core-engine/CoreEngineRunner.ts +21 -0
  158. package/src/executor/messages/ChatMessageMarkupTypes.ts +1 -1
  159. package/src/executor/store/history/jsonl/JsonlSessionHistoryStore.ts +22 -0
  160. package/src/executor/types/SessionExecutor.ts +2 -1
  161. package/src/index.ts +8 -10
  162. package/src/plugin/core/Activation.ts +1 -3
  163. package/src/plugin/core/PluginCommandRequest.ts +1 -1
  164. package/src/plugin/core/PluginStateController.ts +1 -10
  165. package/src/plugin/types/PluginApi.ts +1 -1
  166. package/src/rpc/Client.ts +61 -0
  167. package/src/session/Session.ts +9 -0
  168. package/src/session/browse/Browse.ts +103 -3
  169. package/src/session/index.ts +7 -0
  170. package/src/session/runtime/SessionPromptRuntime.ts +100 -5
  171. package/src/session/services/SessionTurnService.ts +13 -1
  172. package/src/session/services/SessionViewService.ts +1 -7
  173. package/src/session/storage/Metadata.ts +23 -1
  174. package/src/session/storage/Paths.ts +70 -0
  175. package/src/session/storage/RuntimeSessionPort.ts +9 -0
  176. package/src/types/agent/AgentOptions.ts +0 -69
  177. package/src/types/agent/AgentTypes.ts +6 -5
  178. package/src/types/agent/SessionActor.ts +21 -3
  179. package/src/types/agent/SessionTypes.ts +68 -0
  180. package/src/types/config/DowncityConfig.ts +1 -1
  181. package/src/types/executor/SessionRunContext.ts +9 -0
  182. package/src/types/platform/Store.ts +2 -2
  183. package/src/types/rpc/RpcProtocol.ts +46 -4
  184. package/src/types/runtime/agent/AgentContext.ts +132 -45
  185. package/src/types/runtime/platform/Platform.ts +8 -8
  186. package/src/types/runtime/platform/PlatformGateway.ts +2 -2
  187. package/src/types/sdk/AgentSessionStop.ts +39 -0
  188. package/tsconfig.tsbuildinfo +1 -1
  189. package/bin/agent/local/AgentRuntimeFactory.d.ts +0 -72
  190. package/bin/agent/local/AgentRuntimeFactory.d.ts.map +0 -1
  191. package/bin/agent/local/AgentRuntimeFactory.js +0 -73
  192. package/bin/agent/local/AgentRuntimeFactory.js.map +0 -1
  193. package/bin/agent/local/services/AgentLifecycleService.d.ts +0 -65
  194. package/bin/agent/local/services/AgentLifecycleService.d.ts.map +0 -1
  195. package/bin/agent/local/services/AgentLifecycleService.js +0 -140
  196. package/bin/agent/local/services/AgentLifecycleService.js.map +0 -1
  197. package/bin/rpc/Server.d.ts +0 -31
  198. package/bin/rpc/Server.d.ts.map +0 -1
  199. package/bin/rpc/Server.js +0 -106
  200. package/bin/rpc/Server.js.map +0 -1
  201. package/bin/rpc/server/InternalHandlers.d.ts +0 -21
  202. package/bin/rpc/server/InternalHandlers.d.ts.map +0 -1
  203. package/bin/rpc/server/InternalHandlers.js +0 -244
  204. package/bin/rpc/server/InternalHandlers.js.map +0 -1
  205. package/bin/rpc/server/RequestDispatcher.d.ts +0 -27
  206. package/bin/rpc/server/RequestDispatcher.d.ts.map +0 -1
  207. package/bin/rpc/server/RequestDispatcher.js +0 -38
  208. package/bin/rpc/server/RequestDispatcher.js.map +0 -1
  209. package/bin/rpc/server/SdkSessionHandlers.d.ts +0 -25
  210. package/bin/rpc/server/SdkSessionHandlers.d.ts.map +0 -1
  211. package/bin/rpc/server/SdkSessionHandlers.js +0 -86
  212. package/bin/rpc/server/SdkSessionHandlers.js.map +0 -1
  213. package/bin/rpc/server/ServerTypes.d.ts +0 -64
  214. package/bin/rpc/server/ServerTypes.d.ts.map +0 -1
  215. package/bin/rpc/server/ServerTypes.js +0 -9
  216. package/bin/rpc/server/ServerTypes.js.map +0 -1
  217. package/bin/types/runtime/agent/AgentRuntime.d.ts +0 -79
  218. package/bin/types/runtime/agent/AgentRuntime.d.ts.map +0 -1
  219. package/bin/types/runtime/agent/AgentRuntime.js +0 -13
  220. package/bin/types/runtime/agent/AgentRuntime.js.map +0 -1
  221. package/src/agent/local/AgentRuntimeFactory.ts +0 -152
  222. package/src/agent/local/services/AgentLifecycleService.ts +0 -198
  223. package/src/rpc/Server.ts +0 -143
  224. package/src/rpc/server/InternalHandlers.ts +0 -285
  225. package/src/rpc/server/RequestDispatcher.ts +0 -67
  226. package/src/rpc/server/SdkSessionHandlers.ts +0 -106
  227. package/src/rpc/server/ServerTypes.ts +0 -70
  228. package/src/types/runtime/agent/AgentRuntime.ts +0 -84
@@ -2,19 +2,25 @@
2
2
  * RemoteAgent HTTP transport。
3
3
  *
4
4
  * 关键点(中文)
5
- * - 只适配 Town Agent HTTP gateway 的 SDK routes。
5
+ * - 只适配 downcity Agent HTTP gateway 的 SDK routes。
6
6
  * - 不处理 RemoteSession 的 turn lifecycle,避免 transport 与 actor 逻辑混在一起。
7
7
  */
8
8
 
9
9
  import type {
10
10
  AgentCreateSessionInput,
11
11
  AgentListSessionsInput,
12
+ AgentArchiveSessionInput,
13
+ AgentArchiveSessionsInput,
14
+ AgentArchiveSessionResult,
15
+ AgentArchiveSessionsResult,
16
+ AgentCleanArchiveResult,
12
17
  AgentSessionForkInput,
13
18
  AgentSessionHistoryInput,
14
19
  AgentSessionHistoryPage,
15
20
  AgentSessionInfo,
16
21
  AgentSessionSummaryPage,
17
22
  AgentSessionSystemSnapshot,
23
+ AgentSessionStopResult,
18
24
  RemoteAgentPluginActionInput,
19
25
  RemoteAgentPluginActionResult,
20
26
  } from "@/types/agent/AgentTypes.js";
@@ -39,7 +45,7 @@ type SdkEventsReadyFrame = {
39
45
  };
40
46
 
41
47
  /**
42
- * Town HTTP gateway transport。
48
+ * downcity HTTP gateway transport。
43
49
  */
44
50
  export class HttpRemoteAgentTransport implements RemoteAgentTransport {
45
51
  private readonly base_url: string;
@@ -118,6 +124,23 @@ export class HttpRemoteAgentTransport implements RemoteAgentTransport {
118
124
  return { id };
119
125
  }
120
126
 
127
+ async stop(session_id: string): Promise<AgentSessionStopResult> {
128
+ const payload = await read_http_json<{
129
+ success?: boolean;
130
+ error?: string;
131
+ result?: AgentSessionStopResult;
132
+ }>(`${this.base_url}/api/sdk/sessions/${encodeURIComponent(session_id)}/stop`, {
133
+ method: "POST",
134
+ headers: this.headers({
135
+ "Content-Type": "application/json",
136
+ }),
137
+ });
138
+ if (!payload.success || !payload.result) {
139
+ throw new Error(String(payload.error || "Remote session stop failed"));
140
+ }
141
+ return payload.result;
142
+ }
143
+
121
144
  async subscribe(params: {
122
145
  session_id: string;
123
146
  on_ready: () => void;
@@ -250,6 +273,81 @@ export class HttpRemoteAgentTransport implements RemoteAgentTransport {
250
273
  return payload.page;
251
274
  }
252
275
 
276
+ async archive_session(
277
+ input: AgentArchiveSessionInput,
278
+ ): Promise<AgentArchiveSessionResult> {
279
+ const session_id = String(input?.id || "").trim();
280
+ if (!session_id) {
281
+ throw new Error("archive_session requires a non-empty id");
282
+ }
283
+ const payload = await read_http_json<{
284
+ success?: boolean;
285
+ error?: string;
286
+ sessionId?: string;
287
+ archivedAt?: number;
288
+ }>(
289
+ `${this.base_url}/api/sdk/sessions/${encodeURIComponent(session_id)}/archive`,
290
+ {
291
+ method: "POST",
292
+ headers: this.headers({
293
+ "Content-Type": "application/json",
294
+ }),
295
+ },
296
+ );
297
+ if (!payload.success || !payload.sessionId) {
298
+ throw new Error(String(payload.error || "Remote session archive failed"));
299
+ }
300
+ return {
301
+ sessionId: payload.sessionId,
302
+ archivedAt:
303
+ typeof payload.archivedAt === "number" && Number.isFinite(payload.archivedAt)
304
+ ? payload.archivedAt
305
+ : Date.now(),
306
+ };
307
+ }
308
+
309
+ async archive_sessions(
310
+ input?: AgentArchiveSessionsInput,
311
+ ): Promise<AgentArchiveSessionsResult> {
312
+ const query = new URLSearchParams();
313
+ if (input?.limit !== undefined) query.set("limit", String(input.limit));
314
+ if (input?.cursor) query.set("cursor", input.cursor);
315
+ if (input?.query) query.set("query", input.query);
316
+ const payload = await read_http_json<{
317
+ success?: boolean;
318
+ error?: string;
319
+ page?: AgentArchiveSessionsResult;
320
+ }>(
321
+ `${this.base_url}/api/sdk/archived-sessions${query.size > 0 ? `?${query.toString()}` : ""}`,
322
+ {
323
+ headers: this.headers(),
324
+ },
325
+ );
326
+ if (!payload.success || !payload.page) {
327
+ throw new Error(String(payload.error || "Remote archived sessions list failed"));
328
+ }
329
+ return payload.page;
330
+ }
331
+
332
+ async clean_archive(): Promise<AgentCleanArchiveResult> {
333
+ const payload = await read_http_json<{
334
+ success?: boolean;
335
+ error?: string;
336
+ removedSessionIds?: string[];
337
+ }>(`${this.base_url}/api/sdk/archived-sessions`, {
338
+ method: "DELETE",
339
+ headers: this.headers(),
340
+ });
341
+ if (!payload.success) {
342
+ throw new Error(String(payload.error || "Remote clean archive failed"));
343
+ }
344
+ return {
345
+ removedSessionIds: Array.isArray(payload.removedSessionIds)
346
+ ? payload.removedSessionIds
347
+ : [],
348
+ };
349
+ }
350
+
253
351
  async run_plugin_action(
254
352
  input: RemoteAgentPluginActionInput,
255
353
  ): Promise<RemoteAgentPluginActionResult> {
@@ -9,12 +9,18 @@
9
9
  import type {
10
10
  AgentCreateSessionInput,
11
11
  AgentListSessionsInput,
12
+ AgentArchiveSessionInput,
13
+ AgentArchiveSessionsInput,
14
+ AgentArchiveSessionResult,
15
+ AgentArchiveSessionsResult,
16
+ AgentCleanArchiveResult,
12
17
  AgentSessionForkInput,
13
18
  AgentSessionHistoryInput,
14
19
  AgentSessionHistoryPage,
15
20
  AgentSessionInfo,
16
21
  AgentSessionSummaryPage,
17
22
  AgentSessionSystemSnapshot,
23
+ AgentSessionStopResult,
18
24
  RemoteAgentPluginActionInput,
19
25
  RemoteAgentPluginActionResult,
20
26
  } from "@/types/agent/AgentTypes.js";
@@ -62,6 +68,10 @@ export class RpcRemoteAgentTransport implements RemoteAgentTransport {
62
68
  });
63
69
  }
64
70
 
71
+ async stop(session_id: string): Promise<AgentSessionStopResult> {
72
+ return await this.client.stop_session(session_id);
73
+ }
74
+
65
75
  async subscribe(params: {
66
76
  session_id: string;
67
77
  on_ready: () => void;
@@ -111,6 +121,22 @@ export class RpcRemoteAgentTransport implements RemoteAgentTransport {
111
121
  return await this.client.list_sessions(input);
112
122
  }
113
123
 
124
+ async archive_session(
125
+ input: AgentArchiveSessionInput,
126
+ ): Promise<AgentArchiveSessionResult> {
127
+ return await this.client.archive_session(input);
128
+ }
129
+
130
+ async archive_sessions(
131
+ input?: AgentArchiveSessionsInput,
132
+ ): Promise<AgentArchiveSessionsResult> {
133
+ return await this.client.archive_sessions(input);
134
+ }
135
+
136
+ async clean_archive(): Promise<AgentCleanArchiveResult> {
137
+ return await this.client.clean_archive();
138
+ }
139
+
114
140
  async run_plugin_action(
115
141
  input: RemoteAgentPluginActionInput,
116
142
  ): Promise<RemoteAgentPluginActionResult> {
@@ -2,12 +2,12 @@
2
2
  * Agent 项目初始化模块。
3
3
  *
4
4
  * 职责说明(中文)
5
- * - CLI `town agent create` 与 Console 共用同一套初始化逻辑,避免模板与目录结构分叉。
5
+ * - CLI `downcity agent create` 与 Console 共用同一套初始化逻辑,避免模板与目录结构分叉。
6
6
  * - 负责创建项目骨架、静态 prompt、默认 `downcity.json`、基础目录与 schema 文件。
7
7
  * - 负责把用户在创建阶段提供的最小执行配置与渠道配置写入项目。
8
8
  *
9
9
  * 边界说明(中文)
10
- * - 这里只处理“初始化一个新项目”所需的静态文件与目录,不处理 Town 托管进程启停。
10
+ * - 这里只处理“初始化一个新项目”所需的静态文件与目录,不处理 downcity 托管进程启停。
11
11
  * - 这里只校验项目创建阶段依赖的最小平台条件,不承担后续运行时配置合并职责。
12
12
  */
13
13
 
@@ -109,6 +109,7 @@ export class Executor implements SessionExecutor {
109
109
  private readonly core_engine_runner: CoreEngineRunner;
110
110
 
111
111
  private executing = false;
112
+ private abort_controller: AbortController | null = null;
112
113
 
113
114
  constructor(options: ExecutorOptions) {
114
115
  const sessionId = String(options.sessionId || "").trim();
@@ -162,6 +163,17 @@ export class Executor implements SessionExecutor {
162
163
  return this.executing;
163
164
  }
164
165
 
166
+ /**
167
+ * 请求停止当前执行。
168
+ */
169
+ stop(): boolean {
170
+ if (!this.executing || !this.abort_controller) return false;
171
+ if (!this.abort_controller.signal.aborted) {
172
+ this.abort_controller.abort(new Error("Turn stopped"));
173
+ }
174
+ return true;
175
+ }
176
+
165
177
  /**
166
178
  * 获取当前 session 的 history 事实源。
167
179
  */
@@ -260,6 +272,22 @@ export class Executor implements SessionExecutor {
260
272
  };
261
273
  run_context.onAssistantStepCallback = wrappedOnAssistantStepCallback;
262
274
 
275
+ const upstream_abort_signal = run_context.abortSignal;
276
+ const abort_controller = new AbortController();
277
+ const abort_from_upstream = () => {
278
+ if (!abort_controller.signal.aborted) {
279
+ abort_controller.abort(upstream_abort_signal?.reason);
280
+ }
281
+ };
282
+ if (upstream_abort_signal?.aborted) {
283
+ abort_from_upstream();
284
+ } else {
285
+ upstream_abort_signal?.addEventListener("abort", abort_from_upstream, {
286
+ once: true,
287
+ });
288
+ }
289
+ this.abort_controller = abort_controller;
290
+ run_context.abortSignal = abort_controller.signal;
263
291
  this.executing = true;
264
292
  this.recovery_policy.reset_run_state();
265
293
  try {
@@ -308,6 +336,10 @@ export class Executor implements SessionExecutor {
308
336
  return result;
309
337
  } finally {
310
338
  this.recovery_policy.reset_run_state();
339
+ if (this.abort_controller === abort_controller) {
340
+ this.abort_controller = null;
341
+ }
342
+ upstream_abort_signal?.removeEventListener("abort", abort_from_upstream);
311
343
  this.executing = false;
312
344
  }
313
345
  }
@@ -397,6 +429,7 @@ export class Executor implements SessionExecutor {
397
429
  ...(typeof input?.onUiMessageChunkCallback === "function"
398
430
  ? { onUiMessageChunkCallback: input.onUiMessageChunkCallback }
399
431
  : {}),
432
+ ...(input?.abortSignal ? { abortSignal: input.abortSignal } : {}),
400
433
  injectedUserMessages: Array.isArray(input?.injectedUserMessages)
401
434
  ? [...input.injectedUserMessages]
402
435
  : [],
@@ -1,5 +1,5 @@
1
1
  /**
2
- * InitPrompts:`town agent create` 默认 prompt 资产加载器。
2
+ * InitPrompts:`downcity agent create` 默认 prompt 资产加载器。
3
3
  *
4
4
  * 职责说明(中文)
5
5
  * - 统一管理 create 生成的 `PROFILE.md` / `SOUL.md` 默认内容。
@@ -74,7 +74,7 @@ export function buildContextSystemPrompt(input: {
74
74
  const outputRules = [
75
75
  "Task-run output rules:",
76
76
  "- This is a task execution context, not an interactive chat turn.",
77
- "- Do NOT send external channel messages via `town chat send` unless explicitly required by the task itself.",
77
+ "- Do NOT send external channel messages via `downcity chat send` unless explicitly required by the task itself.",
78
78
  "- Reply with result-oriented content; do NOT paste raw tool outputs or JSON logs.",
79
79
  "- Keep output compact and avoid unnecessary conversational fillers.",
80
80
  ].join("\n");
@@ -173,7 +173,7 @@ export async function loadManagedPluginSystemPrompts(input: {
173
173
  .filter(Boolean),
174
174
  );
175
175
 
176
- for (const plugin of input.context.agent.pluginInstances.values()) {
176
+ for (const plugin of input.context.pluginInstances.values()) {
177
177
  if (disabledPluginNames.has(plugin.name)) continue;
178
178
  if (typeof plugin.system !== "function") continue;
179
179
  try {
@@ -43,6 +43,8 @@ import type {
43
43
  } from "@/executor/types/SessionRun.js";
44
44
  import type { SessionMessageV1 } from "@/executor/types/SessionMessages.js";
45
45
 
46
+ const TURN_STOPPED_MESSAGE = "Turn stopped";
47
+
46
48
  /**
47
49
  * 生成 file part 去重 key。
48
50
  */
@@ -200,6 +202,7 @@ export class CoreEngineRunner {
200
202
  prepareStep: prepare_step,
201
203
  messages: message_state.modelMessages,
202
204
  tools,
205
+ abortSignal: input.run_context.abortSignal,
203
206
  providerOptions: buildOpenAIResponsesProviderOptions(),
204
207
  onError: async ({ error }) => {
205
208
  last_observed_stream_error = error;
@@ -405,6 +408,24 @@ export class CoreEngineRunner {
405
408
  ],
406
409
  };
407
410
  } catch (error) {
411
+ if (input.run_context.abortSignal?.aborted) {
412
+ const error_text = TURN_STOPPED_MESSAGE;
413
+ await this.logger.log("info", "[agent] stopped", {
414
+ sessionId: session_id,
415
+ });
416
+ return {
417
+ success: false,
418
+ error: error_text,
419
+ assistantMessage: this.context_composer.buildFallbackAssistantMessage(
420
+ error_text,
421
+ input.run_context,
422
+ ),
423
+ deferredPersistedUserMessages: [
424
+ ...input.run_context.deferredPersistedUserMessages,
425
+ ],
426
+ };
427
+ }
428
+
408
429
  if (this.should_compact_on_error(error)) {
409
430
  throw error;
410
431
  }
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * 关键点(中文)
5
5
  * - 统一描述 chat plugin runtime 中可见的消息协议:frontmatter metadata + `<file>` 标签。
6
- * - direct 模式、`town chat send`、入站附件注入、渠道出站解析都应复用本类型。
6
+ * - direct 模式、`downcity chat send`、入站附件注入、渠道出站解析都应复用本类型。
7
7
  */
8
8
 
9
9
  /**
@@ -493,6 +493,28 @@ export class JsonlSessionHistoryStore implements SessionHistoryStore {
493
493
  });
494
494
  }
495
495
 
496
+ /**
497
+ * 批量追加消息。
498
+ *
499
+ * 关键点(中文)
500
+ * - 一次锁、一次 IO,适合 fork 等需要拷贝整段历史的场景。
501
+ * - 不处理 inflight,调用方需自行确保历史已经收口。
502
+ */
503
+ async appendMany(messages: SessionMessageV1[]): Promise<void> {
504
+ if (!Array.isArray(messages) || messages.length === 0) return;
505
+ const normalized_list = messages
506
+ .map((message) => this.normalizePersistedMessage(message))
507
+ .filter((message): message is SessionMessageV1 => message !== null);
508
+ if (normalized_list.length === 0) return;
509
+
510
+ const payload = normalized_list
511
+ .map((message) => `${JSON.stringify(message)}\n`)
512
+ .join("");
513
+ await this.withWriteLock(async () => {
514
+ await fs.appendFile(this.getMessagesFilePath(), payload, "utf8");
515
+ });
516
+ }
517
+
496
518
  async readInflight(): Promise<SessionMessageV1 | null> {
497
519
  await this.ensureLayout();
498
520
  return this.readInflightUnsafe();
@@ -21,9 +21,10 @@ export interface SessionExecutor {
21
21
  * 请求取消当前正在执行的 turn。
22
22
  *
23
23
  * 关键点(中文)
24
- * - 主要给 ACP 执行器使用,对应协议侧 `session/cancel`。
24
+ * - `session.stop()` 会调用这里终止当前模型流与 tool-loop。
25
25
  * - 返回 `true` 表示本次请求已发出;`false` 表示当前没有可取消的 turn。
26
26
  */
27
+ stop(): boolean;
27
28
 
28
29
  /**
29
30
  * 释放执行器持有的资源。
package/src/index.ts CHANGED
@@ -17,6 +17,11 @@ export {
17
17
  normalizeAgentModel,
18
18
  } from "./model/CityModelAdapter.js";
19
19
  export type {
20
+ AgentArchiveSessionInput,
21
+ AgentArchiveSessionsInput,
22
+ AgentArchiveSessionResult,
23
+ AgentArchiveSessionsResult,
24
+ AgentCleanArchiveResult,
20
25
  AgentSessionCollection,
21
26
  AgentModel,
22
27
  AgentManagedSession,
@@ -26,11 +31,6 @@ export type {
26
31
  AgentCreateSessionInput,
27
32
  AgentListSessionsInput,
28
33
  AgentOptions,
29
- AgentRpcBinding,
30
- AgentRpcStartOptions,
31
- AgentStartOptions,
32
- AgentStartResult,
33
- AgentStopResult,
34
34
  RemoteAgentOptions,
35
35
  AgentSessionConfigSnapshot,
36
36
  AgentSessionForkInput,
@@ -56,13 +56,14 @@ export type {
56
56
  AgentSessionUnsubscribe,
57
57
  } from "./types/sdk/AgentSessionEvent.js";
58
58
  export type { AgentSessionPromptInput } from "./types/sdk/AgentSessionPrompt.js";
59
+ export type { AgentSessionStopResult } from "./types/sdk/AgentSessionStop.js";
59
60
  export type {
60
61
  AgentSessionTurnHandle,
61
62
  AgentSessionTurnResult,
62
63
  } from "./types/sdk/AgentSessionTurn.js";
63
- export type { AgentRuntime, AgentRuntimeBase } from "./types/runtime/agent/AgentRuntime.js";
64
+ export { AgentContext } from "./types/runtime/agent/AgentContext.js";
64
65
  export type {
65
- AgentContext,
66
+ AgentContextOptions,
66
67
  InvokePluginPort,
67
68
  SessionCollectionPort,
68
69
  SessionPort,
@@ -130,9 +131,6 @@ export {
130
131
  registerPluginActionCommandsForCli,
131
132
  } from "./plugin/core/PluginCommand.js";
132
133
 
133
- // Agent RPC 集成
134
- export { startRpcServer } from "./rpc/Server.js";
135
-
136
134
  // Runtime plugin 运行集成
137
135
  export {
138
136
  startAllPlugins,
@@ -9,7 +9,6 @@
9
9
  import { readProjectPluginEnabled } from "@/plugin/core/ProjectConfigStore.js";
10
10
  import type { Plugin } from "@/plugin/types/Plugin.js";
11
11
  import type { AgentContext } from "@/types/runtime/agent/AgentContext.js";
12
- import type { AgentRuntimeBase } from "@/types/runtime/agent/AgentRuntime.js";
13
12
 
14
13
  /**
15
14
  * 读取当前项目配置下的 plugin 启用态。
@@ -17,12 +16,11 @@ import type { AgentRuntimeBase } from "@/types/runtime/agent/AgentRuntime.js";
17
16
  export function isPluginEnabled(params: {
18
17
  plugin: Plugin;
19
18
  context?: Pick<AgentContext, "config">;
20
- runtime?: Pick<AgentRuntimeBase, "config">;
21
19
  }): boolean {
22
20
  const pluginName = String(params.plugin.name || "").trim();
23
21
  if (!pluginName) return false;
24
22
  return readProjectPluginEnabled({
25
23
  pluginName,
26
- config: params.context?.config || params.runtime?.config,
24
+ config: params.context?.config,
27
25
  });
28
26
  }
@@ -2,7 +2,7 @@
2
2
  * PluginCommandRequest:统一 plugin runtime command 请求解析模块。
3
3
  *
4
4
  * 关键点(中文)
5
- * - 统一收口 Town gateway command 入口的请求体解析。
5
+ * - 统一收口 downcity gateway command 入口的请求体解析。
6
6
  * - plugin runtime 远程调用统一走 runtime command 协议,不再让 action 自带 HTTP route。
7
7
  * - ActionSchedule 参数(`schedule` / `delay` / `time`)也在这里一次性归一化。
8
8
  */
@@ -3,7 +3,6 @@
3
3
  */
4
4
 
5
5
  import type { AgentContext } from "@/types/runtime/agent/AgentContext.js";
6
- import type { AgentRuntime } from "@/types/runtime/agent/AgentRuntime.js";
7
6
  import type {
8
7
  PluginLifecycle,
9
8
  PluginState,
@@ -27,16 +26,11 @@ function resolveLifecycle(plugin: BasePlugin): PluginLifecycle | undefined {
27
26
  */
28
27
  export function listPluginInstances(input?: {
29
28
  context?: AgentContext;
30
- runtime?: AgentRuntime;
31
29
  }): BasePlugin[] {
32
- const contextPlugins = input?.context?.agent?.pluginInstances;
30
+ const contextPlugins = input?.context?.pluginInstances;
33
31
  if (contextPlugins instanceof Map && contextPlugins.size > 0) {
34
32
  return [...contextPlugins.values()];
35
33
  }
36
- const runtimePlugins = input?.runtime?.pluginInstances;
37
- if (runtimePlugins instanceof Map && runtimePlugins.size > 0) {
38
- return [...runtimePlugins.values()];
39
- }
40
34
  return [];
41
35
  }
42
36
 
@@ -47,7 +41,6 @@ export function resolvePluginByName(
47
41
  name: string,
48
42
  input?: {
49
43
  context?: AgentContext;
50
- runtime?: AgentRuntime;
51
44
  },
52
45
  ): BasePlugin | null {
53
46
  const key = String(name || "").trim();
@@ -136,7 +129,6 @@ export function markPluginCommand(
136
129
  */
137
130
  export function listPluginStates(input?: {
138
131
  context?: AgentContext;
139
- runtime?: AgentRuntime;
140
132
  }): PluginStateSnapshot[] {
141
133
  return listPluginInstances(input)
142
134
  .map((plugin) =>
@@ -152,7 +144,6 @@ export function isPluginRunning(
152
144
  pluginName: string,
153
145
  input?: {
154
146
  context?: AgentContext;
155
- runtime?: AgentRuntime;
156
147
  },
157
148
  ): boolean {
158
149
  const plugin = resolvePluginByName(pluginName, input);
@@ -2,7 +2,7 @@
2
2
  * plugin catalog / availability / action API 类型。
3
3
  *
4
4
  * 关键点(中文)
5
- * - 统一描述 Town CLI -> Agent runtime 的 plugin 管理协议。
5
+ * - 统一描述 downcity CLI -> Agent runtime 的 plugin 管理协议。
6
6
  * - 当前阶段支持 list / availability / action 三类调用。
7
7
  */
8
8
 
package/src/rpc/Client.ts CHANGED
@@ -11,9 +11,15 @@ import net from "node:net";
11
11
  import type {
12
12
  AgentCreateSessionInput,
13
13
  AgentListSessionsInput,
14
+ AgentArchiveSessionInput,
15
+ AgentArchiveSessionsInput,
16
+ AgentArchiveSessionResult,
17
+ AgentArchiveSessionsResult,
18
+ AgentCleanArchiveResult,
14
19
  AgentSessionHistoryInput,
15
20
  AgentSessionHistoryPage,
16
21
  AgentSessionInfo,
22
+ AgentSessionStopResult,
17
23
  AgentSessionSummaryPage,
18
24
  AgentSessionSystemSnapshot,
19
25
  } from "@/types/agent/AgentTypes.js";
@@ -104,6 +110,48 @@ export class RpcClient {
104
110
  return data.session;
105
111
  }
106
112
 
113
+ /**
114
+ * 归档远程 session。
115
+ */
116
+ async archive_session(
117
+ input: AgentArchiveSessionInput,
118
+ ): Promise<AgentArchiveSessionResult> {
119
+ const data = await this.request<{ result: AgentArchiveSessionResult }>({
120
+ method: "sdk.sessions.archive",
121
+ params: {
122
+ sessionId: input.id,
123
+ },
124
+ });
125
+ return data.result;
126
+ }
127
+
128
+ /**
129
+ * 列出远程已归档 session。
130
+ */
131
+ async archive_sessions(
132
+ input?: AgentArchiveSessionsInput,
133
+ ): Promise<AgentArchiveSessionsResult> {
134
+ const data = await this.request<{ page: AgentArchiveSessionsResult }>({
135
+ method: "sdk.sessions.archived.list",
136
+ params: input,
137
+ });
138
+ return data.page;
139
+ }
140
+
141
+ /**
142
+ * 清空远程已归档 session。
143
+ */
144
+ async clean_archive(): Promise<AgentCleanArchiveResult> {
145
+ const data = await this.request<{ removedSessionIds: string[] }>({
146
+ method: "sdk.sessions.archived.clean",
147
+ });
148
+ return {
149
+ removedSessionIds: Array.isArray(data.removedSessionIds)
150
+ ? data.removedSessionIds
151
+ : [],
152
+ };
153
+ }
154
+
107
155
  /**
108
156
  * 获取远程 session 信息。
109
157
  */
@@ -134,6 +182,19 @@ export class RpcClient {
134
182
  return data.turn;
135
183
  }
136
184
 
185
+ /**
186
+ * 停止远程 session 当前 turn。
187
+ */
188
+ async stop_session(session_id: string): Promise<AgentSessionStopResult> {
189
+ const data = await this.request<{ result: AgentSessionStopResult }>({
190
+ method: "sdk.sessions.stop",
191
+ params: {
192
+ sessionId: session_id,
193
+ },
194
+ });
195
+ return data.result;
196
+ }
197
+
137
198
  /**
138
199
  * 读取 history。
139
200
  */
@@ -36,6 +36,7 @@ import type {
36
36
  AgentSessionUnsubscribe,
37
37
  } from "@/types/sdk/AgentSessionEvent.js";
38
38
  import type { AgentSessionPromptInput } from "@/types/sdk/AgentSessionPrompt.js";
39
+ import type { AgentSessionStopResult } from "@/types/sdk/AgentSessionStop.js";
39
40
  import type { AgentSessionTurnHandle } from "@/types/sdk/AgentSessionTurn.js";
40
41
  import { SessionEventHub } from "@/session/runtime/SessionEventHub.js";
41
42
  import { SessionStateService } from "@/session/services/SessionStateService.js";
@@ -189,6 +190,13 @@ export class Session implements AgentSession {
189
190
  return await this.turnService.prompt(input);
190
191
  }
191
192
 
193
+ /**
194
+ * 停止当前 turn,并取消尚未被吸收的排队 prompt。
195
+ */
196
+ async stop(): Promise<AgentSessionStopResult> {
197
+ return await this.turnService.stop();
198
+ }
199
+
192
200
  /**
193
201
  * 订阅当前 Session 的未来事件。
194
202
  */
@@ -269,6 +277,7 @@ export class Session implements AgentSession {
269
277
  sessionId: this.id,
270
278
  getExecutor: () => this.executor.getExecutor(),
271
279
  prompt: async (input) => await this.prompt(input),
280
+ stop: async () => await this.stop(),
272
281
  subscribe: (subscriber) => this.subscribe(subscriber),
273
282
  publishEvent: (event) => {
274
283
  this.eventHub.publish(event);