@downcity/agent 1.1.267 → 1.1.270

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 (62) hide show
  1. package/bin/executor/core-engine/CoreEngineRunner.d.ts.map +1 -1
  2. package/bin/executor/core-engine/CoreEngineRunner.js +1 -2
  3. package/bin/executor/core-engine/CoreEngineRunner.js.map +1 -1
  4. package/bin/executor/services/ExecutorRecoveryPolicy.d.ts +0 -1
  5. package/bin/executor/services/ExecutorRecoveryPolicy.d.ts.map +1 -1
  6. package/bin/executor/services/ExecutorRecoveryPolicy.js +2 -17
  7. package/bin/executor/services/ExecutorRecoveryPolicy.js.map +1 -1
  8. package/bin/executor/types/SessionRecords.d.ts +5 -7
  9. package/bin/executor/types/SessionRecords.d.ts.map +1 -1
  10. package/bin/executor/types/SessionRecords.js +3 -4
  11. package/bin/executor/types/SessionRecords.js.map +1 -1
  12. package/bin/index.d.ts +1 -1
  13. package/bin/index.d.ts.map +1 -1
  14. package/bin/index.js.map +1 -1
  15. package/bin/session/SessionMessages.d.ts.map +1 -1
  16. package/bin/session/SessionMessages.js +14 -1
  17. package/bin/session/SessionMessages.js.map +1 -1
  18. package/bin/session/SessionSystem.js +6 -6
  19. package/bin/session/SessionSystem.js.map +1 -1
  20. package/bin/session/SessionTitle.d.ts.map +1 -1
  21. package/bin/session/SessionTitle.js +0 -6
  22. package/bin/session/SessionTitle.js.map +1 -1
  23. package/bin/session/SessionTurn.d.ts.map +1 -1
  24. package/bin/session/SessionTurn.js +0 -25
  25. package/bin/session/SessionTurn.js.map +1 -1
  26. package/bin/session/messages/SessionAssistantMessageWriter.d.ts +1 -1
  27. package/bin/session/messages/SessionAssistantMessageWriter.d.ts.map +1 -1
  28. package/bin/session/messages/SessionAssistantMessageWriter.js +153 -12
  29. package/bin/session/messages/SessionAssistantMessageWriter.js.map +1 -1
  30. package/bin/session/messages/SessionJsonValue.d.ts +3 -1
  31. package/bin/session/messages/SessionJsonValue.d.ts.map +1 -1
  32. package/bin/session/messages/SessionJsonValue.js +12 -0
  33. package/bin/session/messages/SessionJsonValue.js.map +1 -1
  34. package/bin/session/messages/SessionMessageCodec.d.ts.map +1 -1
  35. package/bin/session/messages/SessionMessageCodec.js +226 -19
  36. package/bin/session/messages/SessionMessageCodec.js.map +1 -1
  37. package/bin/types/sdk/AgentSessionTurn.d.ts +2 -1
  38. package/bin/types/sdk/AgentSessionTurn.d.ts.map +1 -1
  39. package/bin/types/session/SessionMessage.d.ts +87 -3
  40. package/bin/types/session/SessionMessage.d.ts.map +1 -1
  41. package/package.json +3 -3
  42. package/scripts/agent-session-maintenance.test.mjs +7 -1
  43. package/scripts/executor-failure-result.test.mjs +81 -0
  44. package/scripts/openai-responses-continuation.test.mjs +35 -5
  45. package/scripts/session-messages.test.mjs +287 -1
  46. package/scripts/session-shell-approval.test.mjs +3 -3
  47. package/scripts/session-system-blocks.test.mjs +14 -1
  48. package/scripts/session-turn-failure.test.mjs +101 -0
  49. package/src/executor/core-engine/CoreEngineRunner.ts +1 -5
  50. package/src/executor/services/ExecutorRecoveryPolicy.ts +2 -23
  51. package/src/executor/types/SessionRecords.ts +5 -7
  52. package/src/index.ts +11 -0
  53. package/src/session/SessionMessages.ts +14 -1
  54. package/src/session/SessionSystem.ts +6 -6
  55. package/src/session/SessionTitle.ts +0 -6
  56. package/src/session/SessionTurn.ts +0 -29
  57. package/src/session/messages/SessionAssistantMessageWriter.ts +170 -12
  58. package/src/session/messages/SessionJsonValue.ts +12 -1
  59. package/src/session/messages/SessionMessageCodec.ts +226 -18
  60. package/src/types/sdk/AgentSessionTurn.ts +2 -1
  61. package/src/types/session/SessionMessage.ts +96 -3
  62. package/tsconfig.tsbuildinfo +1 -1
