@downcity/agent 1.1.281 → 1.1.282

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 (39) hide show
  1. package/bin/agent/AgentSessions.d.ts.map +1 -1
  2. package/bin/agent/AgentSessions.js +1 -0
  3. package/bin/agent/AgentSessions.js.map +1 -1
  4. package/bin/executor/Executor.d.ts +4 -1
  5. package/bin/executor/Executor.d.ts.map +1 -1
  6. package/bin/executor/Executor.js +6 -1
  7. package/bin/executor/Executor.js.map +1 -1
  8. package/bin/session/Session.d.ts +24 -4
  9. package/bin/session/Session.d.ts.map +1 -1
  10. package/bin/session/Session.js +102 -23
  11. package/bin/session/Session.js.map +1 -1
  12. package/bin/session/storage/Instruction.d.ts +7 -5
  13. package/bin/session/storage/Instruction.d.ts.map +1 -1
  14. package/bin/session/storage/Instruction.js +9 -5
  15. package/bin/session/storage/Instruction.js.map +1 -1
  16. package/bin/session/storage/Paths.d.ts +2 -2
  17. package/bin/session/storage/Paths.js +2 -2
  18. package/bin/types/agent/SessionActor.d.ts +3 -1
  19. package/bin/types/agent/SessionActor.d.ts.map +1 -1
  20. package/bin/types/agent/SessionTypes.d.ts +2 -2
  21. package/bin/types/agent/SessionTypes.d.ts.map +1 -1
  22. package/bin/types/session/SessionInstruction.d.ts +3 -3
  23. package/bin/types/session/SessionInstruction.d.ts.map +1 -1
  24. package/bin/types/session/SessionInstruction.js +2 -2
  25. package/bin/types/session/SessionOptions.d.ts +9 -1
  26. package/bin/types/session/SessionOptions.d.ts.map +1 -1
  27. package/package.json +2 -2
  28. package/scripts/agent-compiler.mjs +12 -5
  29. package/scripts/session-config-turn-boundary.test.mjs +141 -5
  30. package/src/agent/AgentSessions.ts +1 -0
  31. package/src/executor/Executor.ts +9 -1
  32. package/src/session/Session.ts +115 -26
  33. package/src/session/storage/Instruction.ts +18 -5
  34. package/src/session/storage/Paths.ts +2 -2
  35. package/src/types/agent/SessionActor.ts +4 -1
  36. package/src/types/agent/SessionTypes.ts +2 -2
  37. package/src/types/session/SessionInstruction.ts +3 -3
  38. package/src/types/session/SessionOptions.ts +10 -1
  39. package/tsconfig.tsbuildinfo +1 -1
@@ -75,6 +75,7 @@ import { buildSessionInfo } from "@/session/browse/Browse.js";
75
75
  import { ensureSessionTitle } from "@/session/SessionTitle.js";
76
76
  import { readSessionMetadata } from "@/session/storage/Metadata.js";
77
77
  import {
78
+ has_session_instruction,
78
79
  read_session_instruction,
79
80
  write_session_instruction,
80
81
  } from "@/session/storage/Instruction.js";
