@downcity/agent 1.1.232 → 1.1.237

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 (165) hide show
  1. package/bin/agent/local/Agent.d.ts +1 -1
  2. package/bin/agent/local/Agent.js +2 -2
  3. package/bin/agent/local/Agent.js.map +1 -1
  4. package/bin/agent/local/services/AgentSessions.d.ts +4 -4
  5. package/bin/agent/local/services/AgentSessions.d.ts.map +1 -1
  6. package/bin/agent/local/services/AgentSessions.js +8 -8
  7. package/bin/agent/local/services/AgentSessions.js.map +1 -1
  8. package/bin/agent/remote/RemoteSession.d.ts +2 -0
  9. package/bin/agent/remote/RemoteSession.d.ts.map +1 -1
  10. package/bin/agent/remote/RemoteSession.js +4 -0
  11. package/bin/agent/remote/RemoteSession.js.map +1 -1
  12. package/bin/agent/remote/RemoteTransport.d.ts +2 -0
  13. package/bin/agent/remote/RemoteTransport.d.ts.map +1 -1
  14. package/bin/agent/remote/transports/HttpRemoteAgentTransport.d.ts +1 -0
  15. package/bin/agent/remote/transports/HttpRemoteAgentTransport.d.ts.map +1 -1
  16. package/bin/agent/remote/transports/HttpRemoteAgentTransport.js +11 -0
  17. package/bin/agent/remote/transports/HttpRemoteAgentTransport.js.map +1 -1
  18. package/bin/agent/remote/transports/RpcRemoteAgentTransport.d.ts +1 -0
  19. package/bin/agent/remote/transports/RpcRemoteAgentTransport.d.ts.map +1 -1
  20. package/bin/agent/remote/transports/RpcRemoteAgentTransport.js +3 -0
  21. package/bin/agent/remote/transports/RpcRemoteAgentTransport.js.map +1 -1
  22. package/bin/executor/Executor.d.ts +20 -2
  23. package/bin/executor/Executor.d.ts.map +1 -1
  24. package/bin/executor/Executor.js +102 -18
  25. package/bin/executor/Executor.js.map +1 -1
  26. package/bin/executor/composer/compaction/SessionCompactionComposer.d.ts +6 -0
  27. package/bin/executor/composer/compaction/SessionCompactionComposer.d.ts.map +1 -1
  28. package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionComposer.d.ts +0 -9
  29. package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionComposer.d.ts.map +1 -1
  30. package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionComposer.js +4 -38
  31. package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionComposer.js.map +1 -1
  32. package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionExecutor.d.ts +1 -3
  33. package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionExecutor.d.ts.map +1 -1
  34. package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionExecutor.js +7 -59
  35. package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionExecutor.js.map +1 -1
  36. package/bin/executor/core-engine/CoreEngineContextCompaction.d.ts +38 -0
  37. package/bin/executor/core-engine/CoreEngineContextCompaction.d.ts.map +1 -0
  38. package/bin/executor/core-engine/CoreEngineContextCompaction.js +392 -0
  39. package/bin/executor/core-engine/CoreEngineContextCompaction.js.map +1 -0
  40. package/bin/executor/core-engine/CoreEngineMessageState.d.ts +15 -0
  41. package/bin/executor/core-engine/CoreEngineMessageState.d.ts.map +1 -1
  42. package/bin/executor/core-engine/CoreEngineMessageState.js +20 -0
  43. package/bin/executor/core-engine/CoreEngineMessageState.js.map +1 -1
  44. package/bin/executor/core-engine/CoreEngineRunner.d.ts +9 -5
  45. package/bin/executor/core-engine/CoreEngineRunner.d.ts.map +1 -1
  46. package/bin/executor/core-engine/CoreEngineRunner.js +146 -35
  47. package/bin/executor/core-engine/CoreEngineRunner.js.map +1 -1
  48. package/bin/executor/store/history/SessionHistoryStore.d.ts +4 -10
  49. package/bin/executor/store/history/SessionHistoryStore.d.ts.map +1 -1
  50. package/bin/executor/store/history/jsonl/JsonlSessionHistoryStore.d.ts.map +1 -1
  51. package/bin/executor/store/history/jsonl/JsonlSessionHistoryStore.js +1 -3
  52. package/bin/executor/store/history/jsonl/JsonlSessionHistoryStore.js.map +1 -1
  53. package/bin/executor/types/SessionRun.d.ts +8 -0
  54. package/bin/executor/types/SessionRun.d.ts.map +1 -1
  55. package/bin/index.d.ts +1 -1
  56. package/bin/index.d.ts.map +1 -1
  57. package/bin/index.js +1 -1
  58. package/bin/index.js.map +1 -1
  59. package/bin/plugin/core/PluginLocalExecution.js +3 -3
  60. package/bin/plugin/core/PluginLocalExecution.js.map +1 -1
  61. package/bin/plugin/core/PluginRegistry.d.ts +20 -2
  62. package/bin/plugin/core/PluginRegistry.d.ts.map +1 -1
  63. package/bin/plugin/core/PluginRegistry.js +100 -3
  64. package/bin/plugin/core/PluginRegistry.js.map +1 -1
  65. package/bin/rpc/Client.d.ts +6 -4
  66. package/bin/rpc/Client.d.ts.map +1 -1
  67. package/bin/rpc/Client.js +11 -0
  68. package/bin/rpc/Client.js.map +1 -1
  69. package/bin/session/Session.d.ts +7 -3
  70. package/bin/session/Session.d.ts.map +1 -1
  71. package/bin/session/Session.js +26 -19
  72. package/bin/session/Session.js.map +1 -1
  73. package/bin/session/SessionSystemBuilder.d.ts.map +1 -1
  74. package/bin/session/SessionSystemBuilder.js +3 -1
  75. package/bin/session/SessionSystemBuilder.js.map +1 -1
  76. package/bin/session/recorder/SessionRecorderCompaction.d.ts.map +1 -1
  77. package/bin/session/recorder/SessionRecorderCompaction.js +102 -60
  78. package/bin/session/recorder/SessionRecorderCompaction.js.map +1 -1
  79. package/bin/session/runtime/SessionPromptRuntime.d.ts +11 -7
  80. package/bin/session/runtime/SessionPromptRuntime.d.ts.map +1 -1
  81. package/bin/session/runtime/SessionPromptRuntime.js +22 -24
  82. package/bin/session/runtime/SessionPromptRuntime.js.map +1 -1
  83. package/bin/session/services/SessionStateService.d.ts +10 -6
  84. package/bin/session/services/SessionStateService.d.ts.map +1 -1
  85. package/bin/session/services/SessionStateService.js +29 -20
  86. package/bin/session/services/SessionStateService.js.map +1 -1
  87. package/bin/session/services/SessionTurnService.d.ts +13 -3
  88. package/bin/session/services/SessionTurnService.d.ts.map +1 -1
  89. package/bin/session/services/SessionTurnService.js +90 -7
  90. package/bin/session/services/SessionTurnService.js.map +1 -1
  91. package/bin/types/agent/SessionActor.d.ts +8 -0
  92. package/bin/types/agent/SessionActor.d.ts.map +1 -1
  93. package/bin/types/executor/SessionRunContext.d.ts +16 -8
  94. package/bin/types/executor/SessionRunContext.d.ts.map +1 -1
  95. package/bin/types/plugin/PluginRuntime.d.ts +36 -4
  96. package/bin/types/plugin/PluginRuntime.d.ts.map +1 -1
  97. package/bin/types/plugin/PluginState.d.ts +10 -0
  98. package/bin/types/plugin/PluginState.d.ts.map +1 -1
  99. package/bin/types/rpc/RpcProtocol.d.ts +21 -0
  100. package/bin/types/rpc/RpcProtocol.d.ts.map +1 -1
  101. package/bin/types/runtime/agent/AgentContext.d.ts +2 -2
  102. package/bin/types/runtime/agent/AgentContext.js +1 -1
  103. package/bin/types/session/SessionLocalState.d.ts +2 -2
  104. package/bin/types/session/SessionOptions.d.ts +5 -5
  105. package/bin/types/session/SessionOptions.d.ts.map +1 -1
  106. package/bin/types/session/SessionQueueCommand.d.ts +68 -0
  107. package/bin/types/session/SessionQueueCommand.d.ts.map +1 -0
  108. package/bin/types/session/SessionQueueCommand.js +10 -0
  109. package/bin/types/session/SessionQueueCommand.js.map +1 -0
  110. package/bin/utils/logger/Logger.d.ts +7 -9
  111. package/bin/utils/logger/Logger.d.ts.map +1 -1
  112. package/bin/utils/logger/Logger.js +11 -9
  113. package/bin/utils/logger/Logger.js.map +1 -1
  114. package/package.json +3 -3
  115. package/scripts/core-engine-context-compaction.test.mjs +411 -0
  116. package/scripts/logger-isolation.test.mjs +55 -0
  117. package/scripts/multi-agent-plugin-isolation.test.mjs +289 -0
  118. package/scripts/plugin-tool-bridge.test.mjs +52 -0
  119. package/scripts/remote-session-reconnect.test.mjs +18 -0
  120. package/scripts/session-compaction-context-window.test.mjs +27 -26
  121. package/scripts/session-config-turn-boundary.test.mjs +80 -26
  122. package/scripts/session-prompt-runtime.test.mjs +23 -15
  123. package/scripts/session-recorder.test.mjs +15 -24
  124. package/src/agent/local/Agent.ts +2 -2
  125. package/src/agent/local/services/AgentSessions.ts +10 -10
  126. package/src/agent/remote/RemoteSession.ts +5 -0
  127. package/src/agent/remote/RemoteTransport.ts +2 -0
  128. package/src/agent/remote/transports/HttpRemoteAgentTransport.ts +15 -0
  129. package/src/agent/remote/transports/RpcRemoteAgentTransport.ts +4 -0
  130. package/src/executor/Executor.ts +111 -19
  131. package/src/executor/composer/compaction/SessionCompactionComposer.ts +7 -0
  132. package/src/executor/composer/compaction/jsonl/JsonlSessionCompactionComposer.ts +4 -57
  133. package/src/executor/composer/compaction/jsonl/JsonlSessionCompactionExecutor.ts +8 -66
  134. package/src/executor/core-engine/CoreEngineContextCompaction.ts +477 -0
  135. package/src/executor/core-engine/CoreEngineMessageState.ts +29 -0
  136. package/src/executor/core-engine/CoreEngineRunner.ts +200 -48
  137. package/src/executor/store/history/SessionHistoryStore.ts +4 -12
  138. package/src/executor/store/history/jsonl/JsonlSessionHistoryStore.ts +1 -3
  139. package/src/executor/types/SessionRun.ts +9 -0
  140. package/src/index.ts +1 -1
  141. package/src/plugin/core/PluginLocalExecution.ts +3 -3
  142. package/src/plugin/core/PluginRegistry.ts +116 -3
  143. package/src/rpc/Client.ts +15 -2
  144. package/src/session/Session.ts +28 -20
  145. package/src/session/SessionSystemBuilder.ts +4 -1
  146. package/src/session/recorder/SessionRecorderCompaction.ts +113 -65
  147. package/src/session/runtime/SessionPromptRuntime.ts +31 -46
  148. package/src/session/services/SessionStateService.ts +34 -25
  149. package/src/session/services/SessionTurnService.ts +97 -8
  150. package/src/types/agent/SessionActor.ts +9 -0
  151. package/src/types/executor/SessionRunContext.ts +17 -8
  152. package/src/types/plugin/PluginRuntime.ts +38 -4
  153. package/src/types/plugin/PluginState.ts +10 -0
  154. package/src/types/rpc/RpcProtocol.ts +23 -0
  155. package/src/types/runtime/agent/AgentContext.ts +2 -2
  156. package/src/types/session/SessionLocalState.ts +2 -2
  157. package/src/types/session/SessionOptions.ts +6 -6
  158. package/src/types/session/SessionQueueCommand.ts +78 -0
  159. package/src/utils/logger/Logger.ts +10 -10
  160. package/tsconfig.tsbuildinfo +1 -1
  161. package/bin/types/session/SessionConfigMutation.d.ts +0 -68
  162. package/bin/types/session/SessionConfigMutation.d.ts.map +0 -1
  163. package/bin/types/session/SessionConfigMutation.js +0 -10
  164. package/bin/types/session/SessionConfigMutation.js.map +0 -1
  165. package/src/types/session/SessionConfigMutation.ts +0 -78
