@downcity/agent 1.1.11 → 1.1.12

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 (37) hide show
  1. package/bin/index.d.ts +1 -1
  2. package/bin/index.d.ts.map +1 -1
  3. package/bin/index.js.map +1 -1
  4. package/bin/sdk/Agent.d.ts +11 -6
  5. package/bin/sdk/Agent.d.ts.map +1 -1
  6. package/bin/sdk/Agent.js +60 -16
  7. package/bin/sdk/Agent.js.map +1 -1
  8. package/bin/sdk/AgentSdkTypes.d.ts +95 -0
  9. package/bin/sdk/AgentSdkTypes.d.ts.map +1 -1
  10. package/bin/sdk/RemoteAgent.d.ts +3 -3
  11. package/bin/sdk/RemoteAgent.d.ts.map +1 -1
  12. package/bin/sdk/RemoteAgent.js +5 -2
  13. package/bin/sdk/RemoteAgent.js.map +1 -1
  14. package/bin/sdk/SdkSessionSystemComposer.d.ts +52 -19
  15. package/bin/sdk/SdkSessionSystemComposer.d.ts.map +1 -1
  16. package/bin/sdk/SdkSessionSystemComposer.js +102 -48
  17. package/bin/sdk/SdkSessionSystemComposer.js.map +1 -1
  18. package/bin/sdk/Session.d.ts +15 -13
  19. package/bin/sdk/Session.d.ts.map +1 -1
  20. package/bin/sdk/Session.js +47 -25
  21. package/bin/sdk/Session.js.map +1 -1
  22. package/bin/sdk/SessionMetadata.d.ts +4 -0
  23. package/bin/sdk/SessionMetadata.d.ts.map +1 -1
  24. package/bin/sdk/SessionMetadata.js +16 -0
  25. package/bin/sdk/SessionMetadata.js.map +1 -1
  26. package/bin/session/types/SessionHistoryMeta.d.ts +2 -0
  27. package/bin/session/types/SessionHistoryMeta.d.ts.map +1 -1
  28. package/package.json +1 -1
  29. package/src/index.ts +4 -0
  30. package/src/sdk/Agent.ts +70 -18
  31. package/src/sdk/AgentSdkTypes.ts +113 -0
  32. package/src/sdk/RemoteAgent.ts +10 -4
  33. package/src/sdk/SdkSessionSystemComposer.ts +165 -77
  34. package/src/sdk/Session.ts +61 -32
  35. package/src/sdk/SessionMetadata.ts +18 -0
  36. package/src/session/types/SessionHistoryMeta.ts +2 -0
  37. package/tsconfig.tsbuildinfo +1 -1
@@ -3,19 +3,27 @@
3
3
  *
4
4
  * 关键点(中文)
5
5
  * - 面向 `Agent` SDK 的本地会话执行场景。
6
- * - 注入静态 PROFILE / SOUL / core prompt、显式注入 service system、显式注册 plugin system 与运行时时钟上下文。
6
+ * - 注入调用方显式传入的静态 instruction、显式注入 service system 与显式注册 plugin system
7
+ * - SDK 不在 system 中注入动态变量;动态上下文应由调用方放入 user message。
7
8
  */
8
9
 
9
10
  import { SessionSystemComposer } from "@session/composer/system/SessionSystemComposer.js";
10
11
  import { getSessionRunScope } from "@session/SessionRunScope.js";
11
- import { transformPromptsIntoSystemMessages } from "@session/composer/system/default/PromptRenderer.js";
12
- import { buildRuntimeClockSystemPrompt } from "@session/composer/system/default/variables/VariableReplacer.js";
13
12
  import type { SessionSystemMessage } from "@/session/types/SessionPrompts.js";
13
+ import type {
14
+ AgentSessionSystemBlock,
15
+ AgentSessionSystemSessionInfo,
16
+ } from "@/sdk/AgentSdkTypes.js";
14
17
 
15
18
  /**
16
- * 解析 SDK session system messages 的输入。
19
+ * 解析 SDK session system blocks 的输入。
17
20
  */