@@ -9,6 +9,7 @@
9
9
 
10
10
  import type { UIMessage } from "ai";
11
11
  import {
12
+ to_session_json_object,
12
13
  to_session_json_value,
13
14
  to_session_provider_metadata,
14
15
  } from "@/session/messages/SessionJsonValue.js";
@@ -106,28 +107,36 @@ export function from_ui_user_parts(
106
107
  if (!part || typeof part !== "object") return [];
107
108
  const candidate = part as Record<string, unknown>;
108
109
  if (candidate.type === "text") {
110
+ const provider_metadata = to_session_provider_metadata(candidate.providerMetadata);
109
111
  return [{
110
112
  part_id: `user-text:${index + 1}`,
111
113
  type: "text" as const,
112
114
  text: String(candidate.text || ""),
113
115
  state: "done" as const,
116
+ ...(provider_metadata !== undefined ? { provider_metadata } : {}),
114
117
  }];
115
118
  }
116
119
  if (candidate.type === "file") {
120
+ const provider_metadata = to_session_provider_metadata(candidate.providerMetadata);
117
121
  return [{
118
122
  part_id: `user-file:${index + 1}`,
119
123
  type: "file" as const,
120
124
  url: String(candidate.url || ""),
121
125
  media_type: String(candidate.mediaType || "application/octet-stream"),
122
- ...(candidate.filename ? { filename: String(candidate.filename) } : {}),
126
+ ...(typeof candidate.filename === "string"
127
+ ? { filename: candidate.filename }
128
+ : {}),
129
+ ...(provider_metadata !== undefined ? { provider_metadata } : {}),
123
130
  }];
124
131
  }
125
132
  if (String(candidate.type || "").startsWith("data-")) {
133
+ const data_id = typeof candidate.id === "string" ? candidate.id : undefined;
126
134
  return [{
127
135
  part_id: `user-data:${index + 1}`,
128
136
  type: "data" as const,
129
137
  data_type: String(candidate.type),
130
138
  data: to_session_json_value(candidate.data),
139
+ ...(data_id !== undefined ? { data_id } : {}),
131
140
  }];
132
141
  }
133
142
  return [];
@@ -144,22 +153,66 @@ export function from_ui_assistant_parts(
144
153
  const candidate = part as Record<string, unknown>;
145
154
  const type = String(candidate.type || "");
146
155
  if (type === "text" || type === "reasoning") {
156
+ const provider_metadata = to_session_provider_metadata(candidate.providerMetadata);
147
157
  return [{
148
158
  part_id: `${type}:${index + 1}`,
149
159
  sequence: index + 1,
150
160
  type: type as "text" | "reasoning",
151
161
  text: String(candidate.text || ""),
152
- state: "done" as const,
162
+ state: candidate.state === "streaming" ? "streaming" as const : "done" as const,
163
+ ...(provider_metadata !== undefined ? { provider_metadata } : {}),
153
164
  }];
154
165
  }
155
166
  if (type === "file") {
167
+ const provider_metadata = to_session_provider_metadata(candidate.providerMetadata);
156
168
  return [{
157
169
  part_id: `file:${index + 1}`,
158
170
  sequence: index + 1,
159
171
  type: "file" as const,
160
172
  url: String(candidate.url || ""),
161
173
  media_type: String(candidate.mediaType || "application/octet-stream"),
162
- ...(candidate.filename ? { filename: String(candidate.filename) } : {}),
174
+ ...(typeof candidate.filename === "string"
175
+ ? { filename: candidate.filename }
176
+ : {}),
177
+ ...(provider_metadata !== undefined ? { provider_metadata } : {}),
178
+ }];
179
+ }
180
+ if (type === "source-url") {
181
+ const provider_metadata = to_session_provider_metadata(candidate.providerMetadata);
182
+ return [{
183
+ part_id: `source:${String(candidate.sourceId || index + 1)}`,
184
+ sequence: index + 1,
185
+ type: "source" as const,
186
+ source_type: "url" as const,
187
+ source_id: String(candidate.sourceId || `source-${index + 1}`),
188
+ url: String(candidate.url || ""),
189
+ ...(typeof candidate.title === "string" ? { title: candidate.title } : {}),
190
+ ...(provider_metadata !== undefined ? { provider_metadata } : {}),
191
+ }];
192
+ }
193
+ if (type === "source-document") {
194
+ const provider_metadata = to_session_provider_metadata(candidate.providerMetadata);
195
+ return [{
196
+ part_id: `source:${String(candidate.sourceId || index + 1)}`,
197
+ sequence: index + 1,
198
+ type: "source" as const,
199
+ source_type: "document" as const,
200
+ source_id: String(candidate.sourceId || `source-${index + 1}`),
201
+ media_type: String(candidate.mediaType || "application/octet-stream"),
202
+ title: candidate.title === undefined || candidate.title === null
203
+ ? "Document"
204
+ : String(candidate.title),
205
+ ...(typeof candidate.filename === "string"
206
+ ? { filename: candidate.filename }
207
+ : {}),
208
+ ...(provider_metadata !== undefined ? { provider_metadata } : {}),
209
+ }];
210
+ }
211
+ if (type === "step-start") {
212
+ return [{
213
+ part_id: `step:${index + 1}`,
214
+ sequence: index + 1,
215
+ type: "step-start" as const,
163
216
  }];
164
217
  }
165
218
  if (type === "dynamic-tool" || type.startsWith("tool-")) {
@@ -170,6 +223,8 @@ export function from_ui_assistant_parts(
170
223
  const result_provider_metadata = to_session_provider_metadata(
171
224
  candidate.resultProviderMetadata,
172
225
  );
226
+ const tool_metadata = to_session_json_object(candidate.toolMetadata);
227
+ const approval = to_session_json_object(candidate.approval);
173
228
  return [{
174
229
  part_id: String(candidate.toolCallId || `tool:${index + 1}`),
175
230
  sequence: index + 1,
@@ -197,7 +252,20 @@ export function from_ui_assistant_parts(
197
252
  ...(candidate.output !== undefined
198
253
  ? { output: to_session_json_value(candidate.output) }
199
254
  : {}),
200
- ...(candidate.errorText ? { error: String(candidate.errorText) } : {}),
255
+ ...(typeof candidate.errorText === "string"
256
+ ? { error: candidate.errorText }
257
+ : {}),
258
+ ...(candidate.rawInput !== undefined
259
+ ? { raw_input: to_session_json_value(candidate.rawInput) }
260
+ : {}),
261
+ ...(typeof candidate.title === "string" ? { title: candidate.title } : {}),
262
+ ...(tool_metadata !== undefined ? { tool_metadata } : {}),
263
+ ...(typeof candidate.dynamic === "boolean"
264
+ ? { dynamic: candidate.dynamic }
265
+ : { dynamic: type === "dynamic-tool" }),
266
+ ...(typeof candidate.preliminary === "boolean"
267
+ ? { preliminary: candidate.preliminary }
268
+ : {}),
201
269
  ...(call_provider_metadata !== undefined
202
270
  ? { call_provider_metadata }
203
271
  : {}),
@@ -207,6 +275,30 @@ export function from_ui_assistant_parts(
207
275
  ...(typeof candidate.providerExecuted === "boolean"
208
276
  ? { provider_executed: candidate.providerExecuted }
209
277
  : {}),
278
+ ...(approval?.id
279
+ ? {
280
+ approval: {
281
+ approval_id: String(approval.id),
282
+ ...(typeof approval.approved === "boolean"
283
+ ? { approved: approval.approved }
284
+ : {}),
285
+ ...(typeof approval.reason === "string"
286
+ ? { reason: approval.reason }
287
+ : {}),
288
+ },
289
+ }
290
+ : {}),
291
+ }];
292
+ }
293
+ if (type.startsWith("data-")) {
294
+ const data_id = typeof candidate.id === "string" ? candidate.id : undefined;
295
+ return [{
296
+ part_id: `data:${data_id ?? String(index + 1)}`,
297
+ sequence: index + 1,
298
+ type: "data" as const,
299
+ data_type: type,
300
+ data: to_session_json_value(candidate.data),
301
+ ...(data_id !== undefined ? { data_id } : {}),
210
302
  }];
211
303
  }
212
304
  return [];
@@ -227,19 +319,30 @@ export function extract_session_assistant_text(
227
319
  function to_ui_user_parts(parts: SessionUserMessagePart[]): UIMessage["parts"] {
228
320
  return parts.map((part) => {
229
321
  if (part.type === "text") {
230
- return { type: "text", text: part.text, state: part.state };
322
+ return {
323
+ type: "text",
324
+ text: part.text,
325
+ state: part.state,
326
+ ...(part.provider_metadata !== undefined
327
+ ? { providerMetadata: part.provider_metadata }
328
+ : {}),
329
+ };
231
330
  }
232
331
  if (part.type === "file") {
233
332
  return {
234
333
  type: "file",
235
334
  url: part.url,
236
335
  mediaType: part.media_type,
237
- ...(part.filename ? { filename: part.filename } : {}),
336
+ ...(part.filename !== undefined ? { filename: part.filename } : {}),
337
+ ...(part.provider_metadata !== undefined
338
+ ? { providerMetadata: part.provider_metadata }
339
+ : {}),
238
340
  };
239
341
  }
240
342
  return {
241
343
  type: part.data_type,
242
344
  data: part.data,
345
+ ...(part.data_id !== undefined ? { id: part.data_id } : {}),
243
346
  } as UIMessage["parts"][number];
244
347
  });
245
348
  }
@@ -249,26 +352,73 @@ function to_ui_assistant_parts(
249
352
  ): UIMessage["parts"] {
250
353
  return parts.map((part) => {
251
354
  if (part.type === "text" || part.type === "reasoning") {
252
- return { type: part.type, text: part.text, state: part.state };
355
+ return {
356
+ type: part.type,
357
+ text: part.text,
358
+ state: part.state,
359
+ ...(part.provider_metadata !== undefined
360
+ ? { providerMetadata: part.provider_metadata }
361
+ : {}),
362
+ };
253
363
  }
254
364
  if (part.type === "file") {
255
365
  return {
256
366
  type: "file",
257
367
  url: part.url,
258
368
  mediaType: part.media_type,
259
- ...(part.filename ? { filename: part.filename } : {}),
369
+ ...(part.filename !== undefined ? { filename: part.filename } : {}),
370
+ ...(part.provider_metadata !== undefined
371
+ ? { providerMetadata: part.provider_metadata }
372
+ : {}),
260
373
  };
261
374
  }
262
375
  if (part.type === "data") {
263
376
  return {
264
377
  type: part.data_type,
265
378
  data: part.data,
379
+ ...(part.data_id !== undefined ? { id: part.data_id } : {}),
266
380
  } as UIMessage["parts"][number];
267
381
  }
382
+ if (part.type === "source") {
383
+ if (part.source_type === "url") {
384
+ return {
385
+ type: "source-url",
386
+ sourceId: part.source_id,
387
+ url: part.url,
388
+ ...(part.title !== undefined ? { title: part.title } : {}),
389
+ ...(part.provider_metadata !== undefined
390
+ ? { providerMetadata: part.provider_metadata }
391
+ : {}),
392
+ };
393
+ }
394
+ return {
395
+ type: "source-document",
396
+ sourceId: part.source_id,
397
+ mediaType: part.media_type,
398
+ title: part.title,
399
+ ...(part.filename !== undefined ? { filename: part.filename } : {}),
400
+ ...(part.provider_metadata !== undefined
401
+ ? { providerMetadata: part.provider_metadata }
402
+ : {}),
403
+ };
404
+ }
405
+ if (part.type === "step-start") {
406
+ return { type: "step-start" };
407
+ }
268
408
  if (!("tool_call_id" in part)) {
269
409
  throw new Error(`Unsupported Assistant part: ${part.type}`);
270
410
  }
271
- const input = part.input ?? parse_json(part.input_text);
411
+ const has_input = part.input !== undefined || part.input_text !== undefined;
412
+ const input = part.input !== undefined
413
+ ? part.input
414
+ : part.input_text !== undefined
415
+ ? parse_json(part.input_text)
416
+ : part.raw_input !== undefined
417
+ ? undefined
418
+ : {};
419
+ const tool_identity_fields = part.dynamic === false
420
+ ? { type: `tool-${part.tool_name}` }
421
+ : { type: "dynamic-tool", toolName: part.tool_name };
272
422
  const call_provider_fields = {
273
423
  ...(part.call_provider_metadata !== undefined
274
424
  ? { callProviderMetadata: part.call_provider_metadata }
@@ -276,30 +426,74 @@ function to_ui_assistant_parts(
276
426
  ...(part.provider_executed !== undefined
277
427
  ? { providerExecuted: part.provider_executed }
278
428
  : {}),
429
+ ...(part.title !== undefined ? { title: part.title } : {}),
430
+ ...(part.tool_metadata !== undefined
431
+ ? { toolMetadata: part.tool_metadata }
432
+ : {}),
279
433
  };
280
434
  if (part.state === "completed") {
281
435
  return {
282
- type: "dynamic-tool",
283
- toolName: part.tool_name,
436
+ ...tool_identity_fields,
284
437
  toolCallId: part.tool_call_id,
285
438
  state: "output-available",
286
439
  input,
287
440
  output: part.output,
288
441
  ...call_provider_fields,
442
+ ...(part.preliminary !== undefined
443
+ ? { preliminary: part.preliminary }
444
+ : {}),
445
+ ...(part.approval?.approved === true
446
+ ? {
447
+ approval: {
448
+ id: part.approval.approval_id,
449
+ approved: true as const,
450
+ ...(part.approval.reason !== undefined
451
+ ? { reason: part.approval.reason }
452
+ : {}),
453
+ },
454
+ }
455
+ : {}),
289
456
  ...(part.result_provider_metadata !== undefined
290
457
  ? { resultProviderMetadata: part.result_provider_metadata }
291
458
  : {}),
292
459
  };
293
460
  }
294
461
  if (part.state === "failed") {
462
+ if (part.approval?.approved === false) {
463
+ return {
464
+ ...tool_identity_fields,
465
+ toolCallId: part.tool_call_id,
466
+ state: "output-denied",
467
+ input,
468
+ ...call_provider_fields,
469
+ approval: {
470
+ id: part.approval.approval_id,
471
+ approved: false,
472
+ ...(part.approval.reason !== undefined
473
+ ? { reason: part.approval.reason }
474
+ : {}),
475
+ },
476
+ };
477
+ }
295
478
  return {
296
- type: "dynamic-tool",
297
- toolName: part.tool_name,
479
+ ...tool_identity_fields,
298
480
  toolCallId: part.tool_call_id,
299
481
  state: "output-error",
300
482
  input,
483
+ ...(part.raw_input !== undefined ? { rawInput: part.raw_input } : {}),
301
484
  errorText: part.error || "Tool failed",
302
485
  ...call_provider_fields,
486
+ ...(part.approval?.approved === true
487
+ ? {
488
+ approval: {
489
+ id: part.approval.approval_id,
490
+ approved: true as const,
491
+ ...(part.approval.reason !== undefined
492
+ ? { reason: part.approval.reason }
493
+ : {}),
494
+ },
495
+ }
496
+ : {}),
303
497
  ...(part.result_provider_metadata !== undefined
304
498
  ? { resultProviderMetadata: part.result_provider_metadata }
305
499
  : {}),
@@ -307,8 +501,7 @@ function to_ui_assistant_parts(
307
501
  }
308
502
  if (part.state === "approval-required") {
309
503
  return {
310
- type: "dynamic-tool",
311
- toolName: part.tool_name,
504
+ ...tool_identity_fields,
312
505
  toolCallId: part.tool_call_id,
313
506
  state: "approval-requested",
314
507
  input,
@@ -316,12 +509,27 @@ function to_ui_assistant_parts(
316
509
  ...call_provider_fields,
317
510
  };
318
511
  }
512
+ if (part.state === "running" && part.approval?.approved !== undefined) {
513
+ return {
514
+ ...tool_identity_fields,
515
+ toolCallId: part.tool_call_id,
516
+ state: "approval-responded",
517
+ input,
518
+ ...call_provider_fields,
519
+ approval: {
520
+ id: part.approval.approval_id,
521
+ approved: part.approval.approved,
522
+ ...(part.approval.reason !== undefined
523
+ ? { reason: part.approval.reason }
524
+ : {}),
525
+ },
526
+ };
527
+ }
319
528
  return {
320
- type: "dynamic-tool",
321
- toolName: part.tool_name,
529
+ ...tool_identity_fields,
322
530
  toolCallId: part.tool_call_id,
323
531
  state: part.state === "input-streaming" ? "input-streaming" : "input-available",
324
- input,
532
+ ...(has_input ? { input } : {}),
325
533
  ...call_provider_fields,
326
534
  };
327
535
  }) as UIMessage["parts"];
@@ -32,7 +32,8 @@ export interface AgentSessionTurnResult {
32
32
  * 当前 turn 最终 assistant 消息。
33
33
  *
34
34
  * 说明(中文)
35
- * - `turn.finished` 返回的结果以这条消息作为最终事实源。
35
+ * - 仅在当前 turn 实际产生 assistant 内容时存在。
36
+ * - 失败状态由 `success` 与 `error` 表达,不会伪造成 assistant 正文。
36
37
  * - transport / runtime service 若需要读取最终结构化输出,应优先消费这里。
37
38
  */
38
39
  assistantMessage?: SessionMessageRecordV1;
@@ -54,6 +54,8 @@ export interface SessionUserTextPart {
54
54
  text: string;
55
55
  /** User 文本已经完整,不参与流式更新。 */
56
56
  state: "done";
57
+ /** AI SDK User text part 携带的可序列化 Provider metadata。 */
58
+ provider_metadata?: ProviderMetadata;
57
59
  }
58
60
 
59
61
  /** User 文件 part。 */
@@ -68,6 +70,8 @@ export interface SessionUserFilePart {
68
70
  media_type: string;
69
71
  /** 可选原始文件名。 */
70
72
  filename?: string;
73
+ /** AI SDK User file part 携带的可序列化 Provider metadata。 */
74
+ provider_metadata?: ProviderMetadata;
71
75
  }
72
76
 
73
77
  /** User 结构化数据 part。 */
@@ -80,6 +84,8 @@ export interface SessionUserDataPart {
80
84
  data_type: `data-${string}` | string;
81
85
  /** 可 JSON 序列化的数据。 */
82
86
  data: JsonValue;
87
+ /** AI SDK data part 的可选稳定标识。 */
88
+ data_id?: string;
83
89
  }
84
90
 
85
91
  /** User Message part。 */
@@ -110,6 +116,20 @@ export interface SessionAssistantTextPart {
110
116
  text: string;
111
117
  /** 文本 part 是否已经结束。 */
112
118
  state: "streaming" | "done";
119
+ /** AI SDK text / reasoning part 携带的可序列化 Provider metadata。 */
120
+ provider_metadata?: ProviderMetadata;
121
+ }
122
+
123
+ /** Tool approval 在 UIMessage 中的完整语义快照。 */
124
+ export interface SessionToolApprovalSnapshot {
125
+ /** AI SDK approval request 的稳定标识。 */
126
+ approval_id: string;
127
+ /** 已经作出决定时记录是否批准;等待决定时省略。 */
128
+ approved?: boolean;
129
+ /** Provider 或用户给出的可选决定原因。 */
130
+ reason?: string;
131
+ /** Downcity 本地审批运行时的完整请求;仅本地工具审批存在。 */
132
+ request?: SessionApproval;
113
133
  }
114
134
 
115
135
  /** Assistant 工具 part。 */
@@ -134,14 +154,24 @@ export interface SessionAssistantToolPart {
134
154
  output?: JsonValue;
135
155
  /** 工具失败信息。 */
136
156
  error?: string;
157
+ /** AI SDK 为工具调用提供的可选展示标题。 */
158
+ title?: string;
159
+ /** AI SDK 工具调用携带的可序列化工具元数据。 */
160
+ tool_metadata?: JsonObject;
161
+ /** 当前工具是否由运行时动态定义。 */
162
+ dynamic?: boolean;
163
+ /** Tool output-error 无法解析 input 时保留的原始输入。 */
164
+ raw_input?: JsonValue;
165
+ /** 当前工具结果是否只是后续会被替换的临时结果。 */
166
+ preliminary?: boolean;
137
167
  /** 工具调用阶段由 AI SDK Provider 返回的可序列化 metadata。 */
138
168
  call_provider_metadata?: ProviderMetadata;
139
169
  /** 工具结果阶段由 AI SDK Provider 返回的可序列化 metadata。 */
140
170
  result_provider_metadata?: ProviderMetadata;
141
171
  /** 当前工具是否由模型 Provider 直接执行。 */
142
172
  provider_executed?: boolean;
143
- /** 当前 Tool 等待或已经处理过的完整审批快照。 */
144
- approval?: SessionApproval;
173
+ /** 当前 Tool 等待或已经处理过的完整审批语义。 */
174
+ approval?: SessionToolApprovalSnapshot;
145
175
  }
146
176
 
147
177
  /** Assistant 文件 part。 */
@@ -158,6 +188,8 @@ export interface SessionAssistantFilePart {
158
188
  url: string;
159
189
  /** 可选原始文件名。 */
160
190
  filename?: string;
191
+ /** AI SDK Assistant file part 携带的可序列化 Provider metadata。 */
192
+ provider_metadata?: ProviderMetadata;
161
193
  }
162
194
 
163
195
  /** Assistant 结构化数据 part。 */
@@ -172,6 +204,65 @@ export interface SessionAssistantDataPart {
172
204
  data_type: `data-${string}` | string;
173
205
  /** 可 JSON 序列化的数据。 */
174
206
  data: JsonValue;
207
+ /** AI SDK data part 的可选稳定标识。 */
208
+ data_id?: string;
209
+ }
210
+
211
+ /** Assistant URL source part。 */
212
+ export interface SessionAssistantUrlSourcePart {
213
+ /** Assistant Message 内稳定的 part 标识。 */
214
+ part_id: string;
215
+ /** Assistant Part 在当前 Message 中的不可变线性顺序,从 1 开始。 */
216
+ sequence: number;
217
+ /** part 类型固定为 source。 */
218
+ type: "source";
219
+ /** source 子类型固定为 URL。 */
220
+ source_type: "url";
221
+ /** AI SDK source 的稳定标识。 */
222
+ source_id: string;
223
+ /** source 指向的网页地址。 */
224
+ url: string;
225
+ /** source 的可选展示标题。 */
226
+ title?: string;
227
+ /** AI SDK source part 携带的可序列化 Provider metadata。 */
228
+ provider_metadata?: ProviderMetadata;
229
+ }
230
+
231
+ /** Assistant document source part。 */
232
+ export interface SessionAssistantDocumentSourcePart {
233
+ /** Assistant Message 内稳定的 part 标识。 */
234
+ part_id: string;
235
+ /** Assistant Part 在当前 Message 中的不可变线性顺序,从 1 开始。 */
236
+ sequence: number;
237
+ /** part 类型固定为 source。 */
238
+ type: "source";
239
+ /** source 子类型固定为 document。 */
240
+ source_type: "document";
241
+ /** AI SDK source 的稳定标识。 */
242
+ source_id: string;
243
+ /** document source 的 IANA 媒体类型。 */
244
+ media_type: string;
245
+ /** document source 的展示标题。 */
246
+ title: string;
247
+ /** document source 的可选文件名。 */
248
+ filename?: string;
249
+ /** AI SDK source part 携带的可序列化 Provider metadata。 */
250
+ provider_metadata?: ProviderMetadata;
251
+ }
252
+
253
+ /** Assistant source part。 */
254
+ export type SessionAssistantSourcePart =
255
+ | SessionAssistantUrlSourcePart
256
+ | SessionAssistantDocumentSourcePart;
257
+
258
+ /** Assistant step 边界 part。 */
259
+ export interface SessionAssistantStepPart {
260
+ /** Assistant Message 内稳定的 part 标识。 */
261
+ part_id: string;
262
+ /** Assistant Part 在当前 Message 中的不可变线性顺序,从 1 开始。 */
263
+ sequence: number;
264
+ /** part 类型固定为 step-start。 */
265
+ type: "step-start";
175
266
  }
176
267
 
177
268
  /** Assistant Message part。 */
@@ -179,7 +270,9 @@ export type SessionAssistantMessagePart =
179
270
  | SessionAssistantTextPart
180
271
  | SessionAssistantToolPart
181
272
  | SessionAssistantFilePart
182
- | SessionAssistantDataPart;
273
+ | SessionAssistantDataPart
274
+ | SessionAssistantSourcePart
275
+ | SessionAssistantStepPart;
183
276
 
184
277
  /** Assistant 顶层 Message。 */
185
278
  export interface SessionAssistantMessage extends SessionMessageBase {