@@ -14,6 +14,7 @@ import { isAgentSessionPromptInputEmpty } from "@/types/sdk/AgentSessionPrompt.j
14
14
  import type { AgentSessionPromptInput } from "@/types/sdk/AgentSessionPrompt.js";
15
15
  import type { AgentSessionStopResult } from "@/types/sdk/AgentSessionStop.js";
16
16
  import type { AgentSessionTurnHandle } from "@/types/sdk/AgentSessionTurn.js";
17
+ import type { SessionRunResult } from "@/executor/types/SessionRun.js";
17
18
  import type {
18
19
  SessionRecordV1,
19
20
  SessionMessageRecordV1,
@@ -22,13 +23,14 @@ import type {
22
23
  import { SessionEventHub } from "@/session/runtime/SessionEventHub.js";
23
24
  import { SessionPromptRuntime } from "@/session/runtime/SessionPromptRuntime.js";
24
25
  import type { SessionRunContext } from "@/types/executor/SessionRunContext.js";
25
- import type { SessionRuntimeConfigMutation } from "@/types/session/SessionConfigMutation.js";
26
+ import type { SessionQueueCommand } from "@/types/session/SessionQueueCommand.js";
26
27
  import { SessionStateService } from "@/session/services/SessionStateService.js";
27
28
  import {
28
29
  SessionAssistantMessageWriter,
29
30
  SessionRecorder,
30
31
  } from "@/session/recorder/SessionRecorder.js";
31
32
  import { from_ui_assistant_parts } from "@/session/recorder/SessionMessageCodec.js";
33
+ import { generateId } from "@/utils/Id.js";
32
34
 
33
35
  type SessionTurnServiceOptions = {
34
36
  /**
@@ -71,6 +73,8 @@ export class SessionTurnService {
71
73
  private readonly event_hub: SessionEventHub;
72
74
  private readonly recorder: SessionRecorder;
73
75
  private readonly prompt_runtime: SessionPromptRuntime;
76
+ private active_run_context: SessionRunContext | null = null;
77
+ private request_active_history_reload: (() => void) | null = null;
74
78
 
75
79
  constructor(options: SessionTurnServiceOptions) {
76
80
  this.session_id = options.session_id;
@@ -138,10 +142,49 @@ export class SessionTurnService {
138
142
  }
139
143
 
140
144
  /**
141
- * 把 configured state 修改加入当前 Session 的统一输入队列。
145
+ * 把 configured state command 加入当前 Session 的统一输入队列。
142
146
  */
143
- enqueue_config(mutation: SessionRuntimeConfigMutation): void {
144
- this.prompt_runtime.enqueue_config(mutation);
147
+ enqueue_command(command: SessionQueueCommand): void {
148
+ this.prompt_runtime.enqueue_command(command);
149
+ }
150
+
151
+ /**
152
+ * 把一次显式历史压缩加入当前 Session 的统一输入队列。
153
+ */
154
+ async compact(): Promise<void> {
155
+ await this.state_service.ensure_runnable();
156
+ const command_id = generateId();
157
+ this.enqueue_command({
158
+ type: "command",
159
+ command_id,
160
+ scope: "session",
161
+ execute: async ({ turn_id }) => {
162
+ const active_run_context = this.active_run_context;
163
+ const run_context = active_run_context ||
164
+ this.create_compaction_run_context(turn_id);
165
+ const result = await this.executor.compact_history(run_context);
166
+ if (
167
+ result.compacted &&
168
+ active_run_context !== null &&
169
+ active_run_context === this.active_run_context
170
+ ) {
171
+ this.request_active_history_reload?.();
172
+ }
173
+ await this.state_service.touch_metadata();
174
+ if (result.compacted) {
175
+ return;
176
+ }
177
+ if (!result.compacted && result.reason === "nothing_to_compact") {
178
+ await this.state_service.emit_action_event({
179
+ id: `compacting:${this.session_id}:${command_id}`,
180
+ title: "Session records already compact",
181
+ description: "The Session has no active records to compact.",
182
+ state: "completed",
183
+ turnId: turn_id,
184
+ });
185
+ }
186
+ },
187
+ });
145
188
  }
146
189
 
147
190
  /**
@@ -169,6 +212,7 @@ export class SessionTurnService {
169
212
  current: SessionAssistantMessageWriter | null;
170
213
  } = { current: null };
171
214
  let assistant_segment_index = 0;
215
+ let history_reload_requested = false;
172
216
  const ensure_assistant_writer = async (): Promise<SessionAssistantMessageWriter> => {
173
217
  if (assistant_writer_ref.current) return assistant_writer_ref.current;
174
218
  assistant_segment_index += 1;
@@ -183,6 +227,13 @@ export class SessionTurnService {
183
227
  sessionId: this.session_id,
184
228
  projectRoot: this.project_root,
185
229
  onStepCallback: async () => {
230
+ if (
231
+ this.prompt_runtime.has_pending_command() &&
232
+ assistant_writer_ref.current
233
+ ) {
234
+ await assistant_writer_ref.current.complete();
235
+ assistant_writer_ref.current = null;
236
+ }
186
237
  const merged = await input.onStepMerge();
187
238
  if (merged.length > 0 && assistant_writer_ref.current) {
188
239
  await assistant_writer_ref.current.complete();
@@ -191,6 +242,11 @@ export class SessionTurnService {
191
242
  return merged;
192
243
  },
193
244
  hasPendingStepInput: () => this.prompt_runtime.has_pending_prompt(),
245
+ consume_history_reload: () => {
246
+ const requested = history_reload_requested;
247
+ history_reload_requested = false;
248
+ return requested;
249
+ },
194
250
  onUiMessageChunkCallback: async (chunk) => {
195
251
  if (!is_assistant_content_chunk(chunk.type)) return;
196
252
  const writer = await ensure_assistant_writer();
@@ -206,10 +262,22 @@ export class SessionTurnService {
206
262
  };
207
263
  const query = input.promptInput.query;
208
264
  const executor_query = typeof query === "string" ? query : extractTextFromParts(query);
209
- const result = await this.executor.run({
210
- query: executor_query,
211
- runContext: run_context,
212
- });
265
+ this.active_run_context = run_context;
266
+ this.request_active_history_reload = () => {
267
+ history_reload_requested = true;
268
+ };
269
+ let result: SessionRunResult;
270
+ try {
271
+ result = await this.executor.run({
272
+ query: executor_query,
273
+ runContext: run_context,
274
+ });
275
+ } finally {
276
+ if (this.active_run_context === run_context) {
277
+ this.active_run_context = null;
278
+ this.request_active_history_reload = null;
279
+ }
280
+ }
213
281
  const final_assistant_parts = result.assistantMessage
214
282
  ? from_ui_assistant_parts(result.assistantMessage.parts)
215
283
  : [];
@@ -252,6 +320,10 @@ export class SessionTurnService {
252
320
  await this.state_service.persist_deferred_user_messages(
253
321
  result.deferredPersistedUserMessages,
254
322
  );
323
+ if (result.compact_required) {
324
+ await this.executor.compact_history(run_context);
325
+ await this.state_service.touch_metadata();
326
+ }
255
327
  return {
256
328
  text: result.assistantMessage
257
329
  ? extractTextFromUiMessage(result.assistantMessage)
@@ -263,6 +335,23 @@ export class SessionTurnService {
263
335
  ...(result.error ? { error: result.error } : {}),
264
336
  };
265
337
  }
338
+
339
+ /**
340
+ * 为 turn 开始前执行的 compact command 构造最小运行上下文。
341
+ */
342
+ private create_compaction_run_context(turn_id: string): SessionRunContext {
343
+ return {
344
+ turnId: turn_id,
345
+ sessionId: this.session_id,
346
+ projectRoot: this.project_root,
347
+ onActionCallback: async (event) => {
348
+ await this.state_service.persist_action_event(event);
349
+ },
350
+ injectedUserMessages: [],
351
+ deferredPersistedUserMessages: [],
352
+ pendingAssistantFileParts: [],
353
+ };
354
+ }
266
355
  }
267
356
 
268
357
  function is_assistant_content_chunk(type: string): boolean {
@@ -79,6 +79,15 @@ export interface AgentSessionActor {
79
79
  /** 停止当前 turn,并取消尚未被吸收的排队 prompt。 */
80
80
  stop(): Promise<AgentSessionStopResult>;
81
81
 
82
+ /**
83
+ * 把一次显式历史压缩加入当前 Session 的有序输入队列。
84
+ *
85
+ * 关键点(中文)
86
+ * - 返回表示 command 已成功入队,不表示压缩已经执行完成。
87
+ * - 实际结果通过 Session action message 对外观测。
88
+ */
89
+ compact(): Promise<void>;
90
+
82
91
  /** 订阅当前 session 的未来事件。 */
83
92
  subscribe(
84
93
  subscriber: SessionMutationSubscriber,
@@ -18,7 +18,7 @@ import type {
18
18
  } from "@/executor/types/SessionRun.js";
19
19
  import type { SessionUserMessageV1 } from "@/executor/types/SessionRecords.js";
20
20
  import type { FileUIPart } from "ai";
21
- import type { AgentPluginExecutionRuntime } from "@/types/plugin/PluginRuntime.js";
21
+ import type { AgentPluginExecutionLease } from "@/types/plugin/PluginRuntime.js";
22
22
 
23
23
  /**
24
24
  * 单次 session run 的运行上下文。
@@ -57,28 +57,37 @@ export interface SessionRunContext {
57
57
  onStepCallback?: () => Promise<SessionUserMessageV1[]>;
58
58
 
59
59
  /**
60
- * 判断是否仍有等待并入下一模型 turn 的 steer prompt。
60
+ * 判断是否仍有等待并入下一 Session step 的 steer prompt。
61
61
  *
62
62
  * 关键点(中文)
63
- * - 只检查 prompt,不把单独的配置 mutation 当成继续调用模型的理由。
63
+ * - 只检查 prompt,不把单独的 command 当成继续调用模型的理由。
64
64
  * - 真正的队列消费统一发生在 `onStepCallback`。
65
65
  */
66
66
  hasPendingStepInput?: () => boolean;
67
67
 
68
68
  /**
69
- * 当前模型 turn 实际使用的 Agent env。
69
+ * 消费一次 canonical history 重载请求。
70
70
  *
71
71
  * 关键点(中文)
72
- * - Session 配置队列在模型 turn 开始前更新。
72
+ * - QueueCommand 重写持久化历史后返回 true。
73
+ * - CoreEngine 必须在下一次 provider 调用前重新读取 records,并且每次请求只能消费一次。
74
+ */
75
+ consume_history_reload?: () => boolean;
76
+
77
+ /**
78
+ * 当前 Session step 实际使用的 Agent env。
79
+ *
80
+ * 关键点(中文)
81
+ * - 由 Session 统一输入队列在 step 检查点更新。
73
82
  * - tool/plugin 深层调用通过 run scope 读取,避免看到刚写入但尚未生效的 env。
74
83
  */
75
84
  agentEnv?: Readonly<Record<string, string>>;
76
85
 
77
- /** 当前模型 turn 已提交生效的 Agent instruction 文本。 */
86
+ /** 当前 Session step 已提交生效的 Agent instruction 文本。 */
78
87
  agentSystems?: readonly string[];
79
88
 
80
- /** 当前模型 turn 捕获的 Plugin 执行视图。 */
81
- agentPlugins?: AgentPluginExecutionRuntime;
89
+ /** 当前 Session step 持有的 Plugin 执行 lease。 */
90
+ agentPlugins?: AgentPluginExecutionLease;
82
91
 
83
92
  /**
84
93
  * assistant step 完成回调。
@@ -95,11 +95,17 @@ export interface PluginAvailability {
95
95
  export interface AgentPlugins {
96
96
  /** 注册或替换一个 plugin。 */
97
97
  register(plugin: Plugin): Promise<PluginSnapshot>;
98
- /** 卸载一个 plugin。 */
98
+ /**
99
+ * 从 configured registry 卸载一个 plugin。
100
+ *
101
+ * 关键点(中文)
102
+ * - 返回值表示 configured registry 是否发生删除。
103
+ * - 活跃 Session step 仍可使用已捕获的 execution lease,lifecycle.stop 在 lease 释放后执行。
104
+ */
99
105
  unregister(pluginName: string): Promise<boolean>;
100
106
  /** 启动全部已挂载 plugin lifecycle。 */
101
107
  startAll(): Promise<PluginSnapshot[]>;
102
- /** 卸载全部 plugin */
108
+ /** 卸载全部 plugin,并等待所有 execution lease 释放后的 lifecycle.stop 完成。 */
103
109
  unregisterAll(): Promise<void>;
104
110
  /** 判断 plugin 是否已注册。 */
105
111
  has(pluginName: string): boolean;
@@ -146,9 +152,9 @@ export interface AgentPlugins {
146
152
  }
147
153
 
148
154
  /**
149
- * 单次模型 turn 可使用的 Plugin 能力视图。
155
+ * Plugin execution view 的只读调用能力。
150
156
  */
151
- export interface AgentPluginExecutionRuntime {
157
+ export interface AgentPluginExecutionView {
152
158
  /** 读取当前视图中的 plugin/action metadata。 */
153
159
  read(params: {
154
160
  /** Plugin 名称(可选)。 */
@@ -171,6 +177,34 @@ export interface AgentPluginExecutionRuntime {
171
177
  systemBlocks(): Promise<AgentSessionSystemBlock[]>;
172
178
  }
173
179
 
180
+ /**
181
+ * 单次 Session step 持有的 Plugin 执行 lease。
182
+ */
183
+ export interface AgentPluginExecutionLease extends AgentPluginExecutionView {
184
+ /**
185
+ * 释放当前 step 对捕获 Plugin lifecycle 的占用。
186
+ *
187
+ * 关键点(中文)
188
+ * - 必须幂等,重复释放不会重复停止 lifecycle。
189
+ * - 若 Plugin 已从 configured registry 移除,最后一个 lease 释放时完成延迟 stop。
190
+ */
191
+ release(): Promise<void>;
192
+ }
193
+
194
+ /**
195
+ * Session effective 配置持有的 Plugin 执行 runtime。
196
+ */
197
+ export interface AgentPluginExecutionRuntime extends AgentPluginExecutionView {
198
+ /**
199
+ * 为当前 Session step 获取独立的 Plugin 执行 lease。
200
+ *
201
+ * 关键点(中文)
202
+ * - lease 只捕获创建 runtime 时存在的 Plugin records。
203
+ * - 已退休或 lifecycle 未就绪的 Plugin 不会进入新 lease。
204
+ */
205
+ acquire(): AgentPluginExecutionLease;
206
+ }
207
+
174
208
  /**
175
209
  * Plugin 配置定义。
176
210
  */
@@ -32,6 +32,16 @@ export interface PluginRuntimeRecord {
32
32
  chain: Promise<void>;
33
33
  /** lifecycle.start 是否已经执行成功。 */
34
34
  lifecycle_started: boolean;
35
+ /** 当前正在使用该 Plugin 的 Session step lease 数量。 */
36
+ active_execution_leases: number;
37
+ /** 当前 Plugin 是否已从 configured registry 移除并等待释放。 */
38
+ retired: boolean;
39
+ /** 当前 Plugin 的延迟 lifecycle.stop 是否已经开始。 */
40
+ retirement_started: boolean;
41
+ /** 当前 Plugin 完成延迟 lifecycle.stop 后兑现的 Promise。 */
42
+ retirement_promise?: Promise<void>;
43
+ /** 兑现当前 Plugin retirement Promise 的内部回调。 */
44
+ resolve_retirement?: () => void;
35
45
  }
36
46
 
37
47
  /**
@@ -126,6 +126,17 @@ export type RpcRequest =
126
126
  sessionId: string;
127
127
  };
128
128
  }
129
+ | {
130
+ /** 请求 id,用于匹配响应。 */
131
+ id: string;
132
+ /** 把显式历史压缩加入 Session 的有序输入队列。 */
133
+ method: "sdk.sessions.compact";
134
+ /** 目标 Session 参数。 */
135
+ params: {
136
+ /** 目标 session id。 */
137
+ sessionId: string;
138
+ };
139
+ }
129
140
  | {
130
141
  /** 请求 id,用于匹配响应。 */
131
142
  id: string;
@@ -396,6 +407,18 @@ export interface RpcClientEndpoint {
396
407
  port: number;
397
408
  }
398
409
 
410
+ /** Agent 本机 internal.status.get 返回的进程身份。 */
411
+ export interface RpcInternalStatus {
412
+ /** RPC 服务健康状态。 */
413
+ status: string;
414
+ /** RPC 服务所属进程的操作系统 pid。 */
415
+ pid: number;
416
+ /** 当前 Agent 项目的绝对路径。 */
417
+ projectRoot: string;
418
+ /** daemon 启动实例 ID;非 daemon 前台进程返回空字符串。 */
419
+ instanceId: string;
420
+ }
421
+
399
422
  /**
400
423
  * RPC Session 订阅句柄。
401
424
  */
@@ -234,7 +234,7 @@ export interface AgentContextOptions {
234
234
  *
235
235
  * 关键点(中文)
236
236
  * - 必须是 Agent 持有的同一个 mutable 引用,不要克隆后再传入。
237
- * - Session 模型 turn 内优先读取队列已经提交的 effective env。
237
+ * - Session step 内优先读取队列已经提交的 effective env。
238
238
  */
239
239
  env: Record<string, string>;
240
240
  /** 当前生效的 system 文本集合。 */
@@ -306,7 +306,7 @@ export class AgentContext {
306
306
  * 读取当前调用链可见的 Agent env。
307
307
  *
308
308
  * 关键点(中文)
309
- * - 模型 turn 内优先返回统一输入队列已经提交的 effective env。
309
+ * - Session step 内优先返回统一输入队列已经提交的 effective env。
310
310
  * - Session 运行外返回 Agent 配置 API 最近一次成功写入的 configured env。
311
311
  */
312
312
  get env(): Record<string, string> {
@@ -19,11 +19,11 @@ export interface SessionLocalState {
19
19
  sessionConfig: AgentSessionConfigSnapshot;
20
20
 
21
21
  /**
22
- * 当前模型 turn 实际使用的 Session 配置。
22
+ * 当前 Session step 实际使用的 Session 配置。
23
23
  *
24
24
  * 关键点(中文)
25
25
  * - `sessionConfig` 是配置 API 最近一次成功写入的 configured state。
26
- * - 该字段只在模型 turn 开始前由队列 mutation 更新。
26
+ * - 该字段只在 Session step 检查点由队列 mutation 更新。
27
27
  */
28
28
  effective_session_config: AgentSessionConfigSnapshot;
29
29
 
@@ -12,7 +12,7 @@ import type { AgentSession } from "@/types/agent/SessionActor.js";
12
12
  import type { SessionPort } from "@/types/runtime/agent/AgentContext.js";
13
13
  import type { AgentSessionSystemBlock } from "@/types/agent/SessionTypes.js";
14
14
  import type { AgentPluginExecutionRuntime } from "@/types/plugin/PluginRuntime.js";
15
- import type { AgentSessionConfigMutation } from "@/types/session/SessionConfigMutation.js";
15
+ import type { AgentSessionCommand } from "@/types/session/SessionQueueCommand.js";
16
16
  import type { SessionComposerOptions } from "@/types/session/SessionComposerOptions.js";
17
17
  import type { Logger } from "@/utils/logger/Logger.js";
18
18
  import type { AgentModel } from "@/model/CityModelAdapter.js";
@@ -44,10 +44,10 @@ export interface AgentManagedSession extends AgentSession {
44
44
  isExecuting(): boolean;
45
45
 
46
46
  /**
47
- * 把 Agent configured state 修改加入当前 Session 的统一输入队列。
47
+ * 把 Agent configured state command 加入当前 Session 的统一输入队列。
48
48
  */
49
- enqueue_agent_config(
50
- mutation: AgentSessionConfigMutation,
49
+ enqueue_agent_command(
50
+ command: AgentSessionCommand,
51
51
  ): void;
52
52
  }
53
53
 
@@ -90,11 +90,11 @@ export interface SessionOptions {
90
90
  *
91
91
  * 关键点(中文)
92
92
  * - Session 创建时用它建立初始 effective env。
93
- * - 后续 Agent env 修改通过 Session 配置 mutation 在模型 turn 边界提交。
93
+ * - 后续 Agent env 修改通过 Session command step 检查点执行。
94
94
  */
95
95
  getAgentEnv: () => Record<string, string>;
96
96
 
97
- /** 创建当前 Agent configured plugin 的模型 turn 执行视图。 */
97
+ /** 创建当前 Agent configured plugin Session step 执行视图。 */
98
98
  get_agent_plugins: () => AgentPluginExecutionRuntime;
99
99
 
100
100
  /**
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Session queue command 运行时类型。
3
+ *
4
+ * 关键点(中文)
5
+ * - 配置 API 负责把 configured state 修改成功后创建 command。
6
+ * - command 与 steer 共用 Session 输入队列,并在下一次 Session step 检查点执行。
7
+ * - 这里只描述进程内提交协议,不属于持久化格式或公开 SDK 协议。
8
+ */
9
+
10
+ import type { AgentSessionSystemBlock } from "@/types/agent/SessionTypes.js";
11
+ import type { AgentPluginExecutionRuntime } from "@/types/plugin/PluginRuntime.js";
12
+
13
+ /**
14
+ * Session queue command 的归属作用域。
15
+ */
16
+ export type SessionQueueCommandScope = "agent" | "session";
17
+
18
+ /**
19
+ * Session queue command 执行时的 step 上下文。
20
+ */
21
+ export interface SessionQueueCommandContext {
22
+ /** 当前公开 Session turn 标识。 */
23
+ turn_id: string;
24
+ }
25
+
26
+ /**
27
+ * 等待在 Session step 检查点执行的 command。
28
+ */
29
+ export interface SessionQueueCommand {
30
+ /** 当前队列项固定为 command。 */
31
+ type: "command";
32
+
33
+ /** 当前 command 的稳定唯一标识。 */
34
+ command_id: string;
35
+
36
+ /** 当前配置修改属于 Agent 还是 Session。 */
37
+ scope: SessionQueueCommandScope;
38
+
39
+ /**
40
+ * 把 configured state 提交为当前 Session 的 effective state。
41
+ *
42
+ * 关键点(中文)
43
+ * - effective state 提交失败时可以抛错,但不能让后续 command 静默丢失。
44
+ * - action message 是提交后的观测记录,写入失败不能回滚已经生效的配置。
45
+ */
46
+ execute(context: SessionQueueCommandContext): Promise<void>;
47
+ }
48
+
49
+ /**
50
+ * Agent configured state 广播给已有 Session 的 command。
51
+ */
52
+ export type AgentSessionCommand =
53
+ | {
54
+ /** 当前修改固定为 instruction。 */
55
+ type: "instruction";
56
+ /** 当前 command 唯一标识。 */
57
+ command_id: string;
58
+ /** 下一 Session step 使用的 instruction blocks。 */
59
+ instruction_blocks: AgentSessionSystemBlock[];
60
+ }
61
+ | {
62
+ /** 当前修改固定为 env。 */
63
+ type: "env";
64
+ /** 当前 command 唯一标识。 */
65
+ command_id: string;
66
+ /** 下一 Session step 使用的完整 Agent env。 */
67
+ env: Record<string, string>;
68
+ }
69
+ | {
70
+ /** 当前修改固定为 plugin registry。 */
71
+ type: "plugins";
72
+ /** 当前 command 唯一标识。 */
73
+ command_id: string;
74
+ /** 当前 plugin 配置修改的用户可读标题。 */
75
+ title: string;
76
+ /** 下一 Session step 使用的 Plugin 执行视图。 */
77
+ plugins: AgentPluginExecutionRuntime;
78
+ };
@@ -202,11 +202,11 @@ export class Logger {
202
202
  }
203
203
 
204
204
  /**
205
- * 绑定进程级 projectRoot。
205
+ * 绑定当前 logger 实例的 projectRoot。
206
206
  *
207
207
  * 关键点(中文)
208
- * - 我们约束“一个进程只服务一个 projectRoot”。
209
- * - Logger 作为单例存在,但落盘目录必须在启动入口初始化后才能确定。
208
+ * - 每个 Agent / workspace 持有独立 Logger,绑定只影响当前实例。
209
+ * - 落盘目录必须在实例初始化后明确指定。
210
210
  * - 未绑定 projectRoot 时,只打印到 console,不写入 `.downcity/logs/*`。
211
211
  */
212
212
  bindProjectRoot(projectRoot: string): void {
@@ -357,16 +357,16 @@ export class Logger {
357
357
  }
358
358
  }
359
359
 
360
- export const logger = new Logger();
361
-
362
360
  /**
363
- * 获取统一 logger
361
+ * 创建独立 logger 实例。
364
362
  *
365
363
  * 说明(中文)
366
- * - 当前实现是“进程级单例 logger”(落盘路径依赖 runtime root)。
367
- * - 参数保留是为了兼容上层调用习惯:有些代码会传入 projectRoot / logLevel
368
- * - 若未来需要“多实例 logger”,可以在这里集中改,不影响调用方。
364
+ * - 每次调用都返回独立实例,避免不同 Agent / workspace 互相覆盖落盘目录。
365
+ * - 提供 projectRoot 时立即绑定日志目录;未提供时仅输出到 console
369
366
  */
370
- export function getLogger(_projectRoot?: string, _logLevel?: string): Logger {
367
+ export function getLogger(project_root?: string, log_level?: string): Logger {
368
+ const logger = new Logger(log_level);
369
+ const root = String(project_root || "").trim();
370
+ if (root) logger.bindProjectRoot(root);
371
371
  return logger;
372
372
  }