@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.cjs CHANGED
@@ -107,14 +107,18 @@ __export(runtime_kernel_exports, {
107
107
  UserNode: () => UserNode,
108
108
  WaitUserNode: () => WaitUserNode,
109
109
  agentHasToolTrigger: () => agentHasToolTrigger,
110
+ appendStreamingProviderReasoningDetails: () => appendStreamingProviderReasoningDetails,
110
111
  applySystemReminders: () => applySystemReminders,
111
112
  audit: () => audit_exports,
112
113
  budgetWarningTrigger: () => budgetWarningTrigger,
113
114
  childRunTrace: () => child_run_trace_exports,
114
115
  childRuns: () => child_runs_exports,
116
+ compactProviderReasoningDetails: () => compactProviderReasoningDetails,
117
+ compactReasoningDetailsInValue: () => compactReasoningDetailsInValue,
115
118
  computeToolIdempotencyKey: () => computeToolIdempotencyKey,
116
119
  consoleAudit: () => consoleAudit,
117
120
  contextBudgetWarningTemplate: () => contextBudgetWarningTemplate,
121
+ copyToolContextRuntimeCapability: () => copyToolContextRuntimeCapability,
118
122
  countToolCallsInCurrentRequest: () => countToolCallsInCurrentRequest,
119
123
  createCompositeAudit: () => createCompositeAudit,
120
124
  createConsoleAudit: () => createConsoleAudit,
@@ -419,6 +423,7 @@ var AgentSpecBudgetPolicy = zod.z.object({
419
423
  });
420
424
  var AgentSpecToolHistoryPolicy = zod.z.object({
421
425
  strategy: zod.z.enum(["per-pair", "per-run", "none"]).optional(),
426
+ retentionMode: zod.z.enum(["drop", "compress"]).optional(),
422
427
  keepLatestToolPairs: zod.z.number().int().nonnegative().optional(),
423
428
  keepLatestRuns: zod.z.number().int().nonnegative().optional(),
424
429
  maxInteractionGroups: zod.z.number().int().nonnegative().optional(),
@@ -1175,6 +1180,17 @@ var logger = new Logger("GraphExecutor");
1175
1180
  function asLocalRecord(local) {
1176
1181
  return local && typeof local === "object" ? { ...local } : {};
1177
1182
  }
1183
+ function readNonEmptyString(value) {
1184
+ return typeof value === "string" && value.trim().length > 0 ? value : void 0;
1185
+ }
1186
+ function readRuntimeConversationId(state) {
1187
+ const local = state?.local && typeof state.local === "object" ? state.local : void 0;
1188
+ return readNonEmptyString(local?.conversationId);
1189
+ }
1190
+ function readRuntimeTurnId(state) {
1191
+ const local = state?.local && typeof state.local === "object" ? state.local : void 0;
1192
+ return readNonEmptyString(local?.turnId);
1193
+ }
1178
1194
  var GraphExecutor = class {
1179
1195
  constructor(checkpointer, config = {}) {
1180
1196
  this.checkpointer = checkpointer;
@@ -1192,8 +1208,8 @@ var GraphExecutor = class {
1192
1208
  registerNode(node) {
1193
1209
  this.nodes.set(node.id, node);
1194
1210
  }
1195
- async peekCheckpoint(conversationId) {
1196
- return await this.checkpointer.load(conversationId);
1211
+ async peekCheckpoint(checkpointKey) {
1212
+ return await this.checkpointer.load(checkpointKey);
1197
1213
  }
1198
1214
  sanitize(state) {
1199
1215
  const local = asLocalRecord(state.local);
@@ -1205,8 +1221,8 @@ var GraphExecutor = class {
1205
1221
  local
1206
1222
  };
1207
1223
  }
1208
- async prime(conversationId, local, nodeId = "user") {
1209
- this.ephemeralLocals.set(conversationId, { ...local || {} });
1224
+ async prime(checkpointKey, local, nodeId = "user") {
1225
+ this.ephemeralLocals.set(checkpointKey, { ...local || {} });
1210
1226
  const localSansMemory = { ...local || {} };
1211
1227
  if ("memory" in localSansMemory) delete localSansMemory.memory;
1212
1228
  const state = {
@@ -1214,10 +1230,10 @@ var GraphExecutor = class {
1214
1230
  schemaVersion: ENGINE_STATE_SCHEMA_VERSION,
1215
1231
  local: localSansMemory
1216
1232
  };
1217
- await this.checkpointer.save(conversationId, state);
1233
+ await this.checkpointer.save(checkpointKey, state);
1218
1234
  }
1219
- async setNode(conversationId, nodeId, localPatch) {
1220
- const current = await this.checkpointer.load(conversationId) || {
1235
+ async setNode(checkpointKey, nodeId, localPatch) {
1236
+ const current = await this.checkpointer.load(checkpointKey) || {
1221
1237
  schemaVersion: ENGINE_STATE_SCHEMA_VERSION,
1222
1238
  local: {}
1223
1239
  };
@@ -1228,19 +1244,46 @@ var GraphExecutor = class {
1228
1244
  schemaVersion: current.schemaVersion ?? ENGINE_STATE_SCHEMA_VERSION,
1229
1245
  local: mergedLocal
1230
1246
  };
1231
- await this.checkpointer.save(conversationId, next);
1247
+ await this.checkpointer.save(checkpointKey, next);
1232
1248
  }
1233
- async runUntilYield(conversationId) {
1249
+ async runUntilYield(checkpointKey) {
1234
1250
  const runId = `run_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
1235
1251
  let lifecyclePhase = "completed";
1252
+ let initialState = null;
1253
+ try {
1254
+ initialState = await this.loadInitialState(checkpointKey);
1255
+ } catch (err) {
1256
+ lifecyclePhase = "failed";
1257
+ this.telemetryPort.emit({
1258
+ kind: "run_lifecycle",
1259
+ runId,
1260
+ phase: "spawned",
1261
+ scope: {}
1262
+ });
1263
+ this.telemetryPort.emit({
1264
+ kind: "run_lifecycle",
1265
+ runId,
1266
+ phase: lifecyclePhase,
1267
+ scope: {}
1268
+ });
1269
+ throw err;
1270
+ }
1271
+ let lifecycleConversationId = readRuntimeConversationId(initialState);
1272
+ let lifecycleTurnId = readRuntimeTurnId(initialState);
1236
1273
  this.telemetryPort.emit({
1237
1274
  kind: "run_lifecycle",
1238
1275
  runId,
1239
1276
  phase: "spawned",
1240
- scope: { conversationId: conversationId || void 0 }
1277
+ scope: {
1278
+ conversationId: lifecycleConversationId,
1279
+ turnId: lifecycleTurnId
1280
+ }
1241
1281
  });
1242
1282
  try {
1243
- return await this.runUntilYieldInternal(conversationId);
1283
+ const result = await this.runUntilYieldInternal(checkpointKey, initialState);
1284
+ lifecycleConversationId = readRuntimeConversationId(result.checkpoint);
1285
+ lifecycleTurnId = readRuntimeTurnId(result.checkpoint);
1286
+ return result;
1244
1287
  } catch (err) {
1245
1288
  lifecyclePhase = err?.name === "AbortError" ? "cancelled" : "failed";
1246
1289
  throw err;
@@ -1249,17 +1292,23 @@ var GraphExecutor = class {
1249
1292
  kind: "run_lifecycle",
1250
1293
  runId,
1251
1294
  phase: lifecyclePhase,
1252
- scope: { conversationId: conversationId || void 0 }
1295
+ scope: {
1296
+ conversationId: lifecycleConversationId,
1297
+ turnId: lifecycleTurnId
1298
+ }
1253
1299
  });
1254
1300
  }
1255
1301
  }
1256
- async runUntilYieldInternal(conversationId) {
1257
- let state = await this.checkpointer.load(conversationId) || {
1302
+ async loadInitialState(checkpointKey) {
1303
+ return await this.checkpointer.load(checkpointKey) || {
1258
1304
  nodeId: "user",
1259
1305
  schemaVersion: ENGINE_STATE_SCHEMA_VERSION,
1260
1306
  local: {}
1261
1307
  };
1262
- const ephemeral = this.ephemeralLocals.get(conversationId) || {};
1308
+ }
1309
+ async runUntilYieldInternal(checkpointKey, initialState) {
1310
+ let state = initialState;
1311
+ const ephemeral = this.ephemeralLocals.get(checkpointKey) || {};
1263
1312
  state = {
1264
1313
  ...state,
1265
1314
  schemaVersion: state.schemaVersion ?? ENGINE_STATE_SCHEMA_VERSION,
@@ -1288,7 +1337,7 @@ var GraphExecutor = class {
1288
1337
  const signalRaw = state.local?.signal;
1289
1338
  if (isAbortSignal2(signalRaw) && signalRaw.aborted) {
1290
1339
  logger.warn("[GraphExecutor] \u6536\u5230 AbortSignal\uFF0C\u7ACB\u5373\u505C\u6B62\u63A8\u7406\u5FAA\u73AF");
1291
- this.ephemeralLocals.delete(conversationId);
1340
+ this.ephemeralLocals.delete(checkpointKey);
1292
1341
  throwAbortError();
1293
1342
  }
1294
1343
  const isLastStep = cycleStepCount >= this.config.maxSteps;
@@ -1336,8 +1385,8 @@ var GraphExecutor = class {
1336
1385
  checkpointCount
1337
1386
  });
1338
1387
  const cp2 = this.sanitize(state);
1339
- await this.checkpointer.save(conversationId, cp2);
1340
- this.ephemeralLocals.delete(conversationId);
1388
+ await this.checkpointer.save(checkpointKey, cp2);
1389
+ this.ephemeralLocals.delete(checkpointKey);
1341
1390
  return { events: allEvents, checkpoint: cp2, stepCount };
1342
1391
  }
1343
1392
  logger.info("[GraphExecutor] \u8282\u70B9\u5207\u6362", {
@@ -1348,18 +1397,18 @@ var GraphExecutor = class {
1348
1397
  });
1349
1398
  const nodeRunStartedAt = Date.now();
1350
1399
  const nodeIdForTelemetry = state.nodeId;
1400
+ const conversationIdForTelemetry = readRuntimeConversationId(state);
1351
1401
  let result;
1352
1402
  try {
1353
1403
  result = await node.run(state);
1354
1404
  } finally {
1355
- const turnIdForTelemetry = typeof state.local?.turnId === "string" ? state.local.turnId : void 0;
1356
1405
  this.telemetryPort.emit({
1357
1406
  kind: "graph_node",
1358
1407
  nodeId: nodeIdForTelemetry,
1359
1408
  durationMs: Date.now() - nodeRunStartedAt,
1360
1409
  scope: {
1361
- conversationId: conversationId || void 0,
1362
- turnId: turnIdForTelemetry
1410
+ conversationId: conversationIdForTelemetry,
1411
+ turnId: readRuntimeTurnId(state)
1363
1412
  }
1364
1413
  });
1365
1414
  }
@@ -1398,7 +1447,7 @@ var GraphExecutor = class {
1398
1447
  });
1399
1448
  state = { ...state, nodeId: nextNodeId };
1400
1449
  const cp2 = this.sanitize(state);
1401
- await this.checkpointer.save(conversationId, cp2);
1450
+ await this.checkpointer.save(checkpointKey, cp2);
1402
1451
  continue;
1403
1452
  }
1404
1453
  if (result.kind === "yield") {
@@ -1409,7 +1458,7 @@ var GraphExecutor = class {
1409
1458
  checkpointCount
1410
1459
  });
1411
1460
  const cp2 = this.sanitize(state);
1412
- await this.checkpointer.save(conversationId, cp2);
1461
+ await this.checkpointer.save(checkpointKey, cp2);
1413
1462
  return { events: allEvents, checkpoint: cp2, stepCount };
1414
1463
  }
1415
1464
  if (result.kind === "pause") {
@@ -1420,7 +1469,7 @@ var GraphExecutor = class {
1420
1469
  checkpointCount
1421
1470
  });
1422
1471
  const cp2 = this.sanitize(state);
1423
- await this.checkpointer.save(conversationId, cp2);
1472
+ await this.checkpointer.save(checkpointKey, cp2);
1424
1473
  return { events: allEvents, checkpoint: cp2, stepCount };
1425
1474
  }
1426
1475
  }
@@ -1431,8 +1480,8 @@ var GraphExecutor = class {
1431
1480
  checkpointCount
1432
1481
  });
1433
1482
  const cp = this.sanitize(state);
1434
- await this.checkpointer.save(conversationId, cp);
1435
- this.ephemeralLocals.delete(conversationId);
1483
+ await this.checkpointer.save(checkpointKey, cp);
1484
+ this.ephemeralLocals.delete(checkpointKey);
1436
1485
  return { events: allEvents, checkpoint: cp, stepCount };
1437
1486
  }
1438
1487
  };
@@ -1629,15 +1678,15 @@ function splitConcatenatedJsonObjects(input) {
1629
1678
  }
1630
1679
 
1631
1680
  // src/runtime-kernel/graph-engine/tick-pipeline/helpers.ts
1632
- function readNonEmptyString(value) {
1681
+ function readNonEmptyString2(value) {
1633
1682
  if (typeof value !== "string") return void 0;
1634
1683
  const trimmed = value.trim();
1635
1684
  return trimmed.length > 0 ? trimmed : void 0;
1636
1685
  }
1637
1686
  function resolveConversationIdForRuntimeEvents(toolContext) {
1638
- const fromCamel = readNonEmptyString(toolContext?.conversationId);
1687
+ const fromCamel = readNonEmptyString2(toolContext?.conversationId);
1639
1688
  if (fromCamel) return fromCamel;
1640
- const fromSnake = toolContext ? readNonEmptyString(toolContext["conversation_id"]) : void 0;
1689
+ const fromSnake = toolContext ? readNonEmptyString2(toolContext["conversation_id"]) : void 0;
1641
1690
  if (fromSnake) return fromSnake;
1642
1691
  return generateMessageId();
1643
1692
  }
@@ -1996,7 +2045,7 @@ var runModelLockMiddleware = async (ctx, stage, next) => {
1996
2045
  if (stage.id !== "execute_llm") {
1997
2046
  return;
1998
2047
  }
1999
- const normalized = readNonEmptyString(ctx.cloudQuotaFallbackAppliedModelId);
2048
+ const normalized = readNonEmptyString2(ctx.cloudQuotaFallbackAppliedModelId);
2000
2049
  if (!normalized) {
2001
2050
  return;
2002
2051
  }
@@ -2597,7 +2646,7 @@ function createExecuteLlmStage(dependencies) {
2597
2646
  streamEventHandler,
2598
2647
  ctx.signal,
2599
2648
  (fallbackModelId) => {
2600
- ctx.cloudQuotaFallbackAppliedModelId = readNonEmptyString(fallbackModelId);
2649
+ ctx.cloudQuotaFallbackAppliedModelId = readNonEmptyString2(fallbackModelId);
2601
2650
  },
2602
2651
  (info) => {
2603
2652
  ctx.modelFallbackAudit = info;
@@ -2641,7 +2690,7 @@ function createPrepareCallStage(dependencies) {
2641
2690
  return {
2642
2691
  id: "prepare_call",
2643
2692
  async run(ctx) {
2644
- const lockedRunModelId = readNonEmptyString(ctx.executorLocal?.runLockedModelId);
2693
+ const lockedRunModelId = readNonEmptyString2(ctx.executorLocal?.runLockedModelId);
2645
2694
  const requestedModelId = lockedRunModelId ?? ctx.request.model_id;
2646
2695
  ctx.modelId = dependencies.modelResolver.resolveModelId(requestedModelId);
2647
2696
  await emitAuditEnvelope(ctx.audit, {
@@ -2713,7 +2762,7 @@ var GraphAgentExecutor = class {
2713
2762
  this.llmCaller = dependencies.llmCaller;
2714
2763
  this.toolRuntime = dependencies.toolRuntime;
2715
2764
  this.contextBuilder = dependencies.contextBuilder;
2716
- this.cloudQuotaFallbackModelId = readNonEmptyString(dependencies.cloudQuotaFallbackModelId);
2765
+ this.cloudQuotaFallbackModelId = readNonEmptyString2(dependencies.cloudQuotaFallbackModelId);
2717
2766
  this.modelCatalog = dependencies.modelCatalog ?? createEmptyModelCatalog();
2718
2767
  this.modelResolver = dependencies.modelResolver ?? new ModelResolver({
2719
2768
  modelCatalog: this.modelCatalog
@@ -2761,7 +2810,7 @@ var GraphAgentExecutor = class {
2761
2810
  llmMessages: [],
2762
2811
  mode: input.request.mode === "chat" ? "chat" : "agent",
2763
2812
  conversationId: resolveConversationIdForRuntimeEvents(input.toolContext),
2764
- turnId: readNonEmptyString(input.toolContext?.turnId) ?? `turn_${Date.now()}`,
2813
+ turnId: readNonEmptyString2(input.toolContext?.turnId) ?? `turn_${Date.now()}`,
2765
2814
  telemetry: this.telemetryPort,
2766
2815
  audit: this.auditPort
2767
2816
  };
@@ -2811,18 +2860,18 @@ function isSummarizationCallbacks(value) {
2811
2860
  function isGraphSseSink(value) {
2812
2861
  return typeof value === "function";
2813
2862
  }
2814
- function readNonEmptyString2(value) {
2863
+ function readNonEmptyString3(value) {
2815
2864
  if (typeof value !== "string") return void 0;
2816
2865
  const trimmed = value.trim();
2817
2866
  return trimmed.length > 0 ? trimmed : void 0;
2818
2867
  }
2819
2868
  function readGraphAgentLocal(local) {
2820
2869
  const source = local ?? {};
2821
- const answerId = readNonEmptyString2(source.answerId);
2870
+ const answerId = readNonEmptyString3(source.answerId);
2822
2871
  const chunkSeq = Number.isInteger(source.chunkSeq) ? Number(source.chunkSeq) : 0;
2823
2872
  return {
2824
- conversationId: readNonEmptyString2(source.conversationId) ?? "",
2825
- turnId: readNonEmptyString2(source.turnId),
2873
+ conversationId: readNonEmptyString3(source.conversationId) ?? "",
2874
+ turnId: readNonEmptyString3(source.turnId),
2826
2875
  request: isAgentInvocationRequest(source.request) ? source.request : void 0,
2827
2876
  toolContext: isToolExecutionContext(source.toolContext) ? source.toolContext : void 0,
2828
2877
  history: isRuntimeEventArray(source.history) ? source.history : [],
@@ -3587,7 +3636,7 @@ var LlmNode = class {
3587
3636
  function isRecord8(value) {
3588
3637
  return typeof value === "object" && value !== null && !Array.isArray(value);
3589
3638
  }
3590
- function readNonEmptyString3(value) {
3639
+ function readNonEmptyString4(value) {
3591
3640
  if (typeof value !== "string") {
3592
3641
  return void 0;
3593
3642
  }
@@ -3609,7 +3658,7 @@ function resolveFinalAnswerFromToolResult(toolName, parsedResult) {
3609
3658
  return void 0;
3610
3659
  }
3611
3660
  if (toolName === "write_report") {
3612
- const report = readNonEmptyString3(data.report);
3661
+ const report = readNonEmptyString4(data.report);
3613
3662
  if (!report) {
3614
3663
  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");
3615
3664
  }
@@ -3619,7 +3668,7 @@ function resolveFinalAnswerFromToolResult(toolName, parsedResult) {
3619
3668
  if (data.success !== true) {
3620
3669
  return void 0;
3621
3670
  }
3622
- const finalAnswer = readNonEmptyString3(data.final_answer);
3671
+ const finalAnswer = readNonEmptyString4(data.final_answer);
3623
3672
  if (!finalAnswer) {
3624
3673
  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");
3625
3674
  }
@@ -4164,6 +4213,31 @@ function ensureToolContextRuntimeCapability(params) {
4164
4213
  function getToolContextRuntimeBinding(context) {
4165
4214
  return readBinding(context);
4166
4215
  }
4216
+ function copyToolContextRuntimeCapability(source, target) {
4217
+ const sourceBinding = readBinding(source);
4218
+ if (!sourceBinding) {
4219
+ return void 0;
4220
+ }
4221
+ const existingTargetBinding = readBinding(target);
4222
+ if (existingTargetBinding) {
4223
+ exposeCompatibilitySurface(target, existingTargetBinding);
4224
+ return existingTargetBinding;
4225
+ }
4226
+ const targetBinding = createRuntimeBinding({
4227
+ context: target,
4228
+ persistedHistory: () => sourceBinding.getPersistedHistoryEvents(),
4229
+ workingHistory: () => sourceBinding.getWorkingHistoryEvents(),
4230
+ executionMeta: sourceBinding.readExecutionMeta()
4231
+ });
4232
+ Object.defineProperty(target, TOOL_CONTEXT_RUNTIME_BINDING_KEY, {
4233
+ value: targetBinding,
4234
+ enumerable: false,
4235
+ configurable: true,
4236
+ writable: false
4237
+ });
4238
+ exposeCompatibilitySurface(target, targetBinding);
4239
+ return targetBinding;
4240
+ }
4167
4241
  function readToolContextWorkingHistory(context) {
4168
4242
  if (context.conversationView) {
4169
4243
  return context.conversationView.getWorkingHistoryEvents();
@@ -4577,6 +4651,22 @@ var ToolNode = class {
4577
4651
  });
4578
4652
  }
4579
4653
  async run(state) {
4654
+ const events = [];
4655
+ while (true) {
4656
+ const result = await this.runNextPendingToolCall(state);
4657
+ if (Array.isArray(result.events) && result.events.length > 0) {
4658
+ events.push(...result.events);
4659
+ }
4660
+ if (result.kind === "route" && result.nextNodeId === "tool") {
4661
+ continue;
4662
+ }
4663
+ return {
4664
+ ...result,
4665
+ events
4666
+ };
4667
+ }
4668
+ }
4669
+ async runNextPendingToolCall(state) {
4580
4670
  const calls = state.local?.pendingToolCalls ?? [];
4581
4671
  const signalRaw = state.local?.signal;
4582
4672
  if (isAbortSignal(signalRaw) && signalRaw.aborted) {
@@ -4784,18 +4874,25 @@ var ToolNode = class {
4784
4874
  rawArguments: context.call.function?.arguments,
4785
4875
  parsedArguments: context.toolArgs
4786
4876
  });
4877
+ const remainingCalls = context.calls.slice(1);
4787
4878
  context.state.local = buildErrorLocalState({
4788
4879
  local: context.local,
4789
- remainingCalls: context.calls.slice(1),
4880
+ remainingCalls,
4790
4881
  conversationId: context.conversationId,
4791
4882
  turnId: context.turnId,
4792
4883
  runtimeEvents: context.bridge.getRuntimeEvents(),
4793
4884
  nextProtocolErrorCount: fuse.nextCount
4794
4885
  });
4795
- if (fuse.shouldFuse) {
4886
+ if (fuse.shouldFuse && remainingCalls.length === 0) {
4796
4887
  throw createToolProtocolFuseError(fuse.nextCount, context.exec.error);
4797
4888
  }
4798
- return { kind: "route", nextNodeId: "llm", events: context.bridge.getRuntimeEvents() };
4889
+ return {
4890
+ kind: "route",
4891
+ // 同一个 assistant.tool_calls batch 必须为每个 call 产出 tool_output。
4892
+ // 出错时也继续消费剩余 call,ToolNode.run 会在本节点内 drain 完 batch 再回 LLM。
4893
+ nextNodeId: remainingCalls.length > 0 ? "tool" : "llm",
4894
+ events: context.bridge.getRuntimeEvents()
4895
+ };
4799
4896
  }
4800
4897
  };
4801
4898
 
@@ -4992,12 +5089,12 @@ function asRecord(value) {
4992
5089
  }
4993
5090
  return value;
4994
5091
  }
4995
- function summarizeCheckpoint(conversationId, state, savedAt) {
5092
+ function summarizeCheckpoint(checkpointKey, state, savedAt) {
4996
5093
  const local = asRecord(state.local);
4997
5094
  const executorLocal = asRecord(local?.executorLocal);
4998
5095
  const pendingToolCalls = local?.pendingToolCalls;
4999
5096
  return {
5000
- conversationId,
5097
+ checkpointKey,
5001
5098
  schemaVersion: state.schemaVersion ?? 1,
5002
5099
  savedAt,
5003
5100
  currentNode: state.nodeId,
@@ -5016,25 +5113,25 @@ var MemoryCheckpointer = class {
5016
5113
  local: state.local && typeof state.local === "object" && !Array.isArray(state.local) ? { ...state.local } : state.local
5017
5114
  };
5018
5115
  }
5019
- async load(conversationId) {
5020
- const entry = this.store.get(conversationId);
5116
+ async load(checkpointKey) {
5117
+ const entry = this.store.get(checkpointKey);
5021
5118
  return entry ? this.cloneState(entry.state) : null;
5022
5119
  }
5023
- async save(conversationId, state) {
5024
- this.store.set(conversationId, {
5120
+ async save(checkpointKey, state) {
5121
+ this.store.set(checkpointKey, {
5025
5122
  state: this.cloneState(state),
5026
5123
  savedAt: Date.now()
5027
5124
  });
5028
5125
  }
5029
- async clear(conversationId) {
5030
- this.store.delete(conversationId);
5126
+ async clear(checkpointKey) {
5127
+ this.store.delete(checkpointKey);
5031
5128
  }
5032
- async peekMeta(conversationId) {
5033
- const entry = this.store.get(conversationId);
5034
- return entry ? summarizeCheckpoint(conversationId, entry.state, entry.savedAt) : null;
5129
+ async peekMeta(checkpointKey) {
5130
+ const entry = this.store.get(checkpointKey);
5131
+ return entry ? summarizeCheckpoint(checkpointKey, entry.state, entry.savedAt) : null;
5035
5132
  }
5036
5133
  async list(filter = {}) {
5037
- 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);
5134
+ 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);
5038
5135
  if (filter.limit === void 0) {
5039
5136
  return summaries;
5040
5137
  }
@@ -5106,6 +5203,7 @@ __export(tools_exports, {
5106
5203
  CommonParameterTypes: () => CommonParameterTypes,
5107
5204
  ContextCheckpointTool: () => ContextCheckpointTool,
5108
5205
  computeToolIdempotencyKey: () => computeToolIdempotencyKey,
5206
+ copyToolContextRuntimeCapability: () => copyToolContextRuntimeCapability,
5109
5207
  createContextCheckpointTool: () => createContextCheckpointTool,
5110
5208
  ensureToolContextRuntimeCapability: () => ensureToolContextRuntimeCapability,
5111
5209
  findCachedToolOutputByIdempotencyKey: () => findCachedToolOutputByIdempotencyKey,
@@ -5299,7 +5397,7 @@ function createContextCheckpointTool(options) {
5299
5397
  function isRecord15(value) {
5300
5398
  return !!value && typeof value === "object" && !Array.isArray(value);
5301
5399
  }
5302
- function readNonEmptyString4(value) {
5400
+ function readNonEmptyString5(value) {
5303
5401
  if (typeof value !== "string") {
5304
5402
  return void 0;
5305
5403
  }
@@ -5319,13 +5417,13 @@ function readToolContextUserQuery(context) {
5319
5417
  if (!context) {
5320
5418
  return void 0;
5321
5419
  }
5322
- return readNonEmptyString4(context["user_query"]);
5420
+ return readNonEmptyString5(context["user_query"]);
5323
5421
  }
5324
5422
  function readToolContextModelId(context) {
5325
5423
  if (!context) {
5326
5424
  return void 0;
5327
5425
  }
5328
- return readNonEmptyString4(context["modelId"]);
5426
+ return readNonEmptyString5(context["modelId"]);
5329
5427
  }
5330
5428
  function readToolContextRunContext(context) {
5331
5429
  if (!context) {
@@ -5532,18 +5630,18 @@ function createClassification(category, reason, suggestedDelay, extras) {
5532
5630
  }
5533
5631
  var ErrorClassifier = class {
5534
5632
  static classify(error, context) {
5535
- const isRecord26 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
5633
+ const isRecord27 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
5536
5634
  const baseMsg = (error.message || "").toLowerCase();
5537
5635
  const causeMsg = (() => {
5538
5636
  const cause = error.cause;
5539
5637
  if (typeof cause === "string") return cause.toLowerCase();
5540
5638
  if (cause instanceof Error) return (cause.message || "").toLowerCase();
5541
- if (isRecord26(cause) && typeof cause["message"] === "string") return String(cause["message"]).toLowerCase();
5639
+ if (isRecord27(cause) && typeof cause["message"] === "string") return String(cause["message"]).toLowerCase();
5542
5640
  return "";
5543
5641
  })();
5544
5642
  const causeCode = (() => {
5545
5643
  const cause = error.cause;
5546
- if (isRecord26(cause) && typeof cause["code"] === "string") return String(cause["code"]);
5644
+ if (isRecord27(cause) && typeof cause["code"] === "string") return String(cause["code"]);
5547
5645
  return "";
5548
5646
  })();
5549
5647
  const errorMessage = `${baseMsg} ${causeMsg}`.trim();
@@ -6035,6 +6133,9 @@ __export(llm_exports, {
6035
6133
  LLMPolicyEngine: () => LLMPolicyEngine,
6036
6134
  LlmCaller: () => LlmCaller,
6037
6135
  ModelResolver: () => ModelResolver,
6136
+ appendStreamingProviderReasoningDetails: () => appendStreamingProviderReasoningDetails,
6137
+ compactProviderReasoningDetails: () => compactProviderReasoningDetails,
6138
+ compactReasoningDetailsInValue: () => compactReasoningDetailsInValue,
6038
6139
  createDefaultTokenizerPort: () => createDefaultTokenizerPort,
6039
6140
  defaultPolicyEngine: () => defaultPolicyEngine
6040
6141
  });
@@ -6424,6 +6525,90 @@ function assertToolCallsHaveValidJsonArguments(toolCalls) {
6424
6525
  }
6425
6526
  }
6426
6527
 
6528
+ // src/runtime-kernel/llm/reasoning-details.ts
6529
+ var mergeableTextFields = ["reasoning_content"];
6530
+ function isRecord20(value) {
6531
+ return !!value && typeof value === "object" && !Array.isArray(value);
6532
+ }
6533
+ function findMergeableTextField(detail) {
6534
+ if (!isRecord20(detail)) return void 0;
6535
+ if (typeof detail.provider !== "string") return void 0;
6536
+ if (typeof detail.type !== "string") return void 0;
6537
+ for (const field of mergeableTextFields) {
6538
+ if (typeof detail[field] === "string") {
6539
+ return field;
6540
+ }
6541
+ }
6542
+ return void 0;
6543
+ }
6544
+ function hasOnlyStableTextDetailFields(detail, textField) {
6545
+ const allowedKeys = /* @__PURE__ */ new Set(["provider", "type", textField]);
6546
+ return Object.keys(detail).every((key) => allowedKeys.has(key));
6547
+ }
6548
+ function canMergeTextDetails(previous, incoming) {
6549
+ if (!isRecord20(previous) || !isRecord20(incoming)) return false;
6550
+ const previousField = findMergeableTextField(previous);
6551
+ const incomingField = findMergeableTextField(incoming);
6552
+ if (!previousField || previousField !== incomingField) return false;
6553
+ return previous.provider === incoming.provider && previous.type === incoming.type && hasOnlyStableTextDetailFields(previous, previousField) && hasOnlyStableTextDetailFields(incoming, incomingField);
6554
+ }
6555
+ function mergeStreamingText(previous, incoming) {
6556
+ if (!previous) return incoming;
6557
+ if (!incoming) return previous;
6558
+ if (incoming.startsWith(previous)) {
6559
+ return incoming;
6560
+ }
6561
+ if (previous.endsWith(incoming)) {
6562
+ return previous;
6563
+ }
6564
+ return `${previous}${incoming}`;
6565
+ }
6566
+ function appendStreamingProviderReasoningDetails(existing, incoming) {
6567
+ const next = [...existing];
6568
+ for (const detail of incoming) {
6569
+ const previous = next[next.length - 1];
6570
+ if (canMergeTextDetails(previous, detail)) {
6571
+ const textField = findMergeableTextField(previous);
6572
+ if (textField && isRecord20(detail)) {
6573
+ const mergedText = mergeStreamingText(String(previous[textField]), String(detail[textField]));
6574
+ if (mergedText === previous[textField]) {
6575
+ continue;
6576
+ }
6577
+ next[next.length - 1] = {
6578
+ ...previous,
6579
+ [textField]: mergedText
6580
+ };
6581
+ continue;
6582
+ }
6583
+ }
6584
+ next.push(detail);
6585
+ }
6586
+ return next;
6587
+ }
6588
+ function compactProviderReasoningDetails(reasoningDetails) {
6589
+ return appendStreamingProviderReasoningDetails([], reasoningDetails);
6590
+ }
6591
+ function compactReasoningDetailsInValue(value) {
6592
+ return compactValue(value);
6593
+ }
6594
+ function compactValue(value) {
6595
+ if (Array.isArray(value)) {
6596
+ return value.map((item) => compactValue(item));
6597
+ }
6598
+ if (!isRecord20(value)) {
6599
+ return value;
6600
+ }
6601
+ const compacted = {};
6602
+ for (const [key, childValue] of Object.entries(value)) {
6603
+ if (key === "reasoning_details" && Array.isArray(childValue)) {
6604
+ compacted[key] = compactProviderReasoningDetails(childValue);
6605
+ continue;
6606
+ }
6607
+ compacted[key] = compactValue(childValue);
6608
+ }
6609
+ return compacted;
6610
+ }
6611
+
6427
6612
  // src/runtime-kernel/llm/streaming-adapter.ts
6428
6613
  async function callLlmStream(params) {
6429
6614
  const {
@@ -6436,7 +6621,7 @@ async function callLlmStream(params) {
6436
6621
  } = params;
6437
6622
  let fullResponse = "";
6438
6623
  let streamError = null;
6439
- const reasoningDetails = [];
6624
+ let reasoningDetails = [];
6440
6625
  const streamAnswerId = generateMessageId();
6441
6626
  let streamChunkSeq = 0;
6442
6627
  let capturedUsage = void 0;
@@ -6506,13 +6691,21 @@ async function callLlmStream(params) {
6506
6691
  const reasoning = isRecord19(chunk) ? chunk["reasoning_details"] : void 0;
6507
6692
  if (reasoning !== void 0) {
6508
6693
  const newReasoningDetails = Array.isArray(reasoning) ? reasoning : [reasoning];
6509
- reasoningDetails.push(...newReasoningDetails);
6510
- eventHandler({
6511
- type: "provider_sidecar",
6512
- id: generateMessageId(),
6513
- timestamp: Date.now(),
6514
- reasoning_details: newReasoningDetails
6515
- });
6694
+ const previousReasoningDetails = reasoningDetails;
6695
+ const previousLength = previousReasoningDetails.length;
6696
+ const compactedReasoningDetails = appendStreamingProviderReasoningDetails(reasoningDetails, newReasoningDetails);
6697
+ reasoningDetails = compactedReasoningDetails;
6698
+ const previousLastChanged = previousLength > 0 && compactedReasoningDetails[previousLength - 1] !== previousReasoningDetails[previousLength - 1];
6699
+ const emitFromIndex = previousLastChanged ? previousLength - 1 : previousLength;
6700
+ const emittedReasoningDetails = compactedReasoningDetails.slice(Math.max(0, emitFromIndex));
6701
+ if (emittedReasoningDetails.length > 0) {
6702
+ eventHandler({
6703
+ type: "provider_sidecar",
6704
+ id: generateMessageId(),
6705
+ timestamp: Date.now(),
6706
+ reasoning_details: emittedReasoningDetails
6707
+ });
6708
+ }
6516
6709
  }
6517
6710
  if (chunk.tool_calls) {
6518
6711
  emitThoughtComplete(thoughtSegmenter.onBoundary());
@@ -6966,7 +7159,6 @@ __export(child_runs_exports, {
6966
7159
 
6967
7160
  // src/runtime-kernel/child-runs/childToolContext.ts
6968
7161
  function createChildRunToolContext(params) {
6969
- const inheritedConversationId = typeof params.parentToolContext.conversationId === "string" && params.parentToolContext.conversationId.trim().length > 0 ? params.parentToolContext.conversationId.trim() : void 0;
6970
7162
  const inheritedContext = stripRuntimeReservedToolContextPatch(params.parentToolContext);
6971
7163
  const childToolContext = {
6972
7164
  ...inheritedContext,
@@ -6978,7 +7170,7 @@ function createChildRunToolContext(params) {
6978
7170
  persistedHistory: params.seedHistory,
6979
7171
  workingHistory: params.seedHistory,
6980
7172
  executionMeta: {
6981
- conversationId: inheritedConversationId ?? params.internalConversationId,
7173
+ conversationId: params.conversationId,
6982
7174
  turnId: params.turnId,
6983
7175
  runId: params.runId,
6984
7176
  parentRunId: params.parentRunId
@@ -7129,7 +7321,7 @@ var FinalAnswerCollector = class {
7129
7321
  };
7130
7322
 
7131
7323
  // src/runtime-kernel/child-runs/childRunTraceSink.ts
7132
- function isRecord20(v) {
7324
+ function isRecord21(v) {
7133
7325
  return !!v && typeof v === "object" && !Array.isArray(v);
7134
7326
  }
7135
7327
  function getString2(obj, key) {
@@ -7162,7 +7354,7 @@ function createChildRunTraceSink(params) {
7162
7354
  const { publisher, conversationId, turnId } = params;
7163
7355
  const finalAnswerCollector = new FinalAnswerCollector(conversationId, turnId);
7164
7356
  const sink = (evt) => {
7165
- if (!isRecord20(evt)) {
7357
+ if (!isRecord21(evt)) {
7166
7358
  return [];
7167
7359
  }
7168
7360
  const type = getString2(evt, "type");
@@ -7298,7 +7490,7 @@ function readCheckpointHistory(checkpoint) {
7298
7490
  });
7299
7491
  }
7300
7492
  async function recoverChildRunEventsFromCheckpoint(params) {
7301
- const checkpoint = await params.checkpointer.load(params.conversationId);
7493
+ const checkpoint = await params.checkpointer.load(params.checkpointKey);
7302
7494
  const history = readCheckpointHistory(checkpoint);
7303
7495
  if (history.length === 0) {
7304
7496
  return [];
@@ -7306,7 +7498,7 @@ async function recoverChildRunEventsFromCheckpoint(params) {
7306
7498
  if (hasSeedHistoryPrefix(history, params.seedHistory)) {
7307
7499
  return history.slice(params.seedHistory.length);
7308
7500
  }
7309
- return history.filter((event) => event.conversation_id === params.internalConversationId);
7501
+ return history.filter((event) => event.conversation_id === params.childConversationId);
7310
7502
  }
7311
7503
 
7312
7504
  // src/runtime-kernel/child-runs/childRunInvoker.ts
@@ -7335,6 +7527,7 @@ var ChildRunInvoker = class {
7335
7527
  agentConfig,
7336
7528
  userMessage,
7337
7529
  parentToolContext,
7530
+ conversationId,
7338
7531
  runId,
7339
7532
  parentRunId,
7340
7533
  subrunTracePublisher,
@@ -7343,12 +7536,18 @@ var ChildRunInvoker = class {
7343
7536
  modelId,
7344
7537
  abortSignal
7345
7538
  } = config;
7346
- const internalConversationId = `internal_${generateMessageId()}`;
7539
+ const internalCheckpointKey = `internal_${generateMessageId()}`;
7540
+ const runtimeConversationId = resolveChildRunConversationId({
7541
+ explicitConversationId: conversationId,
7542
+ parentToolContext,
7543
+ fallbackConversationId: internalCheckpointKey
7544
+ });
7347
7545
  const turnId = `turn_${Date.now()}`;
7348
- const childRunId = typeof runId === "string" && runId.trim().length > 0 ? runId.trim() : internalConversationId;
7546
+ const childRunId = typeof runId === "string" && runId.trim().length > 0 ? runId.trim() : internalCheckpointKey;
7349
7547
  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;
7350
7548
  logger13.info(`\u542F\u52A8 child-run: ${agentConfig.id}`, {
7351
- conversationId: internalConversationId,
7549
+ conversationId: runtimeConversationId,
7550
+ checkpointKey: internalCheckpointKey,
7352
7551
  maxSteps,
7353
7552
  userMessage: userMessage.slice(0, 100) + (userMessage.length > 100 ? "..." : "")
7354
7553
  });
@@ -7409,7 +7608,7 @@ var ChildRunInvoker = class {
7409
7608
  const seedHistory = Array.isArray(seedHistoryEvents) ? seedHistoryEvents : [];
7410
7609
  const childToolContext = createChildRunToolContext({
7411
7610
  parentToolContext,
7412
- internalConversationId,
7611
+ conversationId: runtimeConversationId,
7413
7612
  turnId,
7414
7613
  runId: childRunId,
7415
7614
  parentRunId: resolvedParentRunId,
@@ -7418,13 +7617,13 @@ var ChildRunInvoker = class {
7418
7617
  });
7419
7618
  const subrunSseSink = subrunTracePublisher ? createChildRunTraceSink({
7420
7619
  publisher: subrunTracePublisher,
7421
- conversationId: internalConversationId,
7620
+ conversationId: runtimeConversationId,
7422
7621
  turnId
7423
7622
  }) : void 0;
7424
7623
  const initialLocal = {
7425
7624
  request,
7426
7625
  history: seedHistory,
7427
- conversationId: internalConversationId,
7626
+ conversationId: runtimeConversationId,
7428
7627
  turnId,
7429
7628
  toolContext: childToolContext,
7430
7629
  ...abortSignal ? { signal: abortSignal } : {},
@@ -7432,7 +7631,7 @@ var ChildRunInvoker = class {
7432
7631
  ...subrunSseSink ? { sseSink: subrunSseSink } : {},
7433
7632
  systemPrompt
7434
7633
  };
7435
- await graphExecutor.prime(internalConversationId, initialLocal, "llm");
7634
+ await graphExecutor.prime(internalCheckpointKey, initialLocal, "llm");
7436
7635
  const allEvents = [];
7437
7636
  let stepCount = 0;
7438
7637
  let finalAnswer;
@@ -7444,7 +7643,7 @@ var ChildRunInvoker = class {
7444
7643
  err.name = "AbortError";
7445
7644
  throw err;
7446
7645
  }
7447
- const result = await graphExecutor.runUntilYield(internalConversationId);
7646
+ const result = await graphExecutor.runUntilYield(internalCheckpointKey);
7448
7647
  appendUniqueEvents(allEvents, result.events);
7449
7648
  stepCount = result.stepCount;
7450
7649
  if (subrunSseSink && typeof subrunSseSink.finalize === "function") {
@@ -7478,8 +7677,8 @@ var ChildRunInvoker = class {
7478
7677
  }
7479
7678
  const recoveredEvents = await recoverChildRunEventsFromCheckpoint({
7480
7679
  checkpointer,
7481
- conversationId: internalConversationId,
7482
- internalConversationId,
7680
+ checkpointKey: internalCheckpointKey,
7681
+ childConversationId: runtimeConversationId,
7483
7682
  seedHistory
7484
7683
  });
7485
7684
  appendUniqueEvents(allEvents, recoveredEvents);
@@ -7496,7 +7695,7 @@ var ChildRunInvoker = class {
7496
7695
  stack: err.stack
7497
7696
  } : { error: String(err) });
7498
7697
  }
7499
- await checkpointer.clear(internalConversationId);
7698
+ await checkpointer.clear(internalCheckpointKey);
7500
7699
  return {
7501
7700
  success: !error,
7502
7701
  runId: childRunId,
@@ -7509,6 +7708,16 @@ var ChildRunInvoker = class {
7509
7708
  };
7510
7709
  }
7511
7710
  };
7711
+ function readNonEmptyString6(value) {
7712
+ if (typeof value !== "string") {
7713
+ return void 0;
7714
+ }
7715
+ const trimmed = value.trim();
7716
+ return trimmed.length > 0 ? trimmed : void 0;
7717
+ }
7718
+ function resolveChildRunConversationId(params) {
7719
+ return readNonEmptyString6(params.explicitConversationId) ?? readNonEmptyString6(params.parentToolContext.conversationId) ?? params.fallbackConversationId;
7720
+ }
7512
7721
  function resolveChildRunSystemReminderPolicy(agentConfig) {
7513
7722
  const configured = agentConfig.systemReminderPolicy ?? agentConfig.contextPolicy?.systemReminder;
7514
7723
  const threshold = agentConfig.stepPolicy?.lastStepsHintThreshold;
@@ -7699,7 +7908,7 @@ function cloneRunRecord(record) {
7699
7908
  ...record,
7700
7909
  iterationBudget: record.iterationBudget ? { ...record.iterationBudget } : void 0,
7701
7910
  errorIfAny: record.errorIfAny ? { ...record.errorIfAny } : void 0,
7702
- metadata: record.metadata ? { ...record.metadata } : void 0
7911
+ metadata: record.metadata ? structuredClone(record.metadata) : void 0
7703
7912
  };
7704
7913
  }
7705
7914
  function matchesStatus(candidate, filter) {
@@ -7831,7 +8040,7 @@ function runRecordToMeta(record) {
7831
8040
  errorIfAny: record.errorIfAny ? { ...record.errorIfAny } : void 0
7832
8041
  };
7833
8042
  }
7834
- function isRecord21(value) {
8043
+ function isRecord22(value) {
7835
8044
  return typeof value === "object" && value !== null && !Array.isArray(value);
7836
8045
  }
7837
8046
  function readStringField(record, key) {
@@ -7852,7 +8061,7 @@ function getRunIdFromMetadata(event) {
7852
8061
  return snakeCaseRunId;
7853
8062
  }
7854
8063
  const runContext = metadata["run_context"];
7855
- if (isRecord21(runContext)) {
8064
+ if (isRecord22(runContext)) {
7856
8065
  return readStringField(runContext, "runId") ?? readStringField(runContext, "run_id");
7857
8066
  }
7858
8067
  return void 0;
@@ -8070,7 +8279,7 @@ function runMetaFromRecord(record) {
8070
8279
  }
8071
8280
 
8072
8281
  // src/runtime-kernel/run-supervisor/runSupervisor.ts
8073
- function isRecord22(value) {
8282
+ function isRecord23(value) {
8074
8283
  return typeof value === "object" && value !== null && !Array.isArray(value);
8075
8284
  }
8076
8285
  function readStringField2(record, key) {
@@ -8087,7 +8296,7 @@ function readRunIdFromRuntimeEvent(event) {
8087
8296
  return directRunId;
8088
8297
  }
8089
8298
  const runContext = metadata["run_context"];
8090
- if (!isRecord22(runContext)) {
8299
+ if (!isRecord23(runContext)) {
8091
8300
  return void 0;
8092
8301
  }
8093
8302
  return readStringField2(runContext, "runId") ?? readStringField2(runContext, "run_id");
@@ -8099,7 +8308,7 @@ function readAwaitingUserReason(event) {
8099
8308
  if (typeof event.prompt === "string" && event.prompt.trim().length > 0) {
8100
8309
  return event.prompt;
8101
8310
  }
8102
- if (isRecord22(event.form)) {
8311
+ if (isRecord23(event.form)) {
8103
8312
  const prompt = readStringField2(event.form, "prompt");
8104
8313
  if (prompt && prompt.trim().length > 0) {
8105
8314
  return prompt;
@@ -8111,7 +8320,7 @@ function isTerminalStatus(status) {
8111
8320
  return status === "completed" || status === "failed" || status === "cancelled";
8112
8321
  }
8113
8322
  function cloneMetadata(metadata) {
8114
- return metadata ? { ...metadata } : void 0;
8323
+ return metadata ? structuredClone(metadata) : void 0;
8115
8324
  }
8116
8325
  function recordToSnapshot(record) {
8117
8326
  return {
@@ -8198,7 +8407,7 @@ var DefaultRunSupervisor = class {
8198
8407
  startedAt,
8199
8408
  updatedAt: startedAt,
8200
8409
  iterationBudget: spec.iterationBudget ? { ...spec.iterationBudget } : void 0,
8201
- metadata: spec.metadata ? { ...spec.metadata } : void 0
8410
+ metadata: cloneMetadata(spec.metadata)
8202
8411
  };
8203
8412
  await this.registryStore.save(record);
8204
8413
  const handle = new DefaultRunHandle({
@@ -8372,12 +8581,13 @@ var DefaultRunSupervisor = class {
8372
8581
  }
8373
8582
  try {
8374
8583
  await handle.markRunning({ currentNode: "detached" });
8584
+ const registeredRecord = await this.registryStore.load(handle.runId);
8375
8585
  const executorOutcome = await this.executor.execute({
8376
8586
  runId: handle.runId,
8377
- parentRunId: spec.parentRunId,
8378
- conversationId: spec.conversationId,
8379
- agentSpec: spec.agentSpec,
8380
- request: spec.request,
8587
+ parentRunId: handle.parentRunId,
8588
+ conversationId: registeredRecord?.conversationId ?? spec.conversationId,
8589
+ agentSpec: await handle.spec(),
8590
+ request: await handle.request(),
8381
8591
  signal: handle.signal,
8382
8592
  eventBus: spec.eventBus,
8383
8593
  eventStore: spec.eventStore,
@@ -8386,7 +8596,7 @@ var DefaultRunSupervisor = class {
8386
8596
  contextFences: spec.contextFences,
8387
8597
  wakeSource: spec.wakeSource,
8388
8598
  ephemeral: spec.ephemeral,
8389
- metadata: spec.metadata
8599
+ metadata: cloneMetadata(registeredRecord?.metadata ?? spec.metadata)
8390
8600
  });
8391
8601
  const outcome = await this.persistExecutorOutcome(handle, executorOutcome);
8392
8602
  this.notifyTerminalWaiters(outcome);
@@ -8450,10 +8660,14 @@ var DefaultRunSupervisor = class {
8450
8660
  await this.registryStore.save(record);
8451
8661
  }
8452
8662
  const completedAt = executorOutcome?.completedAt ?? this.now();
8663
+ const fallbackMeta = record ? void 0 : await handle.meta();
8453
8664
  const outcome = recordToTerminalOutcome(record ?? {
8454
8665
  runId: handle.runId,
8455
8666
  parentRunId: handle.parentRunId,
8456
- status: executorOutcome?.status ?? "completed"}, completedAt);
8667
+ conversationId: fallbackMeta?.conversationId ?? "",
8668
+ agentSpecId: fallbackMeta?.agentSpecId,
8669
+ status: executorOutcome?.status ?? "completed",
8670
+ startedAt: fallbackMeta?.startedAt ?? completedAt}, completedAt);
8457
8671
  const nextOutcome = {
8458
8672
  ...outcome,
8459
8673
  metadata: {
@@ -8681,6 +8895,7 @@ function createGraphLoopHarness(options) {
8681
8895
  };
8682
8896
  return {
8683
8897
  async run() {
8898
+ const checkpointKey = options.conversationId;
8684
8899
  const executor = createDefaultGraphExecutor({
8685
8900
  llmNode: options.createLlmNode({
8686
8901
  llmCaller: options.llmCaller,
@@ -8709,8 +8924,8 @@ function createGraphLoopHarness(options) {
8709
8924
  signal: options.signal ?? options.toolContext.abortSignal,
8710
8925
  executorLocal
8711
8926
  };
8712
- await executor.prime(options.conversationId, local, "user");
8713
- const result = await executor.runUntilYield(options.conversationId);
8927
+ await executor.prime(checkpointKey, local, "user");
8928
+ const result = await executor.runUntilYield(checkpointKey);
8714
8929
  return {
8715
8930
  checkpointNodeId: result.checkpoint.nodeId,
8716
8931
  stepCount: result.stepCount
@@ -8985,11 +9200,11 @@ new MessageFormatter();
8985
9200
 
8986
9201
  // src/context-manager/profiles/agent/utils/toolInteractionGroup.ts
8987
9202
  var CHECKPOINT_TOOL_NAME = "context_checkpoint";
8988
- function isRecord23(value) {
9203
+ function isRecord24(value) {
8989
9204
  return typeof value === "object" && value !== null && !Array.isArray(value);
8990
9205
  }
8991
9206
  function isToolCallRecord(value) {
8992
- if (!isRecord23(value)) {
9207
+ if (!isRecord24(value)) {
8993
9208
  return false;
8994
9209
  }
8995
9210
  return typeof value.id === "string" && value.id.trim().length > 0;
@@ -9007,7 +9222,7 @@ function safeParseArgs(rawArgs) {
9007
9222
  }
9008
9223
  try {
9009
9224
  const parsed = JSON.parse(rawArgs);
9010
- return isRecord23(parsed) ? parsed : {};
9225
+ return isRecord24(parsed) ? parsed : {};
9011
9226
  } catch {
9012
9227
  return {};
9013
9228
  }
@@ -9301,7 +9516,7 @@ var summarizeToolOutput = (toolName, output, toolSummaryProvider, toolArgs, conf
9301
9516
  };
9302
9517
 
9303
9518
  // src/context-manager/profiles/agent/utils/eventConverter.ts
9304
- function isRecord24(value) {
9519
+ function isRecord25(value) {
9305
9520
  return !!value && typeof value === "object" && !Array.isArray(value);
9306
9521
  }
9307
9522
  function isHistorySummaryEvent2(event) {
@@ -9359,10 +9574,10 @@ function convertEventToAiMessage(event) {
9359
9574
  timestamp: event.timestamp,
9360
9575
  metadata: {
9361
9576
  tool_calls: (() => {
9362
- const isRecord26 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
9577
+ const isRecord27 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
9363
9578
  const payload = event.payload;
9364
9579
  const toolCallsFromPayload = (() => {
9365
- if (!isRecord26(payload)) return void 0;
9580
+ if (!isRecord27(payload)) return void 0;
9366
9581
  const raw = payload["tool_calls"];
9367
9582
  return Array.isArray(raw) ? raw : void 0;
9368
9583
  })();
@@ -9381,9 +9596,9 @@ function convertEventToAiMessage(event) {
9381
9596
  ];
9382
9597
  })(),
9383
9598
  reasoning_details: (() => {
9384
- const isRecord26 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
9599
+ const isRecord27 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
9385
9600
  const payload = event.payload;
9386
- if (!isRecord26(payload)) return void 0;
9601
+ if (!isRecord27(payload)) return void 0;
9387
9602
  const rd = payload["reasoning_details"];
9388
9603
  return Array.isArray(rd) ? rd : void 0;
9389
9604
  })()
@@ -9392,15 +9607,15 @@ function convertEventToAiMessage(event) {
9392
9607
  case "tool_output": {
9393
9608
  const observationFromPayload = (() => {
9394
9609
  const payload = event.payload;
9395
- if (!isRecord24(payload)) return void 0;
9610
+ if (!isRecord25(payload)) return void 0;
9396
9611
  const result = payload["result"];
9397
- if (!isRecord24(result)) return void 0;
9612
+ if (!isRecord25(result)) return void 0;
9398
9613
  const obs = result["observation"];
9399
9614
  return typeof obs === "string" && obs.trim().length > 0 ? obs : void 0;
9400
9615
  })();
9401
9616
  const rawOutput = (() => {
9402
9617
  const payload = event.payload;
9403
- if (isRecord24(payload)) {
9618
+ if (isRecord25(payload)) {
9404
9619
  const out = payload["output"];
9405
9620
  if (typeof out === "string" && out.trim().length > 0) {
9406
9621
  return out;
@@ -9525,7 +9740,7 @@ __export(utils_exports, {
9525
9740
  });
9526
9741
 
9527
9742
  // src/testkit/context-harness/replayHarness.ts
9528
- function isRecord25(value) {
9743
+ function isRecord26(value) {
9529
9744
  return !!value && typeof value === "object" && !Array.isArray(value);
9530
9745
  }
9531
9746
  function createReplayHarness(events) {
@@ -9537,7 +9752,7 @@ function createReplayHarness(events) {
9537
9752
  if (message.role !== "assistant" || message.type !== "tool_calls") {
9538
9753
  return false;
9539
9754
  }
9540
- if (!isRecord25(message.metadata)) {
9755
+ if (!isRecord26(message.metadata)) {
9541
9756
  return false;
9542
9757
  }
9543
9758
  return Array.isArray(message.metadata.tool_calls);