@@ -107,10 +108,16 @@ export class Session implements AgentSession {
107
108
  private readonly get_agent_env: SessionOptions["getAgentEnv"];
108
109
  private readonly get_agent_model: SessionOptions["getAgentModel"];
109
110
  private readonly get_agent_plugins: SessionOptions["get_agent_plugins"];
111
+ private readonly get_instruction_system_blocks:
112
+ SessionOptions["get_instruction_system_blocks"];
110
113
  private effective_instruction_system_blocks: AgentSessionSystemBlock[];
111
114
  private instruction_initialize_promise: Promise<void> | null = null;
112
115
  private effective_agent_env: Record<string, string>;
113
116
  private effective_agent_plugins: AgentPluginExecutionRuntime;
117
+ /** 当前 Session 首次生成后固定的完整 system snapshot。 */
118
+ private system_snapshot_blocks: AgentSessionSystemBlock[] | null = null;
119
+ /** 串行化 snapshot / syncshot 对 system 与 instruction.md 的修改。 */
120
+ private system_mutation_chain: Promise<void> = Promise.resolve();
114
121
  private readonly state: SessionState;
115
122
  private readonly session_turn: SessionTurn;
116
123
  private runtime_port: SessionPort | null = null;
@@ -124,6 +131,7 @@ export class Session implements AgentSession {
124
131
  this.get_agent_env = options.getAgentEnv;
125
132
  this.get_agent_model = options.getAgentModel;
126
133
  this.get_agent_plugins = options.get_agent_plugins;
134
+ this.get_instruction_system_blocks = options.get_instruction_system_blocks;
127
135
  this.effective_instruction_system_blocks = options
128
136
  .instruction_system_blocks
129
137
  .map((block) => ({ ...block }));
@@ -200,23 +208,52 @@ export class Session implements AgentSession {
200
208
  }
201
209
 
202
210
  /**
203
- * 把当前 Session 生效的自定义 instruction 显式固化到 instruction.md。
211
+ * 把当前 Session 首次生成后固定的完整 system 显式固化到 instruction.md。
204
212
  *
205
213
  * 关键点(中文)
206
- * - 只写入 `instruction` 来源的 block,不包含 SDK core 与 plugin system
207
- * - 多个 instruction block 按原顺序合并为一个 Markdown 文档。
214
+ * - 包含 instructionSDK core、plugin system Session context
215
+ * - 多个 system block 按原顺序合并为一个 Markdown 文档。
208
216
  */
209
217
  async snapshot(): Promise<void> {
210
- await this.initialize_instruction();
211
- const instruction = this.effective_instruction_system_blocks
212
- .filter((block) => block.source === "instruction")
213
- .map((block) => block.content)
214
- .join("\n\n");
215
- await write_session_instruction({
216
- project_root: this.project_root,
217
- agent_id: this.agentId,
218
- session_id: this.id,
219
- instruction,
218
+ await this.run_system_mutation(async () => {
219
+ const system_snapshot = await this.system();
220
+ await this.write_system_snapshot(system_snapshot.blocks);
221
+ });
222
+ }
223
+
224
+ /**
225
+ * 使用 Agent 当前 instruction 与 plugin 重新生成一次完整 system。
226
+ *
227
+ * 关键点(中文)
228
+ * - 只替换内存 snapshot,不改变 plugin execution view。
229
+ * - instruction.md 已存在时同步覆盖;不存在时不自动创建。
230
+ * - 当前已经发出的 provider 请求不受影响,后续 step 使用新 snapshot。
231
+ */
232
+ async syncshot(): Promise<void> {
233
+ await this.run_system_mutation(async () => {
234
+ await this.initialize_instruction();
235
+ const should_persist = await has_session_instruction({
236
+ project_root: this.project_root,
237
+ agent_id: this.agentId,
238
+ session_id: this.id,
239
+ });
240
+ const run_context: SessionRunContext = {
241
+ sessionId: this.id,
242
+ injectedUserMessages: [],
243
+ deferredPersistedUserMessages: [],
244
+ pendingAssistantFileParts: [],
245
+ };
246
+ const composed = await this.composer.compose(
247
+ await this.create_compose_input(run_context, 0, true),
248
+ );
249
+ const next_blocks = resolve_composed_system_blocks(composed);
250
+
251
+ if (should_persist) {
252
+ await this.write_system_snapshot(next_blocks);
253
+ }
254
+ this.effective_instruction_system_blocks =
255
+ this.get_instruction_system_blocks().map((block) => ({ ...block }));
256
+ this.system_snapshot_blocks = next_blocks;
220
257
  });
221
258
  }
222
259
 
@@ -556,6 +593,7 @@ export class Session implements AgentSession {
556
593
  instruction_system_blocks: this.effective_instruction_system_blocks.map(
557
594
  (block) => ({ ...block }),
558
595
  ),
596
+ get_instruction_system_blocks: this.get_instruction_system_blocks,
559
597
  getAgentEnv: this.get_agent_env,
560
598
  get_agent_plugins: this.get_agent_plugins,
561
599
  getManagedPluginSystemBlocks: this.get_managed_plugin_system_blocks,
@@ -579,7 +617,7 @@ export class Session implements AgentSession {
579
617
  return new SessionClass(options) as this;
580
618
  }
581
619
 
582
- /** 恢复显式固化的 instruction.md;文件不存在时保留创建时 instruction。 */
620
+ /** 恢复显式固化的完整 system snapshot;文件不存在时等待首次生成。 */
583
621
  private async initialize_instruction(): Promise<void> {
584
622
  if (!this.instruction_initialize_promise) {
585
623
  this.instruction_initialize_promise = (async () => {
@@ -591,6 +629,13 @@ export class Session implements AgentSession {
591
629
  if (persisted_instruction === null) return;
592
630
 
593
631
  const instruction = persisted_instruction.trim();
632
+ this.system_snapshot_blocks = instruction
633
+ ? [{
634
+ source: "instruction" as const,
635
+ name: "snapshot",
636
+ content: instruction,
637
+ }]
638
+ : [];
594
639
  const stable_system_blocks = this.effective_instruction_system_blocks
595
640
  .filter((block) => block.source !== "instruction")
596
641
  .map((block) => ({ ...block }));
@@ -650,6 +695,7 @@ export class Session implements AgentSession {
650
695
  getModel: () => this.get_model(),
651
696
  logger: this.logger,
652
697
  get_plugins: () => this.effective_agent_plugins,
698
+ apply_system_snapshot: (input) => this.apply_system_snapshot(input),
653
699
  });
654
700
  }
655
701
 
@@ -657,10 +703,18 @@ export class Session implements AgentSession {
657
703
  private async create_compose_input(
658
704
  run_context: SessionRunContext,
659
705
  retry_count: number,
706
+ refresh_system = false,
660
707
  ): Promise<SessionComposeInput> {
661
- const plugin_system_blocks = run_context.agentPlugins
662
- ? await run_context.agentPlugins.systemBlocks(run_context)
663
- : await this.effective_agent_plugins.systemBlocks(run_context);
708
+ const instruction_system_blocks = refresh_system
709
+ ? this.get_instruction_system_blocks().map((block) => ({ ...block }))
710
+ : this.effective_instruction_system_blocks.map((block) => ({ ...block }));
711
+ const plugin_system_blocks = this.system_snapshot_blocks && !refresh_system
712
+ ? []
713
+ : refresh_system
714
+ ? await this.get_agent_plugins().systemBlocks(run_context)
715
+ : run_context.agentPlugins
716
+ ? await run_context.agentPlugins.systemBlocks(run_context)
717
+ : await this.effective_agent_plugins.systemBlocks(run_context);
664
718
  return {
665
719
  session: {
666
720
  agent_id: this.agentId,
@@ -674,17 +728,14 @@ export class Session implements AgentSession {
674
728
  model_context_window: this.get_model_context_window(),
675
729
  env: Object.freeze({ ...this.effective_agent_env }),
676
730
  systems: Object.freeze(
677
- this.effective_instruction_system_blocks.map(
678
- (block) => block.content,
679
- ),
731
+ instruction_system_blocks.map((block) => block.content),
680
732
  ),
681
733
  tools: Object.freeze({ ...this.tools }),
682
- instruction_system_blocks:
683
- this.effective_instruction_system_blocks.map(
684
- (block) => ({ ...block }),
685
- ),
734
+ instruction_system_blocks,
686
735
  managed_plugin_system_blocks:
687
- await this.get_managed_plugin_system_blocks(),
736
+ this.system_snapshot_blocks && !refresh_system
737
+ ? []
738
+ : await this.get_managed_plugin_system_blocks(),
688
739
  plugin_system_blocks,
689
740
  },
690
741
  history: await this.session_messages.context_snapshot(),
@@ -703,9 +754,47 @@ export class Session implements AgentSession {
703
754
  deferredPersistedUserMessages: [],
704
755
  pendingAssistantFileParts: [],
705
756
  };
706
- return await this.composer.compose(
757
+ const composed = await this.composer.compose(
707
758
  await this.create_compose_input(run_context, 0),
708
759
  );
760
+ return this.apply_system_snapshot(composed);
761
+ }
762
+
763
+ /** 固定或应用当前 Session 的 system snapshot。 */
764
+ private apply_system_snapshot(input: SessionStepInput): SessionStepInput {
765
+ if (!this.system_snapshot_blocks) {
766
+ this.system_snapshot_blocks = resolve_composed_system_blocks(input);
767
+ }
768
+
769
+ return {
770
+ ...input,
771
+ system: this.system_snapshot_blocks.map((block) => ({
772
+ role: "system" as const,
773
+ content: block.content,
774
+ })),
775
+ system_blocks: this.system_snapshot_blocks.map((block) => ({ ...block })),
776
+ };
777
+ }
778
+
779
+ /** 串行执行一次 Session system 修改。 */
780
+ private async run_system_mutation(
781
+ operation: () => Promise<void>,
782
+ ): Promise<void> {
783
+ const next = this.system_mutation_chain.then(operation, operation);
784
+ this.system_mutation_chain = next.catch(() => undefined);
785
+ await next;
786
+ }
787
+
788
+ /** 把指定完整 system blocks 原子写入 instruction.md。 */
789
+ private async write_system_snapshot(
790
+ blocks: readonly AgentSessionSystemBlock[],
791
+ ): Promise<void> {
792
+ await write_session_instruction({
793
+ project_root: this.project_root,
794
+ agent_id: this.agentId,
795
+ session_id: this.id,
796
+ instruction: blocks.map((block) => block.content).join("\n\n"),
797
+ });
709
798
  }
710
799
 
711
800
  /** 提交 Composer 生成的 Segment 压缩计划。 */
@@ -1,9 +1,9 @@
1
1
  /**
2
- * Session instruction 显式快照存储。
2
+ * Session system 显式快照存储。
3
3
  *
4
4
  * 关键点(中文)
5
- * - instruction.md 是可选文件,不存在时由 Session 使用 Agent 当前 instruction
6
- * - 空文件也是有效快照,用于显式固化没有自定义 instruction 的状态。
5
+ * - instruction.md 是可选文件,不存在时由 Session 在内存中重新生成完整 system
6
+ * - 空文件也是有效的完整 system 快照。
7
7
  * - 写入使用同目录临时文件替换,避免进程中断留下半份内容。
8
8
  */
9
9
 
@@ -16,7 +16,7 @@ import type {
16
16
  WriteSessionInstructionInput,
17
17
  } from "@/types/session/SessionInstruction.js";
18
18
 
19
- /** 读取 Session 显式固化的 instruction;文件不存在时返回 null。 */
19
+ /** 读取 Session 显式固化的完整 system;文件不存在时返回 null。 */
20
20
  export async function read_session_instruction(
21
21
  input: SessionInstructionStorageLocation,
22
22
  ): Promise<string | null> {
@@ -33,7 +33,20 @@ export async function read_session_instruction(
33
33
  }
34
34
  }
35
35
 
36
- /** 原子覆盖当前 Session instruction.md。 */
36
+ /** 判断当前 Session 是否已经显式持久化 instruction.md。 */
37
+ export async function has_session_instruction(
38
+ input: SessionInstructionStorageLocation,
39
+ ): Promise<boolean> {
40
+ return await fs.pathExists(
41
+ getSdkAgentSessionInstructionPath(
42
+ input.project_root,
43
+ input.agent_id,
44
+ input.session_id,
45
+ ),
46
+ );
47
+ }
48
+
49
+ /** 使用完整 system Markdown 原子覆盖当前 Session 的 instruction.md。 */
37
50
  export async function write_session_instruction(
38
51
  input: WriteSessionInstructionInput,
39
52
  ): Promise<void> {
@@ -130,11 +130,11 @@ export function getSdkAgentSessionDirPath(
130
130
  }
131
131
 
132
132
  /**
133
- * 单个 session 显式固化的 instruction.md 路径。
133
+ * 单个 session 显式固化完整 system 的 instruction.md 路径。
134
134
  *
135
135
  * 关键点(中文)
136
136
  * - 文件不存在表示 Session 恢复时继续采用 Agent 当前 instruction。
137
- * - 空文件表示调用方显式固化了空 instruction
137
+ * - 空文件表示调用方显式固化了空 system
138
138
  */
139
139
  export function getSdkAgentSessionInstructionPath(
140
140
  projectRoot: string,
@@ -125,9 +125,12 @@ export interface AgentSession extends AgentSessionActor {
125
125
  /** 写入当前 session 默认配置。 */
126
126
  set(input: AgentSessionSetInput): Promise<void>;
127
127
 
128
- /** 把当前 Session 生效的自定义 instruction 显式固化到 instruction.md。 */
128
+ /** 把当前 Session 首次生成后固定的完整 system 显式固化到 instruction.md。 */
129
129
  snapshot(): Promise<void>;
130
130
 
131
+ /** 使用 Agent 当前 instruction 与 plugin 显式重新生成 Session system。 */
132
+ syncshot(): Promise<void>;
133
+
131
134
  /** 从当前 session 创建一个分叉会话。 */
132
135
  fork(input?: AgentSessionForkInput | string): Promise<AgentSession>;
133
136
  }
@@ -203,7 +203,7 @@ export interface AgentSessionSystemSessionInfo {
203
203
  }
204
204
 
205
205
  /**
206
- * 当前 session 生效的完整 system prompt 快照。
206
+ * 当前 session 首次生成后固定的完整 system prompt 快照。
207
207
  */
208
208
  export interface AgentSessionSystemSnapshot {
209
209
  /** 当前 sessionId。 */
@@ -217,7 +217,7 @@ export interface AgentSessionSystemSnapshot {
217
217
  * - 每轮动态信息应由调用方放入 user message,避免破坏 instruction 缓存命中。
218
218
  */
219
219
  session: AgentSessionSystemSessionInfo;
220
- /** 当前生效的 system blocks,按进入模型的顺序排列。 */
220
+ /** 首次生成后固定的 system blocks,按进入模型的顺序排列。 */
221
221
  blocks: AgentSessionSystemBlock[];
222
222
  }
223
223
 
@@ -1,9 +1,9 @@
1
1
  /**
2
- * Session instruction 显式快照存储类型。
2
+ * Session system 显式快照存储类型。
3
3
  *
4
4
  * 关键点(中文)
5
5
  * - 这里只描述 instruction.md 的定位与写入输入。
6
- * - 文件存在性本身用于表达 Session 是否启用显式 instruction 快照。
6
+ * - 文件存在性本身用于表达 Session 是否启用显式 system 快照。
7
7
  */
8
8
 
9
9
  /** Session instruction.md 的稳定定位信息。 */
@@ -19,6 +19,6 @@ export interface SessionInstructionStorageLocation {
19
19
  /** 原子写入 Session instruction.md 使用的完整输入。 */
20
20
  export interface WriteSessionInstructionInput
21
21
  extends SessionInstructionStorageLocation {
22
- /** 当前 Session 生效的自定义 instruction Markdown。 */
22
+ /** 当前 Session 首次生成后固定的完整 system Markdown。 */
23
23
  instruction: string;
24
24
  }
@@ -78,10 +78,19 @@ export interface SessionOptions {
78
78
  *
79
79
  * 关键点(中文)
80
80
  * - Session 创建后不再动态读取 Agent instruction。
81
- * - `session.snapshot()` 只会把其中 `instruction` 来源的内容显式写入本地文件。
81
+ * - `session.snapshot()` 会把首次生成后固定的完整 system 显式写入本地文件。
82
82
  */
83
83
  instruction_system_blocks: AgentSessionSystemBlock[];
84
84
 
85
+ /**
86
+ * 读取当前 Agent configured instruction system blocks。
87
+ *
88
+ * 关键点(中文)
89
+ * - 仅供 `session.syncshot()` 显式重新生成 system 使用。
90
+ * - 普通 Session 执行仍使用首次生成后固定的 system snapshot。
91
+ */
92
+ get_instruction_system_blocks: () => AgentSessionSystemBlock[];
93
+
85
94
  /**
86
95
  * 读取当前 Agent configured env。
87
96
  *