@linnlabs/linnkit 0.8.0 → 0.10.0

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 (83) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +1 -1
  3. package/README.zh-CN.md +1 -1
  4. package/bin/linnkit.cjs +7 -0
  5. package/dist/{agentSpec-EkmviZjy.d.cts → agentSpec-Du4Iye0q.d.cts} +16 -1
  6. package/dist/{agentSpec-EkmviZjy.d.ts → agentSpec-Du4Iye0q.d.ts} +16 -1
  7. package/dist/cli.cjs +234 -91
  8. package/dist/cli.cjs.map +1 -1
  9. package/dist/cli.js +234 -91
  10. package/dist/cli.js.map +1 -1
  11. package/dist/context-manager.cjs +230 -32
  12. package/dist/context-manager.cjs.map +1 -1
  13. package/dist/context-manager.d.cts +52 -15
  14. package/dist/context-manager.d.ts +52 -15
  15. package/dist/context-manager.js +230 -33
  16. package/dist/context-manager.js.map +1 -1
  17. package/dist/{context-trace-HE2qY5Q-.d.cts → context-trace-BHKDS-eq.d.cts} +2 -2
  18. package/dist/{context-trace-DRi5M4lX.d.ts → context-trace-CHbqHmyE.d.ts} +2 -2
  19. package/dist/contracts.cjs +3 -1
  20. package/dist/contracts.cjs.map +1 -1
  21. package/dist/contracts.d.cts +3 -3
  22. package/dist/contracts.d.ts +3 -3
  23. package/dist/contracts.js +3 -1
  24. package/dist/contracts.js.map +1 -1
  25. package/dist/{defaultGraphExecutor-BBswR8wn.d.ts → defaultGraphExecutor-B29_qTHy.d.ts} +16 -15
  26. package/dist/{defaultGraphExecutor-BIjJj7WF.d.cts → defaultGraphExecutor-C2E59v_R.d.cts} +16 -15
  27. package/dist/{index-Cm-JbzTH.d.cts → index-BAaUP9yU.d.cts} +38 -15
  28. package/dist/{index-DRBWi1fy.d.ts → index-BaVpVNi2.d.ts} +38 -15
  29. package/dist/{index-DO4dQgf2.d.cts → index-BnYCS8Zg.d.cts} +2 -2
  30. package/dist/{index-CJeWHopy.d.ts → index-C0DAjsdX.d.ts} +2 -2
  31. package/dist/{index-Dl5PLgAv.d.cts → index-CKQzzZ5Y.d.cts} +2 -2
  32. package/dist/{index-CHqwkvGp.d.ts → index-D0mKxTR5.d.ts} +2 -2
  33. package/dist/index.cjs +327 -110
  34. package/dist/index.cjs.map +1 -1
  35. package/dist/index.d.cts +10 -10
  36. package/dist/index.d.ts +10 -10
  37. package/dist/index.js +327 -110
  38. package/dist/index.js.map +1 -1
  39. package/dist/{ports-DnLuKfpE.d.ts → ports-DpPTFhSd.d.ts} +2 -2
  40. package/dist/{ports-DaatKJXp.d.cts → ports-s-tSp3sB.d.cts} +2 -2
  41. package/dist/quickstart.cjs +232 -88
  42. package/dist/quickstart.cjs.map +1 -1
  43. package/dist/quickstart.d.cts +7 -7
  44. package/dist/quickstart.d.ts +7 -7
  45. package/dist/quickstart.js +232 -88
  46. package/dist/quickstart.js.map +1 -1
  47. package/dist/{runAgent-CPj_9e58.d.ts → runAgent-C6F-399C.d.ts} +5 -5
  48. package/dist/{runAgent-HYKlXbVr.d.cts → runAgent-ilEj66Ik.d.cts} +5 -5
  49. package/dist/{runHandle-D3gPsD7B.d.cts → runHandle-BNOqS-Bl.d.cts} +3 -3
  50. package/dist/{runHandle-CyXvzgzk.d.ts → runHandle-BdLXOFqF.d.ts} +3 -3
  51. package/dist/runtime-kernel/events.cjs +1 -0
  52. package/dist/runtime-kernel/events.cjs.map +1 -1
  53. package/dist/runtime-kernel/events.d.cts +4 -4
  54. package/dist/runtime-kernel/events.d.ts +4 -4
  55. package/dist/runtime-kernel/events.js +1 -0
  56. package/dist/runtime-kernel/events.js.map +1 -1
  57. package/dist/runtime-kernel.cjs +318 -103
  58. package/dist/runtime-kernel.cjs.map +1 -1
  59. package/dist/runtime-kernel.d.cts +8 -8
  60. package/dist/runtime-kernel.d.ts +8 -8
  61. package/dist/runtime-kernel.js +315 -104
  62. package/dist/runtime-kernel.js.map +1 -1
  63. package/dist/testkit.cjs +331 -116
  64. package/dist/testkit.cjs.map +1 -1
  65. package/dist/testkit.d.cts +8 -8
  66. package/dist/testkit.d.ts +8 -8
  67. package/dist/testkit.js +331 -116
  68. package/dist/testkit.js.map +1 -1
  69. package/dist/{todo-B1PmDlp3.d.cts → todo-Ca8llpRQ.d.cts} +1 -1
  70. package/dist/{todo-B1PmDlp3.d.ts → todo-Ca8llpRQ.d.ts} +1 -1
  71. package/dist/{toolContracts-CLkQmhTG.d.cts → toolContracts-Bm3EZ1UM.d.cts} +13 -2
  72. package/dist/{toolContracts-Blll0241.d.ts → toolContracts-f8lzZBNa.d.ts} +13 -2
  73. package/docs/integration/README.md +1 -1
  74. package/docs/integration/agent-registration-guide.md +1 -1
  75. package/docs/integration/child-runs.md +4 -1
  76. package/docs/integration/context-engineering.md +30 -15
  77. package/docs/integration/context-fences.md +32 -3
  78. package/docs/integration/llm-provider.md +1 -1
  79. package/docs/integration/persistence.md +1 -0
  80. package/docs/integration/run-supervisor.md +3 -0
  81. package/docs/integration/tool-development-guide.md +7 -5
  82. package/docs/integration/tool-history.md +43 -17
  83. package/package.json +5 -4