18
- export interface ResolveSdkSessionSystemMessagesParams {
21
+ export interface ResolveSdkSessionSystemBlocksParams {
22
+ /**
23
+ * 当前 agent 的稳定标识。
24
+ */
25
+ agentId: string;
26
+
19
27
  /**
20
28
  * 当前 agent 绑定的项目根目录。
21
29
  */
@@ -27,128 +35,205 @@ export interface ResolveSdkSessionSystemMessagesParams {
27
35
  sessionId: string;
28
36
 
29
37
  /**
30
- * 读取当前生效的静态 system 文本集合。
38
+ * 当前 session 首次创建时间(ms)。
39
+ */
40
+ createdAt: number;
41
+
42
+ /**
43
+ * 当前 session 初始化时解析到的系统时区。
31
44
  */
32
- getStaticSystemPrompts: () => string[];
45
+ timezone: string;
33
46
 
34
47
  /**
35
- * 读取当前显式注入 service system 文本集合。
48
+ * 读取当前 SDK 调用方传入的 instruction system blocks。
36
49
  */
37
- getServiceSystemPrompts: () => Promise<string[]>;
50
+ getInstructionSystemBlocks: () => AgentSessionSystemBlock[];
38
51
 
39
52
  /**
40
- * 读取当前显式注册 plugin 的 system 文本集合。
53
+ * 读取当前显式注入 service 的 system blocks。
41
54
  */
42
- getPluginSystemPrompts: () => Promise<string[]>;
55
+ getServiceSystemBlocks: () => Promise<AgentSessionSystemBlock[]>;
56
+
57
+ /**
58
+ * 读取当前显式注册 plugin 的 system blocks。
59
+ */
60
+ getPluginSystemBlocks: () => Promise<AgentSessionSystemBlock[]>;
43
61
  }
44
62
 
45
63
  type SdkSessionSystemComposerOptions = {
46
64
  /**
47
- * 当前 agent 绑定的项目根目录。
65
+ * 当前 agent 的稳定标识。
48
66
  */
49
- projectRoot: string;
67
+ agentId: string;
50
68
 
51
69
  /**
52
- * 读取当前生效的静态 system 文本集合。
70
+ * 当前 agent 绑定的项目根目录。
53
71
  */
54
- getStaticSystemPrompts: () => string[];
72
+ projectRoot: string;
55
73
 
56
74
  /**
57
- * 读取当前显式注册 plugin 的 system 文本集合。
75
+ * 读取当前 session 首次创建时间(ms)。
58
76
  */
59
- getPluginSystemPrompts: () => Promise<string[]>;
77
+ getSessionCreatedAt: () => number;
60
78
 
61
79
  /**
62
- * 读取当前显式注入 service 的 system 文本集合。
80
+ * 读取当前 session 初始化时解析到的系统时区。
63
81
  */
64
- getServiceSystemPrompts: () => Promise<string[]>;
65
- };
82
+ getSessionTimezone: () => string;
66
83
 
67
- async function resolvePromptMessages(params: {
68
84
  /**
69
- * 原始 system prompt 文本集合。
85
+ * 读取当前 SDK 调用方传入的 instruction system blocks。
70
86
  */
71
- prompts: string[];
87
+ getInstructionSystemBlocks: () => AgentSessionSystemBlock[];
88
+
72
89
  /**
73
- * 当前项目根目录。
90
+ * 读取当前显式注册 plugin 的 system blocks。
74
91
  */
75
- projectRoot: string;
92
+ getPluginSystemBlocks: () => Promise<AgentSessionSystemBlock[]>;
93
+
76
94
  /**
77
- * 当前 sessionId
95
+ * 读取当前显式注入 service 的 system blocks
78
96
  */
79
- sessionId: string;
80
- }): Promise<SessionSystemMessage[]> {
81
- const nonEmptyPrompts = params.prompts.filter((item) =>
82
- String(item || "").trim(),
83
- );
84
- return await transformPromptsIntoSystemMessages(nonEmptyPrompts, {
85
- projectPath: params.projectRoot,
86
- sessionId: params.sessionId,
87
- variableMode: "stable",
88
- });
97
+ getServiceSystemBlocks: () => Promise<AgentSessionSystemBlock[]>;
98
+ };
99
+
100
+ function normalizeSystemBlocks(
101
+ blocks: AgentSessionSystemBlock[],
102
+ ): AgentSessionSystemBlock[] {
103
+ if (!Array.isArray(blocks)) return [];
104
+ return blocks
105
+ .map((block) => {
106
+ const content = String(block?.content || "").trim();
107
+ if (!content) return null;
108
+ const source = block.source;
109
+ if (
110
+ source !== "core" &&
111
+ source !== "instruction" &&
112
+ source !== "service" &&
113
+ source !== "plugin" &&
114
+ source !== "session"
115
+ ) {
116
+ return null;
117
+ }
118
+ return {
119
+ source,
120
+ name: String(block.name || source).trim() || source,
121
+ content,
122
+ } satisfies AgentSessionSystemBlock;
123
+ })
124
+ .filter((block): block is AgentSessionSystemBlock => Boolean(block));
125
+ }
126
+
127
+ function createSessionInfo(
128
+ params: Pick<
129
+ ResolveSdkSessionSystemBlocksParams,
130
+ "agentId" | "sessionId" | "projectRoot" | "createdAt" | "timezone"
131
+ >,
132
+ ): AgentSessionSystemSessionInfo {
133
+ const createdAt = Number.isFinite(params.createdAt) ? params.createdAt : 0;
134
+ return {
135
+ agentId: String(params.agentId || "").trim(),
136
+ sessionId: String(params.sessionId || "").trim(),
137
+ projectRoot: String(params.projectRoot || "").trim(),
138
+ createdAt: new Date(createdAt).toISOString(),
139
+ timezone: String(params.timezone || "").trim() || "UTC",
140
+ };
141
+ }
142
+
143
+ function createSessionSystemBlock(
144
+ session: AgentSessionSystemSessionInfo,
145
+ ): AgentSessionSystemBlock {
146
+ const content = [
147
+ "当前会话上下文:",
148
+ `你正在服务 agent "${session.agentId}" 的 session "${session.sessionId}"。`,
149
+ `当前项目根目录是 "${session.projectRoot}"。`,
150
+ `本会话创建于 ${session.createdAt},参考时区是 ${session.timezone}。`,
151
+ "这个创建时间是当前会话的稳定参考时间,不代表每轮运行时的当前时间。",
152
+ "如果用户消息中提供了新的当前时间、相对时间或其他动态上下文,应优先使用用户消息中的动态信息。",
153
+ ].join("\n");
154
+ return {
155
+ source: "session",
156
+ name: "context",
157
+ content,
158
+ };
89
159
  }
90
160
 
91
161
  /**
92
- * 解析 SDK session 当前生效的 system messages
162
+ * 解析 SDK session 当前生效的 system blocks
93
163
  */
94
- export async function resolveSdkSessionSystemMessages(
95
- params: ResolveSdkSessionSystemMessagesParams,
96
- ): Promise<SessionSystemMessage[]> {
164
+ export async function resolveSdkSessionSystemBlocks(
165
+ params: ResolveSdkSessionSystemBlocksParams,
166
+ ): Promise<AgentSessionSystemBlock[]> {
167
+ const agentId = String(params.agentId || "").trim();
97
168
  const projectRoot = String(params.projectRoot || "").trim();
98
169
  const sessionId = String(params.sessionId || "").trim();
170
+ const createdAt = Number(params.createdAt || 0);
171
+ const timezone = String(params.timezone || "").trim();
172
+ if (!agentId) {
173
+ throw new Error("resolveSdkSessionSystemBlocks requires a non-empty agentId");
174
+ }
99
175
  if (!projectRoot) {
100
- throw new Error("resolveSdkSessionSystemMessages requires a non-empty projectRoot");
176
+ throw new Error("resolveSdkSessionSystemBlocks requires a non-empty projectRoot");
101
177
  }
102
178
  if (!sessionId) {
103
- throw new Error("resolveSdkSessionSystemMessages requires a non-empty sessionId");
179
+ throw new Error("resolveSdkSessionSystemBlocks requires a non-empty sessionId");
180
+ }
181
+ if (!Number.isFinite(createdAt) || createdAt <= 0) {
182
+ throw new Error("resolveSdkSessionSystemBlocks requires a valid createdAt");
183
+ }
184
+ if (!timezone) {
185
+ throw new Error("resolveSdkSessionSystemBlocks requires a non-empty timezone");
104
186
  }
105
- const staticMessages = await resolvePromptMessages({
106
- prompts: params.getStaticSystemPrompts(),
107
- projectRoot,
108
- sessionId,
109
- });
110
- const serviceMessages = await resolvePromptMessages({
111
- prompts: await params.getServiceSystemPrompts(),
112
- projectRoot,
113
- sessionId,
114
- });
115
- const pluginMessages = await resolvePromptMessages({
116
- prompts: await params.getPluginSystemPrompts(),
117
- projectRoot,
118
- sessionId,
119
- });
120
-
121
187
  return [
122
- ...staticMessages,
123
- ...serviceMessages,
124
- ...pluginMessages,
125
- {
126
- role: "system" as const,
127
- content: buildRuntimeClockSystemPrompt({
128
- projectPath: projectRoot,
129
- sessionId,
130
- }),
131
- },
188
+ ...normalizeSystemBlocks(params.getInstructionSystemBlocks()),
189
+ ...normalizeSystemBlocks(await params.getServiceSystemBlocks()),
190
+ ...normalizeSystemBlocks(await params.getPluginSystemBlocks()),
191
+ // session block 放在最后,尽量保留前缀 system blocks 的跨 session 缓存命中。
192
+ createSessionSystemBlock(
193
+ createSessionInfo({ agentId, projectRoot, sessionId, createdAt, timezone }),
194
+ ),
132
195
  ];
133
196
  }
134
197
 
198
+ /**
199
+ * 解析 SDK session 当前生效的 system messages。
200
+ */
201
+ export async function resolveSdkSessionSystemMessages(
202
+ params: ResolveSdkSessionSystemBlocksParams,
203
+ ): Promise<SessionSystemMessage[]> {
204
+ const blocks = await resolveSdkSessionSystemBlocks(params);
205
+ return blocks.map((block) => ({
206
+ role: "system" as const,
207
+ content: block.content,
208
+ }));
209
+ }
210
+
135
211
  /**
136
212
  * SDK Session system composer 实现。
137
213
  */
138
214
  export class SdkSessionSystemComposer extends SessionSystemComposer {
139
215
  readonly name = "sdk_prompt_system";
140
216
 
217
+ private readonly agentId: string;
141
218
  private readonly projectRoot: string;
142
- private readonly getStaticSystemPrompts: SdkSessionSystemComposerOptions["getStaticSystemPrompts"];
143
- private readonly getServiceSystemPrompts: SdkSessionSystemComposerOptions["getServiceSystemPrompts"];
144
- private readonly getPluginSystemPrompts: SdkSessionSystemComposerOptions["getPluginSystemPrompts"];
219
+ private readonly getSessionCreatedAt: SdkSessionSystemComposerOptions["getSessionCreatedAt"];
220
+ private readonly getSessionTimezone: SdkSessionSystemComposerOptions["getSessionTimezone"];
221
+ private readonly getInstructionSystemBlocks: SdkSessionSystemComposerOptions["getInstructionSystemBlocks"];
222
+ private readonly getServiceSystemBlocks: SdkSessionSystemComposerOptions["getServiceSystemBlocks"];
223
+ private readonly getPluginSystemBlocks: SdkSessionSystemComposerOptions["getPluginSystemBlocks"];
145
224
 
146
225
  constructor(options: SdkSessionSystemComposerOptions) {
147
226
  super();
227
+ this.agentId = String(options.agentId || "").trim();
148
228
  this.projectRoot = String(options.projectRoot || "").trim();
149
- this.getStaticSystemPrompts = options.getStaticSystemPrompts;
150
- this.getServiceSystemPrompts = options.getServiceSystemPrompts;
151
- this.getPluginSystemPrompts = options.getPluginSystemPrompts;
229
+ this.getSessionCreatedAt = options.getSessionCreatedAt;
230
+ this.getSessionTimezone = options.getSessionTimezone;
231
+ this.getInstructionSystemBlocks = options.getInstructionSystemBlocks;
232
+ this.getServiceSystemBlocks = options.getServiceSystemBlocks;
233
+ this.getPluginSystemBlocks = options.getPluginSystemBlocks;
234
+ if (!this.agentId) {
235
+ throw new Error("SdkSessionSystemComposer requires a non-empty agentId");
236
+ }
152
237
  if (!this.projectRoot) {
153
238
  throw new Error("SdkSessionSystemComposer requires a non-empty projectRoot");
154
239
  }
@@ -163,11 +248,14 @@ export class SdkSessionSystemComposer extends SessionSystemComposer {
163
248
  throw new Error("SdkSessionSystemComposer.resolve requires a non-empty sessionId");
164
249
  }
165
250
  return await resolveSdkSessionSystemMessages({
251
+ agentId: this.agentId,
166
252
  projectRoot: this.projectRoot,
167
253
  sessionId,
168
- getStaticSystemPrompts: this.getStaticSystemPrompts,
169
- getServiceSystemPrompts: this.getServiceSystemPrompts,
170
- getPluginSystemPrompts: this.getPluginSystemPrompts,
254
+ createdAt: this.getSessionCreatedAt(),
255
+ timezone: this.getSessionTimezone(),
256
+ getInstructionSystemBlocks: this.getInstructionSystemBlocks,
257
+ getServiceSystemBlocks: this.getServiceSystemBlocks,
258
+ getPluginSystemBlocks: this.getPluginSystemBlocks,
171
259
  });
172
260
  }
173
261
  }
@@ -22,14 +22,19 @@ import type {
22
22
  AgentSessionRunResult,
23
23
  AgentSessionSetInput,
24
24
  AgentSessionStreamEvent,
25
+ AgentSessionSystemBlock,
26
+ AgentSessionSystemSnapshot,
25
27
  } from "@/sdk/AgentSdkTypes.js";
26
28
  import type { SessionMessageV1 } from "@/session/types/SessionMessages.js";
27
- import { SdkSessionSystemComposer } from "@/sdk/SdkSessionSystemComposer.js";
28
- import { resolveSdkSessionSystemMessages } from "@/sdk/SdkSessionSystemComposer.js";
29
+ import {
30
+ resolveSdkSessionSystemBlocks,
31
+ SdkSessionSystemComposer,
32
+ } from "@/sdk/SdkSessionSystemComposer.js";
29
33
  import {
30
34
  inferModelLabel,
31
35
  patchSdkSessionModelLabel,
32
36
  readSdkSessionMetadata,
37
+ resolveSystemTimezone,
33
38
  writeSdkSessionMetadata,
34
39
  } from "@/sdk/SessionMetadata.js";
35
40
  import {
@@ -75,19 +80,19 @@ type SdkSessionOptions = {
75
80
  };
76
81
 
77
82
  /**
78
- * 读取静态 system 文本集合。
83
+ * 读取当前 SDK 调用方传入的 instruction system blocks。
79
84
  */
80
- getStaticSystemPrompts: () => string[];
85
+ getInstructionSystemBlocks: () => AgentSessionSystemBlock[];
81
86
 
82
87
  /**
83
- * 读取当前 agent 显式注入 service 的 system 文本集合。
88
+ * 读取当前 agent 显式注入 service 的 system blocks。
84
89
  */
85
- getServiceSystemPrompts: () => Promise<string[]>;
90
+ getServiceSystemBlocks: () => Promise<AgentSessionSystemBlock[]>;
86
91
 
87
92
  /**
88
- * 读取当前 agent 显式注册 plugin 的 system 文本集合。
93
+ * 读取当前 agent 显式注册 plugin 的 system blocks。
89
94
  */
90
- getPluginSystemPrompts: () => Promise<string[]>;
95
+ getPluginSystemBlocks: () => Promise<AgentSessionSystemBlock[]>;
91
96
  };
92
97
 
93
98
  /**
@@ -100,12 +105,14 @@ export class SdkSession {
100
105
  private readonly projectRoot: string;
101
106
  private readonly tools: Record<string, Tool>;
102
107
  private readonly logger: SdkSessionOptions["logger"];
103
- private readonly getStaticSystemPrompts: SdkSessionOptions["getStaticSystemPrompts"];
104
- private readonly getServiceSystemPrompts: SdkSessionOptions["getServiceSystemPrompts"];
105
- private readonly getPluginSystemPrompts: SdkSessionOptions["getPluginSystemPrompts"];
108
+ private readonly getInstructionSystemBlocks: SdkSessionOptions["getInstructionSystemBlocks"];
109
+ private readonly getServiceSystemBlocks: SdkSessionOptions["getServiceSystemBlocks"];
110
+ private readonly getPluginSystemBlocks: SdkSessionOptions["getPluginSystemBlocks"];
106
111
  private readonly historyComposer: JsonlSessionHistoryComposer;
107
112
  private readonly coreSession: CoreSession;
108
113
  private sessionConfig: AgentSessionConfigSnapshot = {};
114
+ private createdAt = Date.now();
115
+ private timezone = resolveSystemTimezone();
109
116
  private initializePromise: Promise<this> | null = null;
110
117
  private servicePort: SessionPort | null = null;
111
118
 
@@ -115,9 +122,9 @@ export class SdkSession {
115
122
  this.projectRoot = String(options.projectRoot || "").trim();
116
123
  this.tools = options.tools;
117
124
  this.logger = options.logger;
118
- this.getStaticSystemPrompts = options.getStaticSystemPrompts;
119
- this.getServiceSystemPrompts = options.getServiceSystemPrompts;
120
- this.getPluginSystemPrompts = options.getPluginSystemPrompts;
125
+ this.getInstructionSystemBlocks = options.getInstructionSystemBlocks;
126
+ this.getServiceSystemBlocks = options.getServiceSystemBlocks;
127
+ this.getPluginSystemBlocks = options.getPluginSystemBlocks;
121
128
  if (!this.id) {
122
129
  throw new Error("SdkSession requires a non-empty sessionId");
123
130
  }
@@ -166,10 +173,13 @@ export class SdkSession {
166
173
  historyComposer,
167
174
  compactionComposer: new JsonlSessionCompactionComposer(),
168
175
  systemComposer: new SdkSessionSystemComposer({
176
+ agentId: this.agentId,
169
177
  projectRoot: this.projectRoot,
170
- getStaticSystemPrompts: this.getStaticSystemPrompts,
171
- getServiceSystemPrompts: this.getServiceSystemPrompts,
172
- getPluginSystemPrompts: this.getPluginSystemPrompts,
178
+ getSessionCreatedAt: () => this.createdAt,
179
+ getSessionTimezone: () => this.timezone,
180
+ getInstructionSystemBlocks: this.getInstructionSystemBlocks,
181
+ getServiceSystemBlocks: this.getServiceSystemBlocks,
182
+ getPluginSystemBlocks: this.getPluginSystemBlocks,
173
183
  }),
174
184
  getTools: () => this.tools,
175
185
  });
@@ -190,6 +200,12 @@ export class SdkSession {
190
200
  agentId: this.agentId,
191
201
  sessionId: this.id,
192
202
  });
203
+ const createdAt =
204
+ typeof metadata.createdAt === "number" ? metadata.createdAt : Date.now();
205
+ const timezone =
206
+ typeof metadata.timezone === "string" && metadata.timezone.trim()
207
+ ? metadata.timezone.trim()
208
+ : resolveSystemTimezone();
193
209
  await writeSdkSessionMetadata({
194
210
  projectRoot: this.projectRoot,
195
211
  agentId: this.agentId,
@@ -197,10 +213,12 @@ export class SdkSession {
197
213
  meta: {
198
214
  ...metadata,
199
215
  agentId: this.agentId,
200
- createdAt:
201
- typeof metadata.createdAt === "number" ? metadata.createdAt : Date.now(),
216
+ createdAt,
217
+ timezone,
202
218
  },
203
219
  });
220
+ this.createdAt = createdAt;
221
+ this.timezone = timezone;
204
222
  this.sessionConfig = {
205
223
  ...(metadata.sdkConfig?.modelLabel
206
224
  ? { modelLabel: metadata.sdkConfig.modelLabel }
@@ -279,20 +297,31 @@ export class SdkSession {
279
297
  *
280
298
  * 关键点(中文)
281
299
  * - 返回内容与实际 run 时使用的 SDK system composer 同源。
282
- * - 包含静态 system、显式注入 service system、显式注册 plugin system 与 runtime clock。
283
- * - 这里只返回文本数组,不把 system prompt 写入会话历史。
300
+ * - 包含 instruction/core、显式注入 service system、显式注册 plugin system 与 session 上下文。
301
+ * - 返回结构化快照,不把 system prompt 写入会话历史。
284
302
  */
285
- async system(): Promise<string[]> {
286
- const messages = await resolveSdkSessionSystemMessages({
303
+ async system(): Promise<AgentSessionSystemSnapshot> {
304
+ const blocks = await resolveSdkSessionSystemBlocks({
305
+ agentId: this.agentId,
287
306
  projectRoot: this.projectRoot,
288
307
  sessionId: this.id,
289
- getStaticSystemPrompts: this.getStaticSystemPrompts,
290
- getServiceSystemPrompts: this.getServiceSystemPrompts,
291
- getPluginSystemPrompts: this.getPluginSystemPrompts,
308
+ createdAt: this.createdAt,
309
+ timezone: this.timezone,
310
+ getInstructionSystemBlocks: this.getInstructionSystemBlocks,
311
+ getServiceSystemBlocks: this.getServiceSystemBlocks,
312
+ getPluginSystemBlocks: this.getPluginSystemBlocks,
292
313
  });
293
- return messages
294
- .map((message) => String(message.content || ""))
295
- .filter((content) => content.trim().length > 0);
314
+ return {
315
+ sessionId: this.id,
316
+ session: {
317
+ agentId: this.agentId,
318
+ sessionId: this.id,
319
+ projectRoot: this.projectRoot,
320
+ createdAt: new Date(this.createdAt).toISOString(),
321
+ timezone: this.timezone,
322
+ },
323
+ blocks,
324
+ };
296
325
  }
297
326
 
298
327
  /**
@@ -401,9 +430,9 @@ export class SdkSession {
401
430
  sessionId: `fork-${Date.now()}-${nanoid(8)}`,
402
431
  tools: this.tools,
403
432
  logger: this.logger,
404
- getStaticSystemPrompts: this.getStaticSystemPrompts,
405
- getServiceSystemPrompts: this.getServiceSystemPrompts,
406
- getPluginSystemPrompts: this.getPluginSystemPrompts,
433
+ getInstructionSystemBlocks: this.getInstructionSystemBlocks,
434
+ getServiceSystemBlocks: this.getServiceSystemBlocks,
435
+ getPluginSystemBlocks: this.getPluginSystemBlocks,
407
436
  });
408
437
  await forked.initialize();
409
438
  if (this.sessionConfig.model) {
@@ -36,6 +36,21 @@ function normalizeModelLabel(input: unknown): string | undefined {
36
36
  return label || undefined;
37
37
  }
38
38
 
39
+ /**
40
+ * 读取当前系统时区。
41
+ */
42
+ export function resolveSystemTimezone(): string {
43
+ const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
44
+ return typeof timezone === "string" && timezone.trim()
45
+ ? timezone.trim()
46
+ : "UTC";
47
+ }
48
+
49
+ function normalizeTimezone(input: unknown): string | undefined {
50
+ const timezone = typeof input === "string" ? input.trim() : "";
51
+ return timezone || undefined;
52
+ }
53
+
39
54
  /**
40
55
  * 从模型实例推导轻量可读标签。
41
56
  */
@@ -83,6 +98,7 @@ export async function readSdkSessionMetadata(
83
98
  typeof raw.createdAt === "number" && Number.isFinite(raw.createdAt)
84
99
  ? raw.createdAt
85
100
  : Date.now(),
101
+ timezone: normalizeTimezone(raw.timezone) || resolveSystemTimezone(),
86
102
  updatedAt:
87
103
  typeof raw.updatedAt === "number" && Number.isFinite(raw.updatedAt)
88
104
  ? raw.updatedAt
@@ -116,6 +132,7 @@ export async function readSdkSessionMetadata(
116
132
  sessionId: input.sessionId,
117
133
  agentId: input.agentId,
118
134
  createdAt: Date.now(),
135
+ timezone: resolveSystemTimezone(),
119
136
  updatedAt: 0,
120
137
  pinnedSkillIds: [],
121
138
  };
@@ -160,6 +177,7 @@ export async function patchSdkSessionModelLabel(
160
177
  agentId: input.agentId,
161
178
  createdAt:
162
179
  typeof current.createdAt === "number" ? current.createdAt : Date.now(),
180
+ timezone: normalizeTimezone(current.timezone) || resolveSystemTimezone(),
163
181
  updatedAt: Date.now(),
164
182
  ...(modelLabel
165
183
  ? {
@@ -27,6 +27,8 @@ export type SessionHistoryMetaV1 = {
27
27
  agentId?: string;
28
28
  /** 当前 session 首次创建时间戳(ms)。 */
29
29
  createdAt?: number;
30
+ /** 当前 session 初始化时解析到的系统时区。 */
31
+ timezone?: string;
30
32
  /** 最近一次更新元信息的时间戳(ms)。 */
31
33
  updatedAt: number;
32
34
  /** 固定注入到 Session 上下文的 skill id 列表。 */