package/dist/testkit.js CHANGED
@@ -105,14 +105,18 @@ __export(runtime_kernel_exports, {
105
105
  UserNode: () => UserNode,
106
106
  WaitUserNode: () => WaitUserNode,
107
107
  agentHasToolTrigger: () => agentHasToolTrigger,
108
+ appendStreamingProviderReasoningDetails: () => appendStreamingProviderReasoningDetails,
108
109
  applySystemReminders: () => applySystemReminders,
109
110
  audit: () => audit_exports,
110
111
  budgetWarningTrigger: () => budgetWarningTrigger,
111
112
  childRunTrace: () => child_run_trace_exports,
112
113
  childRuns: () => child_runs_exports,
114
+ compactProviderReasoningDetails: () => compactProviderReasoningDetails,
115
+ compactReasoningDetailsInValue: () => compactReasoningDetailsInValue,
113
116
  computeToolIdempotencyKey: () => computeToolIdempotencyKey,
114
117
  consoleAudit: () => consoleAudit,
115
118
  contextBudgetWarningTemplate: () => contextBudgetWarningTemplate,
119
+ copyToolContextRuntimeCapability: () => copyToolContextRuntimeCapability,
116
120
  countToolCallsInCurrentRequest: () => countToolCallsInCurrentRequest,
117
121
  createCompositeAudit: () => createCompositeAudit,
118
122
  createConsoleAudit: () => createConsoleAudit,
@@ -417,6 +421,7 @@ var AgentSpecBudgetPolicy = z.object({
417
421
  });
418
422
  var AgentSpecToolHistoryPolicy = z.object({
419
423
  strategy: z.enum(["per-pair", "per-run", "none"]).optional(),
424
+ retentionMode: z.enum(["drop", "compress"]).optional(),
420
425
  keepLatestToolPairs: z.number().int().nonnegative().optional(),
421
426
  keepLatestRuns: z.number().int().nonnegative().optional(),
422
427
  maxInteractionGroups: z.number().int().nonnegative().optional(),
@@ -1173,6 +1178,17 @@ var logger = new Logger("GraphExecutor");
1173
1178
  function asLocalRecord(local) {
1174
1179
  return local && typeof local === "object" ? { ...local } : {};
1175
1180
  }
1181
+ function readNonEmptyString(value) {
1182
+ return typeof value === "string" && value.trim().length > 0 ? value : void 0;
1183
+ }
1184
+ function readRuntimeConversationId(state) {
1185
+ const local = state?.local && typeof state.local === "object" ? state.local : void 0;
1186
+ return readNonEmptyString(local?.conversationId);
1187
+ }
1188
+ function readRuntimeTurnId(state) {
1189
+ const local = state?.local && typeof state.local === "object" ? state.local : void 0;
1190
+ return readNonEmptyString(local?.turnId);
1191
+ }
1176
1192
  var GraphExecutor = class {
1177
1193
  constructor(checkpointer, config = {}) {
1178
1194
  this.checkpointer = checkpointer;
@@ -1190,8 +1206,8 @@ var GraphExecutor = class {
1190
1206
  registerNode(node) {
1191
1207
  this.nodes.set(node.id, node);
1192
1208
  }
1193
- async peekCheckpoint(conversationId) {
1194
- return await this.checkpointer.load(conversationId);
1209
+ async peekCheckpoint(checkpointKey) {
1210
+ return await this.checkpointer.load(checkpointKey);
1195
1211
  }
1196
1212
  sanitize(state) {
1197
1213
  const local = asLocalRecord(state.local);
@@ -1203,8 +1219,8 @@ var GraphExecutor = class {
1203
1219
  local
1204
1220
  };
1205
1221
  }
1206
- async prime(conversationId, local, nodeId = "user") {
1207
- this.ephemeralLocals.set(conversationId, { ...local || {} });
1222
+ async prime(checkpointKey, local, nodeId = "user") {
1223
+ this.ephemeralLocals.set(checkpointKey, { ...local || {} });
1208
1224
  const localSansMemory = { ...local || {} };
1209
1225
  if ("memory" in localSansMemory) delete localSansMemory.memory;
1210
1226
  const state = {
@@ -1212,10 +1228,10 @@ var GraphExecutor = class {
1212
1228
  schemaVersion: ENGINE_STATE_SCHEMA_VERSION,
1213
1229
  local: localSansMemory
1214
1230
  };
1215
- await this.checkpointer.save(conversationId, state);
1231
+ await this.checkpointer.save(checkpointKey, state);
1216
1232
  }
1217
- async setNode(conversationId, nodeId, localPatch) {
1218
- const current = await this.checkpointer.load(conversationId) || {
1233
+ async setNode(checkpointKey, nodeId, localPatch) {
1234
+ const current = await this.checkpointer.load(checkpointKey) || {
1219
1235
  schemaVersion: ENGINE_STATE_SCHEMA_VERSION,
1220
1236
  local: {}
1221
1237
  };
@@ -1226,19 +1242,46 @@ var GraphExecutor = class {
1226
1242
  schemaVersion: current.schemaVersion ?? ENGINE_STATE_SCHEMA_VERSION,
1227
1243
  local: mergedLocal
1228
1244
  };
1229
- await this.checkpointer.save(conversationId, next);
1245
+ await this.checkpointer.save(checkpointKey, next);
1230
1246
  }
1231
- async runUntilYield(conversationId) {
1247
+ async runUntilYield(checkpointKey) {
1232
1248
  const runId = `run_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
1233
1249
  let lifecyclePhase = "completed";
1250
+ let initialState = null;
1251
+ try {
1252
+ initialState = await this.loadInitialState(checkpointKey);
1253
+ } catch (err) {
1254
+ lifecyclePhase = "failed";
1255
+ this.telemetryPort.emit({
1256
+ kind: "run_lifecycle",
1257
+ runId,
1258
+ phase: "spawned",
1259
+ scope: {}
1260
+ });
1261
+ this.telemetryPort.emit({
1262
+ kind: "run_lifecycle",
1263
+ runId,
1264
+ phase: lifecyclePhase,
1265
+ scope: {}
1266
+ });
1267
+ throw err;
1268
+ }
1269
+ let lifecycleConversationId = readRuntimeConversationId(initialState);
1270
+ let lifecycleTurnId = readRuntimeTurnId(initialState);
1234
1271
  this.telemetryPort.emit({
1235
1272
  kind: "run_lifecycle",
1236
1273
  runId,
1237
1274
  phase: "spawned",
1238
- scope: { conversationId: conversationId || void 0 }
1275
+ scope: {
1276
+ conversationId: lifecycleConversationId,
1277
+ turnId: lifecycleTurnId
1278
+ }
1239
1279
  });
1240
1280
  try {
1241
- return await this.runUntilYieldInternal(conversationId);
1281
+ const result = await this.runUntilYieldInternal(checkpointKey, initialState);
1282
+ lifecycleConversationId = readRuntimeConversationId(result.checkpoint);
1283
+ lifecycleTurnId = readRuntimeTurnId(result.checkpoint);
1284
+ return result;
1242
1285
  } catch (err) {
1243
1286
  lifecyclePhase = err?.name === "AbortError" ? "cancelled" : "failed";
1244
1287
  throw err;
@@ -1247,17 +1290,23 @@ var GraphExecutor = class {
1247
1290
  kind: "run_lifecycle",
1248
1291
  runId,
1249
1292
  phase: lifecyclePhase,
1250
- scope: { conversationId: conversationId || void 0 }
1293
+ scope: {
1294
+ conversationId: lifecycleConversationId,
1295
+ turnId: lifecycleTurnId
1296
+ }
1251
1297
  });
1252
1298
  }
1253
1299
  }
1254
- async runUntilYieldInternal(conversationId) {
1255
- let state = await this.checkpointer.load(conversationId) || {
1300
+ async loadInitialState(checkpointKey) {
1301
+ return await this.checkpointer.load(checkpointKey) || {
1256
1302
  nodeId: "user",
1257
1303
  schemaVersion: ENGINE_STATE_SCHEMA_VERSION,
1258
1304
  local: {}
1259
1305
  };
1260
- const ephemeral = this.ephemeralLocals.get(conversationId) || {};
1306
+ }
1307
+ async runUntilYieldInternal(checkpointKey, initialState) {
1308
+ let state = initialState;
1309
+ const ephemeral = this.ephemeralLocals.get(checkpointKey) || {};
1261
1310
  state = {
1262
1311
  ...state,
1263
1312
  schemaVersion: state.schemaVersion ?? ENGINE_STATE_SCHEMA_VERSION,
@@ -1286,7 +1335,7 @@ var GraphExecutor = class {
1286
1335
  const signalRaw = state.local?.signal;
1287
1336
  if (isAbortSignal2(signalRaw) && signalRaw.aborted) {
1288
1337
  logger.warn("[GraphExecutor] \u6536\u5230 AbortSignal\uFF0C\u7ACB\u5373\u505C\u6B62\u63A8\u7406\u5FAA\u73AF");
1289
- this.ephemeralLocals.delete(conversationId);
1338
+ this.ephemeralLocals.delete(checkpointKey);
1290
1339
  throwAbortError();
1291
1340
  }
1292
1341
  const isLastStep = cycleStepCount >= this.config.maxSteps;
@@ -1334,8 +1383,8 @@ var GraphExecutor = class {
1334
1383
  checkpointCount
1335
1384
  });
1336
1385
  const cp2 = this.sanitize(state);
1337
- await this.checkpointer.save(conversationId, cp2);
1338
- this.ephemeralLocals.delete(conversationId);
1386
+ await this.checkpointer.save(checkpointKey, cp2);
1387
+ this.ephemeralLocals.delete(checkpointKey);
1339
1388
  return { events: allEvents, checkpoint: cp2, stepCount };
1340
1389
  }
1341
1390
  logger.info("[GraphExecutor] \u8282\u70B9\u5207\u6362", {
@@ -1346,18 +1395,18 @@ var GraphExecutor = class {
1346
1395
  });
1347
1396
  const nodeRunStartedAt = Date.now();
1348
1397
  const nodeIdForTelemetry = state.nodeId;
1398
+ const conversationIdForTelemetry = readRuntimeConversationId(state);
1349
1399
  let result;
1350
1400
  try {
1351
1401
  result = await node.run(state);
1352
1402
  } finally {
1353
- const turnIdForTelemetry = typeof state.local?.turnId === "string" ? state.local.turnId : void 0;
1354
1403
  this.telemetryPort.emit({
1355
1404
  kind: "graph_node",
1356
1405
  nodeId: nodeIdForTelemetry,
1357
1406
  durationMs: Date.now() - nodeRunStartedAt,
1358
1407
  scope: {
1359
- conversationId: conversationId || void 0,
1360
- turnId: turnIdForTelemetry
1408
+ conversationId: conversationIdForTelemetry,
1409
+ turnId: readRuntimeTurnId(state)
1361
1410
  }
1362
1411
  });
1363
1412
  }
@@ -1396,7 +1445,7 @@ var GraphExecutor = class {
1396
1445
  });
1397
1446
  state = { ...state, nodeId: nextNodeId };
1398
1447
  const cp2 = this.sanitize(state);
1399
- await this.checkpointer.save(conversationId, cp2);
1448
+ await this.checkpointer.save(checkpointKey, cp2);
1400
1449
  continue;
1401
1450
  }
1402
1451
  if (result.kind === "yield") {
@@ -1407,7 +1456,7 @@ var GraphExecutor = class {
1407
1456
  checkpointCount
1408
1457
  });
1409
1458
  const cp2 = this.sanitize(state);
1410
- await this.checkpointer.save(conversationId, cp2);
1459
+ await this.checkpointer.save(checkpointKey, cp2);
1411
1460
  return { events: allEvents, checkpoint: cp2, stepCount };
1412
1461
  }
1413
1462
  if (result.kind === "pause") {
@@ -1418,7 +1467,7 @@ var GraphExecutor = class {
1418
1467
  checkpointCount
1419
1468
  });
1420
1469
  const cp2 = this.sanitize(state);
1421
- await this.checkpointer.save(conversationId, cp2);
1470
+ await this.checkpointer.save(checkpointKey, cp2);
1422
1471
  return { events: allEvents, checkpoint: cp2, stepCount };
1423
1472
  }
1424
1473
  }
@@ -1429,8 +1478,8 @@ var GraphExecutor = class {
1429
1478
  checkpointCount
1430
1479
  });
1431
1480
  const cp = this.sanitize(state);
1432
- await this.checkpointer.save(conversationId, cp);
1433
- this.ephemeralLocals.delete(conversationId);
1481
+ await this.checkpointer.save(checkpointKey, cp);
1482
+ this.ephemeralLocals.delete(checkpointKey);
1434
1483
  return { events: allEvents, checkpoint: cp, stepCount };
1435
1484
  }
1436
1485
  };
@@ -1627,15 +1676,15 @@ function splitConcatenatedJsonObjects(input) {
1627
1676
  }
1628
1677
 
1629
1678
  // src/runtime-kernel/graph-engine/tick-pipeline/helpers.ts
1630
- function readNonEmptyString(value) {
1679
+ function readNonEmptyString2(value) {
1631
1680
  if (typeof value !== "string") return void 0;
1632
1681
  const trimmed = value.trim();
1633
1682
  return trimmed.length > 0 ? trimmed : void 0;
1634
1683
  }
1635
1684
  function resolveConversationIdForRuntimeEvents(toolContext) {
1636
- const fromCamel = readNonEmptyString(toolContext?.conversationId);
1685
+ const fromCamel = readNonEmptyString2(toolContext?.conversationId);
1637
1686
  if (fromCamel) return fromCamel;
1638
- const fromSnake = toolContext ? readNonEmptyString(toolContext["conversation_id"]) : void 0;
1687
+ const fromSnake = toolContext ? readNonEmptyString2(toolContext["conversation_id"]) : void 0;
1639
1688
  if (fromSnake) return fromSnake;
1640
1689
  return generateMessageId();
1641
1690
  }
@@ -1994,7 +2043,7 @@ var runModelLockMiddleware = async (ctx, stage, next) => {
1994
2043
  if (stage.id !== "execute_llm") {
1995
2044
  return;
1996
2045
  }
1997
- const normalized = readNonEmptyString(ctx.cloudQuotaFallbackAppliedModelId);
2046
+ const normalized = readNonEmptyString2(ctx.cloudQuotaFallbackAppliedModelId);
1998
2047
  if (!normalized) {
1999
2048
  return;
2000
2049
  }
@@ -2595,7 +2644,7 @@ function createExecuteLlmStage(dependencies) {
2595
2644
  streamEventHandler,
2596
2645
  ctx.signal,
2597
2646
  (fallbackModelId) => {
2598
- ctx.cloudQuotaFallbackAppliedModelId = readNonEmptyString(fallbackModelId);
2647
+ ctx.cloudQuotaFallbackAppliedModelId = readNonEmptyString2(fallbackModelId);
2599
2648
  },
2600
2649
  (info) => {
2601
2650
  ctx.modelFallbackAudit = info;
@@ -2639,7 +2688,7 @@ function createPrepareCallStage(dependencies) {
2639
2688
  return {
2640
2689
  id: "prepare_call",
2641
2690
  async run(ctx) {
2642
- const lockedRunModelId = readNonEmptyString(ctx.executorLocal?.runLockedModelId);
2691
+ const lockedRunModelId = readNonEmptyString2(ctx.executorLocal?.runLockedModelId);
2643
2692
  const requestedModelId = lockedRunModelId ?? ctx.request.model_id;
2644
2693
  ctx.modelId = dependencies.modelResolver.resolveModelId(requestedModelId);
2645
2694
  await emitAuditEnvelope(ctx.audit, {
@@ -2711,7 +2760,7 @@ var GraphAgentExecutor = class {
2711
2760
  this.llmCaller = dependencies.llmCaller;
2712
2761
  this.toolRuntime = dependencies.toolRuntime;
2713
2762
  this.contextBuilder = dependencies.contextBuilder;
2714
- this.cloudQuotaFallbackModelId = readNonEmptyString(dependencies.cloudQuotaFallbackModelId);
2763
+ this.cloudQuotaFallbackModelId = readNonEmptyString2(dependencies.cloudQuotaFallbackModelId);
2715
2764
  this.modelCatalog = dependencies.modelCatalog ?? createEmptyModelCatalog();
2716
2765
  this.modelResolver = dependencies.modelResolver ?? new ModelResolver({
2717
2766
  modelCatalog: this.modelCatalog
@@ -2759,7 +2808,7 @@ var GraphAgentExecutor = class {
2759
2808
  llmMessages: [],
2760
2809
  mode: input.request.mode === "chat" ? "chat" : "agent",
2761
2810
  conversationId: resolveConversationIdForRuntimeEvents(input.toolContext),
2762
- turnId: readNonEmptyString(input.toolContext?.turnId) ?? `turn_${Date.now()}`,
2811
+ turnId: readNonEmptyString2(input.toolContext?.turnId) ?? `turn_${Date.now()}`,
2763
2812
  telemetry: this.telemetryPort,
2764
2813
  audit: this.auditPort
2765
2814
  };
@@ -2809,18 +2858,18 @@ function isSummarizationCallbacks(value) {
2809
2858
  function isGraphSseSink(value) {
2810
2859
  return typeof value === "function";
2811
2860
  }
2812
- function readNonEmptyString2(value) {
2861
+ function readNonEmptyString3(value) {
2813
2862
  if (typeof value !== "string") return void 0;
2814
2863
  const trimmed = value.trim();
2815
2864
  return trimmed.length > 0 ? trimmed : void 0;
2816
2865
  }
2817
2866
  function readGraphAgentLocal(local) {
2818
2867
  const source = local ?? {};
2819
- const answerId = readNonEmptyString2(source.answerId);
2868
+ const answerId = readNonEmptyString3(source.answerId);
2820
2869
  const chunkSeq = Number.isInteger(source.chunkSeq) ? Number(source.chunkSeq) : 0;
2821
2870
  return {
2822
- conversationId: readNonEmptyString2(source.conversationId) ?? "",
2823
- turnId: readNonEmptyString2(source.turnId),
2871
+ conversationId: readNonEmptyString3(source.conversationId) ?? "",
2872
+ turnId: readNonEmptyString3(source.turnId),
2824
2873
  request: isAgentInvocationRequest(source.request) ? source.request : void 0,
2825
2874
  toolContext: isToolExecutionContext(source.toolContext) ? source.toolContext : void 0,
2826
2875
  history: isRuntimeEventArray(source.history) ? source.history : [],
@@ -3585,7 +3634,7 @@ var LlmNode = class {
3585
3634
  function isRecord8(value) {
3586
3635
  return typeof value === "object" && value !== null && !Array.isArray(value);
3587
3636
  }
3588
- function readNonEmptyString3(value) {
3637
+ function readNonEmptyString4(value) {
3589
3638
  if (typeof value !== "string") {
3590
3639
  return void 0;
3591
3640
  }
@@ -3607,7 +3656,7 @@ function resolveFinalAnswerFromToolResult(toolName, parsedResult) {
3607
3656
  return void 0;
3608
3657
  }
3609
3658
  if (toolName === "write_report") {
3610
- const report = readNonEmptyString3(data.report);
3659
+ const report = readNonEmptyString4(data.report);
3611
3660
  if (!report) {
3612
3661
  throw new Error("[write_report] \u5DE5\u5177\u8F93\u51FA\u7F3A\u5C11 data.report\uFF08\u5FC5\u987B\u63D0\u4F9B\u5B8C\u6574\u62A5\u544A\u6B63\u6587\uFF09");
3613
3662
  }
@@ -3617,7 +3666,7 @@ function resolveFinalAnswerFromToolResult(toolName, parsedResult) {
3617
3666
  if (data.success !== true) {
3618
3667
  return void 0;
3619
3668
  }
3620
- const finalAnswer = readNonEmptyString3(data.final_answer);
3669
+ const finalAnswer = readNonEmptyString4(data.final_answer);
3621
3670
  if (!finalAnswer) {
3622
3671
  throw new Error("[research_run_writer] \u5DE5\u5177\u8F93\u51FA\u7F3A\u5C11 data.final_answer\uFF08success=true \u65F6\u5FC5\u987B\u63D0\u4F9B\u6700\u7EC8\u62A5\u544A\u6B63\u6587\uFF09");
3623
3672
  }
@@ -4162,6 +4211,31 @@ function ensureToolContextRuntimeCapability(params) {
4162
4211
  function getToolContextRuntimeBinding(context) {
4163
4212
  return readBinding(context);
4164
4213
  }
4214
+ function copyToolContextRuntimeCapability(source, target) {
4215
+ const sourceBinding = readBinding(source);
4216
+ if (!sourceBinding) {
4217
+ return void 0;
4218
+ }
4219
+ const existingTargetBinding = readBinding(target);
4220
+ if (existingTargetBinding) {
4221
+ exposeCompatibilitySurface(target, existingTargetBinding);
4222
+ return existingTargetBinding;
4223
+ }
4224
+ const targetBinding = createRuntimeBinding({
4225
+ context: target,
4226
+ persistedHistory: () => sourceBinding.getPersistedHistoryEvents(),
4227
+ workingHistory: () => sourceBinding.getWorkingHistoryEvents(),
4228
+ executionMeta: sourceBinding.readExecutionMeta()
4229
+ });
4230
+ Object.defineProperty(target, TOOL_CONTEXT_RUNTIME_BINDING_KEY, {
4231
+ value: targetBinding,
4232
+ enumerable: false,
4233
+ configurable: true,
4234
+ writable: false
4235
+ });
4236
+ exposeCompatibilitySurface(target, targetBinding);
4237
+ return targetBinding;
4238
+ }
4165
4239
  function readToolContextWorkingHistory(context) {
4166
4240
  if (context.conversationView) {
4167
4241
  return context.conversationView.getWorkingHistoryEvents();
@@ -4575,6 +4649,22 @@ var ToolNode = class {
4575
4649
  });
4576
4650
  }
4577
4651
  async run(state) {
4652
+ const events = [];
4653
+ while (true) {
4654
+ const result = await this.runNextPendingToolCall(state);
4655
+ if (Array.isArray(result.events) && result.events.length > 0) {
4656
+ events.push(...result.events);
4657
+ }
4658
+ if (result.kind === "route" && result.nextNodeId === "tool") {
4659
+ continue;
4660
+ }
4661
+ return {
4662
+ ...result,
4663
+ events
4664
+ };
4665
+ }
4666
+ }
4667
+ async runNextPendingToolCall(state) {
4578
4668
  const calls = state.local?.pendingToolCalls ?? [];
4579
4669
  const signalRaw = state.local?.signal;
4580
4670
  if (isAbortSignal(signalRaw) && signalRaw.aborted) {
@@ -4782,18 +4872,25 @@ var ToolNode = class {
4782
4872
  rawArguments: context.call.function?.arguments,
4783
4873
  parsedArguments: context.toolArgs
4784
4874
  });
4875
+ const remainingCalls = context.calls.slice(1);
4785
4876
  context.state.local = buildErrorLocalState({
4786
4877
  local: context.local,
4787
- remainingCalls: context.calls.slice(1),
4878
+ remainingCalls,
4788
4879
  conversationId: context.conversationId,
4789
4880
  turnId: context.turnId,
4790
4881
  runtimeEvents: context.bridge.getRuntimeEvents(),
4791
4882
  nextProtocolErrorCount: fuse.nextCount
4792
4883
  });
4793
- if (fuse.shouldFuse) {
4884
+ if (fuse.shouldFuse && remainingCalls.length === 0) {
4794
4885
  throw createToolProtocolFuseError(fuse.nextCount, context.exec.error);
4795
4886
  }
4796
- return { kind: "route", nextNodeId: "llm", events: context.bridge.getRuntimeEvents() };
4887
+ return {
4888
+ kind: "route",
4889
+ // 同一个 assistant.tool_calls batch 必须为每个 call 产出 tool_output。
4890
+ // 出错时也继续消费剩余 call,ToolNode.run 会在本节点内 drain 完 batch 再回 LLM。
4891
+ nextNodeId: remainingCalls.length > 0 ? "tool" : "llm",
4892
+ events: context.bridge.getRuntimeEvents()
4893
+ };
4797
4894
  }
4798
4895
  };
4799
4896
 
@@ -4990,12 +5087,12 @@ function asRecord(value) {
4990
5087
  }
4991
5088
  return value;
4992
5089
  }
4993
- function summarizeCheckpoint(conversationId, state, savedAt) {
5090
+ function summarizeCheckpoint(checkpointKey, state, savedAt) {
4994
5091
  const local = asRecord(state.local);
4995
5092
  const executorLocal = asRecord(local?.executorLocal);
4996
5093
  const pendingToolCalls = local?.pendingToolCalls;
4997
5094
  return {
4998
- conversationId,
5095
+ checkpointKey,
4999
5096
  schemaVersion: state.schemaVersion ?? 1,
5000
5097
  savedAt,
5001
5098
  currentNode: state.nodeId,
@@ -5014,25 +5111,25 @@ var MemoryCheckpointer = class {
5014
5111
  local: state.local && typeof state.local === "object" && !Array.isArray(state.local) ? { ...state.local } : state.local
5015
5112
  };
5016
5113
  }
5017
- async load(conversationId) {
5018
- const entry = this.store.get(conversationId);
5114
+ async load(checkpointKey) {
5115
+ const entry = this.store.get(checkpointKey);
5019
5116
  return entry ? this.cloneState(entry.state) : null;
5020
5117
  }
5021
- async save(conversationId, state) {
5022
- this.store.set(conversationId, {
5118
+ async save(checkpointKey, state) {
5119
+ this.store.set(checkpointKey, {
5023
5120
  state: this.cloneState(state),
5024
5121
  savedAt: Date.now()
5025
5122
  });
5026
5123
  }
5027
- async clear(conversationId) {
5028
- this.store.delete(conversationId);
5124
+ async clear(checkpointKey) {
5125
+ this.store.delete(checkpointKey);
5029
5126
  }
5030
- async peekMeta(conversationId) {
5031
- const entry = this.store.get(conversationId);
5032
- return entry ? summarizeCheckpoint(conversationId, entry.state, entry.savedAt) : null;
5127
+ async peekMeta(checkpointKey) {
5128
+ const entry = this.store.get(checkpointKey);
5129
+ return entry ? summarizeCheckpoint(checkpointKey, entry.state, entry.savedAt) : null;
5033
5130
  }
5034
5131
  async list(filter = {}) {
5035
- const summaries = Array.from(this.store.entries()).map(([conversationId, entry]) => summarizeCheckpoint(conversationId, entry.state, entry.savedAt)).filter((summary) => filter.savedAfter === void 0 ? true : summary.savedAt > filter.savedAfter).sort((left, right) => right.savedAt - left.savedAt);
5132
+ const summaries = Array.from(this.store.entries()).map(([checkpointKey, entry]) => summarizeCheckpoint(checkpointKey, entry.state, entry.savedAt)).filter((summary) => filter.savedAfter === void 0 ? true : summary.savedAt > filter.savedAfter).sort((left, right) => right.savedAt - left.savedAt);
5036
5133
  if (filter.limit === void 0) {
5037
5134
  return summaries;
5038
5135
  }
@@ -5104,6 +5201,7 @@ __export(tools_exports, {
5104
5201
  CommonParameterTypes: () => CommonParameterTypes,
5105
5202
  ContextCheckpointTool: () => ContextCheckpointTool,
5106
5203
  computeToolIdempotencyKey: () => computeToolIdempotencyKey,
5204
+ copyToolContextRuntimeCapability: () => copyToolContextRuntimeCapability,
5107
5205
  createContextCheckpointTool: () => createContextCheckpointTool,
5108
5206
  ensureToolContextRuntimeCapability: () => ensureToolContextRuntimeCapability,
5109
5207
  findCachedToolOutputByIdempotencyKey: () => findCachedToolOutputByIdempotencyKey,
@@ -5297,7 +5395,7 @@ function createContextCheckpointTool(options) {
5297
5395
  function isRecord15(value) {
5298
5396
  return !!value && typeof value === "object" && !Array.isArray(value);
5299
5397
  }
5300
- function readNonEmptyString4(value) {
5398
+ function readNonEmptyString5(value) {
5301
5399
  if (typeof value !== "string") {
5302
5400
  return void 0;
5303
5401
  }
@@ -5317,13 +5415,13 @@ function readToolContextUserQuery(context) {
5317
5415
  if (!context) {
5318
5416
  return void 0;
5319
5417
  }
5320
- return readNonEmptyString4(context["user_query"]);
5418
+ return readNonEmptyString5(context["user_query"]);
5321
5419
  }
5322
5420
  function readToolContextModelId(context) {
5323
5421
  if (!context) {
5324
5422
  return void 0;
5325
5423
  }
5326
- return readNonEmptyString4(context["modelId"]);
5424
+ return readNonEmptyString5(context["modelId"]);
5327
5425
  }
5328
5426
  function readToolContextRunContext(context) {
5329
5427
  if (!context) {
@@ -5530,18 +5628,18 @@ function createClassification(category, reason, suggestedDelay, extras) {
5530
5628
  }
5531
5629
  var ErrorClassifier = class {
5532
5630
  static classify(error, context) {
5533
- const isRecord26 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
5631
+ const isRecord27 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
5534
5632
  const baseMsg = (error.message || "").toLowerCase();
5535
5633
  const causeMsg = (() => {
5536
5634
  const cause = error.cause;
5537
5635
  if (typeof cause === "string") return cause.toLowerCase();
5538
5636
  if (cause instanceof Error) return (cause.message || "").toLowerCase();
5539
- if (isRecord26(cause) && typeof cause["message"] === "string") return String(cause["message"]).toLowerCase();
5637
+ if (isRecord27(cause) && typeof cause["message"] === "string") return String(cause["message"]).toLowerCase();
5540
5638
  return "";
5541
5639
  })();
5542
5640
  const causeCode = (() => {
5543
5641
  const cause = error.cause;
5544
- if (isRecord26(cause) && typeof cause["code"] === "string") return String(cause["code"]);
5642
+ if (isRecord27(cause) && typeof cause["code"] === "string") return String(cause["code"]);
5545
5643
  return "";
5546
5644
  })();
5547
5645
  const errorMessage = `${baseMsg} ${causeMsg}`.trim();
@@ -6033,6 +6131,9 @@ __export(llm_exports, {
6033
6131
  LLMPolicyEngine: () => LLMPolicyEngine,
6034
6132
  LlmCaller: () => LlmCaller,
6035
6133
  ModelResolver: () => ModelResolver,
6134
+ appendStreamingProviderReasoningDetails: () => appendStreamingProviderReasoningDetails,
6135
+ compactProviderReasoningDetails: () => compactProviderReasoningDetails,
6136
+ compactReasoningDetailsInValue: () => compactReasoningDetailsInValue,
6036
6137
  createDefaultTokenizerPort: () => createDefaultTokenizerPort,
6037
6138
  defaultPolicyEngine: () => defaultPolicyEngine
6038
6139
  });
@@ -6422,6 +6523,90 @@ function assertToolCallsHaveValidJsonArguments(toolCalls) {
6422
6523
  }
6423
6524
  }
6424
6525
 
6526
+ // src/runtime-kernel/llm/reasoning-details.ts
6527
+ var mergeableTextFields = ["reasoning_content"];
6528
+ function isRecord20(value) {
6529
+ return !!value && typeof value === "object" && !Array.isArray(value);
6530
+ }
6531
+ function findMergeableTextField(detail) {
6532
+ if (!isRecord20(detail)) return void 0;
6533
+ if (typeof detail.provider !== "string") return void 0;
6534
+ if (typeof detail.type !== "string") return void 0;
6535
+ for (const field of mergeableTextFields) {
6536
+ if (typeof detail[field] === "string") {
6537
+ return field;
6538
+ }
6539
+ }
6540
+ return void 0;
6541
+ }
6542
+ function hasOnlyStableTextDetailFields(detail, textField) {
6543
+ const allowedKeys = /* @__PURE__ */ new Set(["provider", "type", textField]);
6544
+ return Object.keys(detail).every((key) => allowedKeys.has(key));
6545
+ }
6546
+ function canMergeTextDetails(previous, incoming) {
6547
+ if (!isRecord20(previous) || !isRecord20(incoming)) return false;
6548
+ const previousField = findMergeableTextField(previous);
6549
+ const incomingField = findMergeableTextField(incoming);
6550
+ if (!previousField || previousField !== incomingField) return false;
6551
+ return previous.provider === incoming.provider && previous.type === incoming.type && hasOnlyStableTextDetailFields(previous, previousField) && hasOnlyStableTextDetailFields(incoming, incomingField);
6552
+ }
6553
+ function mergeStreamingText(previous, incoming) {
6554
+ if (!previous) return incoming;
6555
+ if (!incoming) return previous;
6556
+ if (incoming.startsWith(previous)) {
6557
+ return incoming;
6558
+ }
6559
+ if (previous.endsWith(incoming)) {
6560
+ return previous;
6561
+ }
6562
+ return `${previous}${incoming}`;
6563
+ }
6564
+ function appendStreamingProviderReasoningDetails(existing, incoming) {
6565
+ const next = [...existing];
6566
+ for (const detail of incoming) {
6567
+ const previous = next[next.length - 1];
6568
+ if (canMergeTextDetails(previous, detail)) {
6569
+ const textField = findMergeableTextField(previous);
6570
+ if (textField && isRecord20(detail)) {
6571
+ const mergedText = mergeStreamingText(String(previous[textField]), String(detail[textField]));
6572
+ if (mergedText === previous[textField]) {
6573
+ continue;
6574
+ }
6575
+ next[next.length - 1] = {
6576
+ ...previous,
6577
+ [textField]: mergedText
6578
+ };
6579
+ continue;
6580
+ }
6581
+ }
6582
+ next.push(detail);
6583
+ }
6584
+ return next;
6585
+ }
6586
+ function compactProviderReasoningDetails(reasoningDetails) {
6587
+ return appendStreamingProviderReasoningDetails([], reasoningDetails);
6588
+ }
6589
+ function compactReasoningDetailsInValue(value) {
6590
+ return compactValue(value);
6591
+ }
6592
+ function compactValue(value) {
6593
+ if (Array.isArray(value)) {
6594
+ return value.map((item) => compactValue(item));
6595
+ }
6596
+ if (!isRecord20(value)) {
6597
+ return value;
6598
+ }
6599
+ const compacted = {};
6600
+ for (const [key, childValue] of Object.entries(value)) {
6601
+ if (key === "reasoning_details" && Array.isArray(childValue)) {
6602
+ compacted[key] = compactProviderReasoningDetails(childValue);
6603
+ continue;
6604
+ }
6605
+ compacted[key] = compactValue(childValue);
6606
+ }
6607
+ return compacted;
6608
+ }
6609
+
6425
6610
  // src/runtime-kernel/llm/streaming-adapter.ts
6426
6611
  async function callLlmStream(params) {
6427
6612
  const {
@@ -6434,7 +6619,7 @@ async function callLlmStream(params) {
6434
6619
  } = params;
6435
6620
  let fullResponse = "";
6436
6621
  let streamError = null;
6437
- const reasoningDetails = [];
6622
+ let reasoningDetails = [];
6438
6623
  const streamAnswerId = generateMessageId();
6439
6624
  let streamChunkSeq = 0;
6440
6625
  let capturedUsage = void 0;
@@ -6504,13 +6689,21 @@ async function callLlmStream(params) {
6504
6689
  const reasoning = isRecord19(chunk) ? chunk["reasoning_details"] : void 0;
6505
6690
  if (reasoning !== void 0) {
6506
6691
  const newReasoningDetails = Array.isArray(reasoning) ? reasoning : [reasoning];
6507
- reasoningDetails.push(...newReasoningDetails);
6508
- eventHandler({
6509
- type: "provider_sidecar",
6510
- id: generateMessageId(),
6511
- timestamp: Date.now(),
6512
- reasoning_details: newReasoningDetails
6513
- });
6692
+ const previousReasoningDetails = reasoningDetails;
6693
+ const previousLength = previousReasoningDetails.length;
6694
+ const compactedReasoningDetails = appendStreamingProviderReasoningDetails(reasoningDetails, newReasoningDetails);
6695
+ reasoningDetails = compactedReasoningDetails;
6696
+ const previousLastChanged = previousLength > 0 && compactedReasoningDetails[previousLength - 1] !== previousReasoningDetails[previousLength - 1];
6697
+ const emitFromIndex = previousLastChanged ? previousLength - 1 : previousLength;
6698
+ const emittedReasoningDetails = compactedReasoningDetails.slice(Math.max(0, emitFromIndex));
6699
+ if (emittedReasoningDetails.length > 0) {
6700
+ eventHandler({
6701
+ type: "provider_sidecar",
6702
+ id: generateMessageId(),
6703
+ timestamp: Date.now(),
6704
+ reasoning_details: emittedReasoningDetails
6705
+ });
6706
+ }
6514
6707
  }
6515
6708
  if (chunk.tool_calls) {
6516
6709
  emitThoughtComplete(thoughtSegmenter.onBoundary());
@@ -6964,7 +7157,6 @@ __export(child_runs_exports, {
6964
7157
 
6965
7158
  // src/runtime-kernel/child-runs/childToolContext.ts
6966
7159
  function createChildRunToolContext(params) {
6967
- const inheritedConversationId = typeof params.parentToolContext.conversationId === "string" && params.parentToolContext.conversationId.trim().length > 0 ? params.parentToolContext.conversationId.trim() : void 0;
6968
7160
  const inheritedContext = stripRuntimeReservedToolContextPatch(params.parentToolContext);
6969
7161
  const childToolContext = {
6970
7162
  ...inheritedContext,
@@ -6976,7 +7168,7 @@ function createChildRunToolContext(params) {
6976
7168
  persistedHistory: params.seedHistory,
6977
7169
  workingHistory: params.seedHistory,
6978
7170
  executionMeta: {
6979
- conversationId: inheritedConversationId ?? params.internalConversationId,
7171
+ conversationId: params.conversationId,
6980
7172
  turnId: params.turnId,
6981
7173
  runId: params.runId,
6982
7174
  parentRunId: params.parentRunId
@@ -7127,7 +7319,7 @@ var FinalAnswerCollector = class {
7127
7319
  };
7128
7320
 
7129
7321
  // src/runtime-kernel/child-runs/childRunTraceSink.ts
7130
- function isRecord20(v) {
7322
+ function isRecord21(v) {
7131
7323
  return !!v && typeof v === "object" && !Array.isArray(v);
7132
7324
  }
7133
7325
  function getString2(obj, key) {
@@ -7160,7 +7352,7 @@ function createChildRunTraceSink(params) {
7160
7352
  const { publisher, conversationId, turnId } = params;
7161
7353
  const finalAnswerCollector = new FinalAnswerCollector(conversationId, turnId);
7162
7354
  const sink = (evt) => {
7163
- if (!isRecord20(evt)) {
7355
+ if (!isRecord21(evt)) {
7164
7356
  return [];
7165
7357
  }
7166
7358
  const type = getString2(evt, "type");
@@ -7296,7 +7488,7 @@ function readCheckpointHistory(checkpoint) {
7296
7488
  });
7297
7489
  }
7298
7490
  async function recoverChildRunEventsFromCheckpoint(params) {
7299
- const checkpoint = await params.checkpointer.load(params.conversationId);
7491
+ const checkpoint = await params.checkpointer.load(params.checkpointKey);
7300
7492
  const history = readCheckpointHistory(checkpoint);
7301
7493
  if (history.length === 0) {
7302
7494
  return [];
@@ -7304,7 +7496,7 @@ async function recoverChildRunEventsFromCheckpoint(params) {
7304
7496
  if (hasSeedHistoryPrefix(history, params.seedHistory)) {
7305
7497
  return history.slice(params.seedHistory.length);
7306
7498
  }
7307
- return history.filter((event) => event.conversation_id === params.internalConversationId);
7499
+ return history.filter((event) => event.conversation_id === params.childConversationId);
7308
7500
  }
7309
7501
 
7310
7502
  // src/runtime-kernel/child-runs/childRunInvoker.ts
@@ -7333,6 +7525,7 @@ var ChildRunInvoker = class {
7333
7525
  agentConfig,
7334
7526
  userMessage,
7335
7527
  parentToolContext,
7528
+ conversationId,
7336
7529
  runId,
7337
7530
  parentRunId,
7338
7531
  subrunTracePublisher,
@@ -7341,12 +7534,18 @@ var ChildRunInvoker = class {
7341
7534
  modelId,
7342
7535
  abortSignal
7343
7536
  } = config;
7344
- const internalConversationId = `internal_${generateMessageId()}`;
7537
+ const internalCheckpointKey = `internal_${generateMessageId()}`;
7538
+ const runtimeConversationId = resolveChildRunConversationId({
7539
+ explicitConversationId: conversationId,
7540
+ parentToolContext,
7541
+ fallbackConversationId: internalCheckpointKey
7542
+ });
7345
7543
  const turnId = `turn_${Date.now()}`;
7346
- const childRunId = typeof runId === "string" && runId.trim().length > 0 ? runId.trim() : internalConversationId;
7544
+ const childRunId = typeof runId === "string" && runId.trim().length > 0 ? runId.trim() : internalCheckpointKey;
7347
7545
  const resolvedParentRunId = typeof parentRunId === "string" && parentRunId.trim().length > 0 ? parentRunId.trim() : typeof parentToolContext.runId === "string" && parentToolContext.runId.trim().length > 0 ? parentToolContext.runId.trim() : void 0;
7348
7546
  logger13.info(`\u542F\u52A8 child-run: ${agentConfig.id}`, {
7349
- conversationId: internalConversationId,
7547
+ conversationId: runtimeConversationId,
7548
+ checkpointKey: internalCheckpointKey,
7350
7549
  maxSteps,
7351
7550
  userMessage: userMessage.slice(0, 100) + (userMessage.length > 100 ? "..." : "")
7352
7551
  });
@@ -7407,7 +7606,7 @@ var ChildRunInvoker = class {
7407
7606
  const seedHistory = Array.isArray(seedHistoryEvents) ? seedHistoryEvents : [];
7408
7607
  const childToolContext = createChildRunToolContext({
7409
7608
  parentToolContext,
7410
- internalConversationId,
7609
+ conversationId: runtimeConversationId,
7411
7610
  turnId,
7412
7611
  runId: childRunId,
7413
7612
  parentRunId: resolvedParentRunId,
@@ -7416,13 +7615,13 @@ var ChildRunInvoker = class {
7416
7615
  });
7417
7616
  const subrunSseSink = subrunTracePublisher ? createChildRunTraceSink({
7418
7617
  publisher: subrunTracePublisher,
7419
- conversationId: internalConversationId,
7618
+ conversationId: runtimeConversationId,
7420
7619
  turnId
7421
7620
  }) : void 0;
7422
7621
  const initialLocal = {
7423
7622
  request,
7424
7623
  history: seedHistory,
7425
- conversationId: internalConversationId,
7624
+ conversationId: runtimeConversationId,
7426
7625
  turnId,
7427
7626
  toolContext: childToolContext,
7428
7627
  ...abortSignal ? { signal: abortSignal } : {},
@@ -7430,7 +7629,7 @@ var ChildRunInvoker = class {
7430
7629
  ...subrunSseSink ? { sseSink: subrunSseSink } : {},
7431
7630
  systemPrompt
7432
7631
  };
7433
- await graphExecutor.prime(internalConversationId, initialLocal, "llm");
7632
+ await graphExecutor.prime(internalCheckpointKey, initialLocal, "llm");
7434
7633
  const allEvents = [];
7435
7634
  let stepCount = 0;
7436
7635
  let finalAnswer;
@@ -7442,7 +7641,7 @@ var ChildRunInvoker = class {
7442
7641
  err.name = "AbortError";
7443
7642
  throw err;
7444
7643
  }
7445
- const result = await graphExecutor.runUntilYield(internalConversationId);
7644
+ const result = await graphExecutor.runUntilYield(internalCheckpointKey);
7446
7645
  appendUniqueEvents(allEvents, result.events);
7447
7646
  stepCount = result.stepCount;
7448
7647
  if (subrunSseSink && typeof subrunSseSink.finalize === "function") {
@@ -7476,8 +7675,8 @@ var ChildRunInvoker = class {
7476
7675
  }
7477
7676
  const recoveredEvents = await recoverChildRunEventsFromCheckpoint({
7478
7677
  checkpointer,
7479
- conversationId: internalConversationId,
7480
- internalConversationId,
7678
+ checkpointKey: internalCheckpointKey,
7679
+ childConversationId: runtimeConversationId,
7481
7680
  seedHistory
7482
7681
  });
7483
7682
  appendUniqueEvents(allEvents, recoveredEvents);
@@ -7494,7 +7693,7 @@ var ChildRunInvoker = class {
7494
7693
  stack: err.stack
7495
7694
  } : { error: String(err) });
7496
7695
  }
7497
- await checkpointer.clear(internalConversationId);
7696
+ await checkpointer.clear(internalCheckpointKey);
7498
7697
  return {
7499
7698
  success: !error,
7500
7699
  runId: childRunId,
@@ -7507,6 +7706,16 @@ var ChildRunInvoker = class {
7507
7706
  };
7508
7707
  }
7509
7708
  };
7709
+ function readNonEmptyString6(value) {
7710
+ if (typeof value !== "string") {
7711
+ return void 0;
7712
+ }
7713
+ const trimmed = value.trim();
7714
+ return trimmed.length > 0 ? trimmed : void 0;
7715
+ }
7716
+ function resolveChildRunConversationId(params) {
7717
+ return readNonEmptyString6(params.explicitConversationId) ?? readNonEmptyString6(params.parentToolContext.conversationId) ?? params.fallbackConversationId;
7718
+ }
7510
7719
  function resolveChildRunSystemReminderPolicy(agentConfig) {
7511
7720
  const configured = agentConfig.systemReminderPolicy ?? agentConfig.contextPolicy?.systemReminder;
7512
7721
  const threshold = agentConfig.stepPolicy?.lastStepsHintThreshold;
@@ -7697,7 +7906,7 @@ function cloneRunRecord(record) {
7697
7906
  ...record,
7698
7907
  iterationBudget: record.iterationBudget ? { ...record.iterationBudget } : void 0,
7699
7908
  errorIfAny: record.errorIfAny ? { ...record.errorIfAny } : void 0,
7700
- metadata: record.metadata ? { ...record.metadata } : void 0
7909
+ metadata: record.metadata ? structuredClone(record.metadata) : void 0
7701
7910
  };
7702
7911
  }
7703
7912
  function matchesStatus(candidate, filter) {
@@ -7829,7 +8038,7 @@ function runRecordToMeta(record) {
7829
8038
  errorIfAny: record.errorIfAny ? { ...record.errorIfAny } : void 0
7830
8039
  };
7831
8040
  }
7832
- function isRecord21(value) {
8041
+ function isRecord22(value) {
7833
8042
  return typeof value === "object" && value !== null && !Array.isArray(value);
7834
8043
  }
7835
8044
  function readStringField(record, key) {
@@ -7850,7 +8059,7 @@ function getRunIdFromMetadata(event) {
7850
8059
  return snakeCaseRunId;
7851
8060
  }
7852
8061
  const runContext = metadata["run_context"];
7853
- if (isRecord21(runContext)) {
8062
+ if (isRecord22(runContext)) {
7854
8063
  return readStringField(runContext, "runId") ?? readStringField(runContext, "run_id");
7855
8064
  }
7856
8065
  return void 0;
@@ -8068,7 +8277,7 @@ function runMetaFromRecord(record) {
8068
8277
  }
8069
8278
 
8070
8279
  // src/runtime-kernel/run-supervisor/runSupervisor.ts
8071
- function isRecord22(value) {
8280
+ function isRecord23(value) {
8072
8281
  return typeof value === "object" && value !== null && !Array.isArray(value);
8073
8282
  }
8074
8283
  function readStringField2(record, key) {
@@ -8085,7 +8294,7 @@ function readRunIdFromRuntimeEvent(event) {
8085
8294
  return directRunId;
8086
8295
  }
8087
8296
  const runContext = metadata["run_context"];
8088
- if (!isRecord22(runContext)) {
8297
+ if (!isRecord23(runContext)) {
8089
8298
  return void 0;
8090
8299
  }
8091
8300
  return readStringField2(runContext, "runId") ?? readStringField2(runContext, "run_id");
@@ -8097,7 +8306,7 @@ function readAwaitingUserReason(event) {
8097
8306
  if (typeof event.prompt === "string" && event.prompt.trim().length > 0) {
8098
8307
  return event.prompt;
8099
8308
  }
8100
- if (isRecord22(event.form)) {
8309
+ if (isRecord23(event.form)) {
8101
8310
  const prompt = readStringField2(event.form, "prompt");
8102
8311
  if (prompt && prompt.trim().length > 0) {
8103
8312
  return prompt;
@@ -8109,7 +8318,7 @@ function isTerminalStatus(status) {
8109
8318
  return status === "completed" || status === "failed" || status === "cancelled";
8110
8319
  }
8111
8320
  function cloneMetadata(metadata) {
8112
- return metadata ? { ...metadata } : void 0;
8321
+ return metadata ? structuredClone(metadata) : void 0;
8113
8322
  }
8114
8323
  function recordToSnapshot(record) {
8115
8324
  return {
@@ -8196,7 +8405,7 @@ var DefaultRunSupervisor = class {
8196
8405
  startedAt,
8197
8406
  updatedAt: startedAt,
8198
8407
  iterationBudget: spec.iterationBudget ? { ...spec.iterationBudget } : void 0,
8199
- metadata: spec.metadata ? { ...spec.metadata } : void 0
8408
+ metadata: cloneMetadata(spec.metadata)
8200
8409
  };
8201
8410
  await this.registryStore.save(record);
8202
8411
  const handle = new DefaultRunHandle({
@@ -8370,12 +8579,13 @@ var DefaultRunSupervisor = class {
8370
8579
  }
8371
8580
  try {
8372
8581
  await handle.markRunning({ currentNode: "detached" });
8582
+ const registeredRecord = await this.registryStore.load(handle.runId);
8373
8583
  const executorOutcome = await this.executor.execute({
8374
8584
  runId: handle.runId,
8375
- parentRunId: spec.parentRunId,
8376
- conversationId: spec.conversationId,
8377
- agentSpec: spec.agentSpec,
8378
- request: spec.request,
8585
+ parentRunId: handle.parentRunId,
8586
+ conversationId: registeredRecord?.conversationId ?? spec.conversationId,
8587
+ agentSpec: await handle.spec(),
8588
+ request: await handle.request(),
8379
8589
  signal: handle.signal,
8380
8590
  eventBus: spec.eventBus,
8381
8591
  eventStore: spec.eventStore,
@@ -8384,7 +8594,7 @@ var DefaultRunSupervisor = class {
8384
8594
  contextFences: spec.contextFences,
8385
8595
  wakeSource: spec.wakeSource,
8386
8596
  ephemeral: spec.ephemeral,
8387
- metadata: spec.metadata
8597
+ metadata: cloneMetadata(registeredRecord?.metadata ?? spec.metadata)
8388
8598
  });
8389
8599
  const outcome = await this.persistExecutorOutcome(handle, executorOutcome);
8390
8600
  this.notifyTerminalWaiters(outcome);
@@ -8448,10 +8658,14 @@ var DefaultRunSupervisor = class {
8448
8658
  await this.registryStore.save(record);
8449
8659
  }
8450
8660
  const completedAt = executorOutcome?.completedAt ?? this.now();
8661
+ const fallbackMeta = record ? void 0 : await handle.meta();
8451
8662
  const outcome = recordToTerminalOutcome(record ?? {
8452
8663
  runId: handle.runId,
8453
8664
  parentRunId: handle.parentRunId,
8454
- status: executorOutcome?.status ?? "completed"}, completedAt);
8665
+ conversationId: fallbackMeta?.conversationId ?? "",
8666
+ agentSpecId: fallbackMeta?.agentSpecId,
8667
+ status: executorOutcome?.status ?? "completed",
8668
+ startedAt: fallbackMeta?.startedAt ?? completedAt}, completedAt);
8455
8669
  const nextOutcome = {
8456
8670
  ...outcome,
8457
8671
  metadata: {
@@ -8679,6 +8893,7 @@ function createGraphLoopHarness(options) {
8679
8893
  };
8680
8894
  return {
8681
8895
  async run() {
8896
+ const checkpointKey = options.conversationId;
8682
8897
  const executor = createDefaultGraphExecutor({
8683
8898
  llmNode: options.createLlmNode({
8684
8899
  llmCaller: options.llmCaller,
@@ -8707,8 +8922,8 @@ function createGraphLoopHarness(options) {
8707
8922
  signal: options.signal ?? options.toolContext.abortSignal,
8708
8923
  executorLocal
8709
8924
  };
8710
- await executor.prime(options.conversationId, local, "user");
8711
- const result = await executor.runUntilYield(options.conversationId);
8925
+ await executor.prime(checkpointKey, local, "user");
8926
+ const result = await executor.runUntilYield(checkpointKey);
8712
8927
  return {
8713
8928
  checkpointNodeId: result.checkpoint.nodeId,
8714
8929
  stepCount: result.stepCount
@@ -8983,11 +9198,11 @@ new MessageFormatter();
8983
9198
 
8984
9199
  // src/context-manager/profiles/agent/utils/toolInteractionGroup.ts
8985
9200
  var CHECKPOINT_TOOL_NAME = "context_checkpoint";
8986
- function isRecord23(value) {
9201
+ function isRecord24(value) {
8987
9202
  return typeof value === "object" && value !== null && !Array.isArray(value);
8988
9203
  }
8989
9204
  function isToolCallRecord(value) {
8990
- if (!isRecord23(value)) {
9205
+ if (!isRecord24(value)) {
8991
9206
  return false;
8992
9207
  }
8993
9208
  return typeof value.id === "string" && value.id.trim().length > 0;
@@ -9005,7 +9220,7 @@ function safeParseArgs(rawArgs) {
9005
9220
  }
9006
9221
  try {
9007
9222
  const parsed = JSON.parse(rawArgs);
9008
- return isRecord23(parsed) ? parsed : {};
9223
+ return isRecord24(parsed) ? parsed : {};
9009
9224
  } catch {
9010
9225
  return {};
9011
9226
  }
@@ -9299,7 +9514,7 @@ var summarizeToolOutput = (toolName, output, toolSummaryProvider, toolArgs, conf
9299
9514
  };
9300
9515
 
9301
9516
  // src/context-manager/profiles/agent/utils/eventConverter.ts
9302
- function isRecord24(value) {
9517
+ function isRecord25(value) {
9303
9518
  return !!value && typeof value === "object" && !Array.isArray(value);
9304
9519
  }
9305
9520
  function isHistorySummaryEvent2(event) {
@@ -9357,10 +9572,10 @@ function convertEventToAiMessage(event) {
9357
9572
  timestamp: event.timestamp,
9358
9573
  metadata: {
9359
9574
  tool_calls: (() => {
9360
- const isRecord26 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
9575
+ const isRecord27 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
9361
9576
  const payload = event.payload;
9362
9577
  const toolCallsFromPayload = (() => {
9363
- if (!isRecord26(payload)) return void 0;
9578
+ if (!isRecord27(payload)) return void 0;
9364
9579
  const raw = payload["tool_calls"];
9365
9580
  return Array.isArray(raw) ? raw : void 0;
9366
9581
  })();
@@ -9379,9 +9594,9 @@ function convertEventToAiMessage(event) {
9379
9594
  ];
9380
9595
  })(),
9381
9596
  reasoning_details: (() => {
9382
- const isRecord26 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
9597
+ const isRecord27 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
9383
9598
  const payload = event.payload;
9384
- if (!isRecord26(payload)) return void 0;
9599
+ if (!isRecord27(payload)) return void 0;
9385
9600
  const rd = payload["reasoning_details"];
9386
9601
  return Array.isArray(rd) ? rd : void 0;
9387
9602
  })()
@@ -9390,15 +9605,15 @@ function convertEventToAiMessage(event) {
9390
9605
  case "tool_output": {
9391
9606
  const observationFromPayload = (() => {
9392
9607
  const payload = event.payload;
9393
- if (!isRecord24(payload)) return void 0;
9608
+ if (!isRecord25(payload)) return void 0;
9394
9609
  const result = payload["result"];
9395
- if (!isRecord24(result)) return void 0;
9610
+ if (!isRecord25(result)) return void 0;
9396
9611
  const obs = result["observation"];
9397
9612
  return typeof obs === "string" && obs.trim().length > 0 ? obs : void 0;
9398
9613
  })();
9399
9614
  const rawOutput = (() => {
9400
9615
  const payload = event.payload;
9401
- if (isRecord24(payload)) {
9616
+ if (isRecord25(payload)) {
9402
9617
  const out = payload["output"];
9403
9618
  if (typeof out === "string" && out.trim().length > 0) {
9404
9619
  return out;
@@ -9523,7 +9738,7 @@ __export(utils_exports, {
9523
9738
  });
9524
9739
 
9525
9740
  // src/testkit/context-harness/replayHarness.ts
9526
- function isRecord25(value) {
9741
+ function isRecord26(value) {
9527
9742
  return !!value && typeof value === "object" && !Array.isArray(value);
9528
9743
  }
9529
9744
  function createReplayHarness(events) {
@@ -9535,7 +9750,7 @@ function createReplayHarness(events) {
9535
9750
  if (message.role !== "assistant" || message.type !== "tool_calls") {
9536
9751
  return false;
9537
9752
  }
9538
- if (!isRecord25(message.metadata)) {
9753
+ if (!isRecord26(message.metadata)) {
9539
9754
  return false;
9540
9755
  }
9541
9756
  return Array.isArray(message.metadata.tool_calls);