@linnlabs/linnkit 0.9.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 (81) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/bin/linnkit.cjs +7 -0
  3. package/dist/{agentSpec-EkmviZjy.d.cts → agentSpec-Du4Iye0q.d.cts} +16 -1
  4. package/dist/{agentSpec-EkmviZjy.d.ts → agentSpec-Du4Iye0q.d.ts} +16 -1
  5. package/dist/cli.cjs +118 -65
  6. package/dist/cli.cjs.map +1 -1
  7. package/dist/cli.js +118 -65
  8. package/dist/cli.js.map +1 -1
  9. package/dist/context-manager.cjs +234 -32
  10. package/dist/context-manager.cjs.map +1 -1
  11. package/dist/context-manager.d.cts +52 -15
  12. package/dist/context-manager.d.ts +52 -15
  13. package/dist/context-manager.js +234 -33
  14. package/dist/context-manager.js.map +1 -1
  15. package/dist/{context-trace-HE2qY5Q-.d.cts → context-trace-BHKDS-eq.d.cts} +2 -2
  16. package/dist/{context-trace-DRi5M4lX.d.ts → context-trace-CHbqHmyE.d.ts} +2 -2
  17. package/dist/contracts.cjs +3 -1
  18. package/dist/contracts.cjs.map +1 -1
  19. package/dist/contracts.d.cts +3 -3
  20. package/dist/contracts.d.ts +3 -3
  21. package/dist/contracts.js +3 -1
  22. package/dist/contracts.js.map +1 -1
  23. package/dist/{defaultGraphExecutor-BBswR8wn.d.ts → defaultGraphExecutor-B29_qTHy.d.ts} +16 -15
  24. package/dist/{defaultGraphExecutor-BIjJj7WF.d.cts → defaultGraphExecutor-C2E59v_R.d.cts} +16 -15
  25. package/dist/{index-BanRABEt.d.cts → index-BAaUP9yU.d.cts} +26 -14
  26. package/dist/{index-Z8NXKNwI.d.ts → index-BaVpVNi2.d.ts} +26 -14
  27. package/dist/{index-DO4dQgf2.d.cts → index-BnYCS8Zg.d.cts} +2 -2
  28. package/dist/{index-CJeWHopy.d.ts → index-C0DAjsdX.d.ts} +2 -2
  29. package/dist/{index-Dl5PLgAv.d.cts → index-CKQzzZ5Y.d.cts} +2 -2
  30. package/dist/{index-CHqwkvGp.d.ts → index-D0mKxTR5.d.ts} +2 -2
  31. package/dist/index.cjs +186 -85
  32. package/dist/index.cjs.map +1 -1
  33. package/dist/index.d.cts +10 -10
  34. package/dist/index.d.ts +10 -10
  35. package/dist/index.js +186 -85
  36. package/dist/index.js.map +1 -1
  37. package/dist/{ports-DnLuKfpE.d.ts → ports-DpPTFhSd.d.ts} +2 -2
  38. package/dist/{ports-DaatKJXp.d.cts → ports-s-tSp3sB.d.cts} +2 -2
  39. package/dist/quickstart.cjs +119 -65
  40. package/dist/quickstart.cjs.map +1 -1
  41. package/dist/quickstart.d.cts +7 -7
  42. package/dist/quickstart.d.ts +7 -7
  43. package/dist/quickstart.js +119 -65
  44. package/dist/quickstart.js.map +1 -1
  45. package/dist/{runAgent-CPj_9e58.d.ts → runAgent-C6F-399C.d.ts} +5 -5
  46. package/dist/{runAgent-HYKlXbVr.d.cts → runAgent-ilEj66Ik.d.cts} +5 -5
  47. package/dist/{runHandle-D3gPsD7B.d.cts → runHandle-BNOqS-Bl.d.cts} +3 -3
  48. package/dist/{runHandle-CyXvzgzk.d.ts → runHandle-BdLXOFqF.d.ts} +3 -3
  49. package/dist/runtime-kernel/events.cjs +1 -0
  50. package/dist/runtime-kernel/events.cjs.map +1 -1
  51. package/dist/runtime-kernel/events.d.cts +4 -4
  52. package/dist/runtime-kernel/events.d.ts +4 -4
  53. package/dist/runtime-kernel/events.js +1 -0
  54. package/dist/runtime-kernel/events.js.map +1 -1
  55. package/dist/runtime-kernel.cjs +181 -82
  56. package/dist/runtime-kernel.cjs.map +1 -1
  57. package/dist/runtime-kernel.d.cts +8 -8
  58. package/dist/runtime-kernel.d.ts +8 -8
  59. package/dist/runtime-kernel.js +181 -83
  60. package/dist/runtime-kernel.js.map +1 -1
  61. package/dist/testkit.cjs +181 -82
  62. package/dist/testkit.cjs.map +1 -1
  63. package/dist/testkit.d.cts +8 -8
  64. package/dist/testkit.d.ts +8 -8
  65. package/dist/testkit.js +181 -82
  66. package/dist/testkit.js.map +1 -1
  67. package/dist/{todo-B1PmDlp3.d.cts → todo-Ca8llpRQ.d.cts} +1 -1
  68. package/dist/{todo-B1PmDlp3.d.ts → todo-Ca8llpRQ.d.ts} +1 -1
  69. package/dist/{toolContracts-CLkQmhTG.d.cts → toolContracts-Bm3EZ1UM.d.cts} +13 -2
  70. package/dist/{toolContracts-Blll0241.d.ts → toolContracts-f8lzZBNa.d.ts} +13 -2
  71. package/docs/integration/README.md +1 -1
  72. package/docs/integration/agent-registration-guide.md +1 -1
  73. package/docs/integration/child-runs.md +4 -1
  74. package/docs/integration/context-engineering.md +30 -15
  75. package/docs/integration/context-fences.md +32 -3
  76. package/docs/integration/llm-provider.md +1 -1
  77. package/docs/integration/persistence.md +1 -0
  78. package/docs/integration/run-supervisor.md +3 -0
  79. package/docs/integration/tool-development-guide.md +7 -5
  80. package/docs/integration/tool-history.md +43 -17
  81. package/package.json +4 -3
@@ -42,6 +42,7 @@ var Logger = class {
42
42
  constructor(moduleName) {
43
43
  this.moduleName = moduleName;
44
44
  }
45
+ moduleName;
45
46
  debug(message, data) {
46
47
  this.log(0 /* DEBUG */, "debug", message, data);
47
48
  }
@@ -264,6 +265,7 @@ var AgentSpecBudgetPolicy = zod.z.object({
264
265
  });
265
266
  var AgentSpecToolHistoryPolicy = zod.z.object({
266
267
  strategy: zod.z.enum(["per-pair", "per-run", "none"]).optional(),
268
+ retentionMode: zod.z.enum(["drop", "compress"]).optional(),
267
269
  keepLatestToolPairs: zod.z.number().int().nonnegative().optional(),
268
270
  keepLatestRuns: zod.z.number().int().nonnegative().optional(),
269
271
  maxInteractionGroups: zod.z.number().int().nonnegative().optional(),
@@ -1020,6 +1022,17 @@ var logger = new Logger("GraphExecutor");
1020
1022
  function asLocalRecord(local) {
1021
1023
  return local && typeof local === "object" ? { ...local } : {};
1022
1024
  }
1025
+ function readNonEmptyString(value) {
1026
+ return typeof value === "string" && value.trim().length > 0 ? value : void 0;
1027
+ }
1028
+ function readRuntimeConversationId(state) {
1029
+ const local = state?.local && typeof state.local === "object" ? state.local : void 0;
1030
+ return readNonEmptyString(local?.conversationId);
1031
+ }
1032
+ function readRuntimeTurnId(state) {
1033
+ const local = state?.local && typeof state.local === "object" ? state.local : void 0;
1034
+ return readNonEmptyString(local?.turnId);
1035
+ }
1023
1036
  var GraphExecutor = class {
1024
1037
  constructor(checkpointer, config = {}) {
1025
1038
  this.checkpointer = checkpointer;
@@ -1029,6 +1042,7 @@ var GraphExecutor = class {
1029
1042
  };
1030
1043
  this.telemetryPort = config.telemetryPort ?? noopTelemetry;
1031
1044
  }
1045
+ checkpointer;
1032
1046
  nodes = /* @__PURE__ */ new Map();
1033
1047
  ephemeralLocals = /* @__PURE__ */ new Map();
1034
1048
  config;
@@ -1036,8 +1050,8 @@ var GraphExecutor = class {
1036
1050
  registerNode(node) {
1037
1051
  this.nodes.set(node.id, node);
1038
1052
  }
1039
- async peekCheckpoint(conversationId) {
1040
- return await this.checkpointer.load(conversationId);
1053
+ async peekCheckpoint(checkpointKey) {
1054
+ return await this.checkpointer.load(checkpointKey);
1041
1055
  }
1042
1056
  sanitize(state) {
1043
1057
  const local = asLocalRecord(state.local);
@@ -1049,8 +1063,8 @@ var GraphExecutor = class {
1049
1063
  local
1050
1064
  };
1051
1065
  }
1052
- async prime(conversationId, local, nodeId = "user") {
1053
- this.ephemeralLocals.set(conversationId, { ...local || {} });
1066
+ async prime(checkpointKey, local, nodeId = "user") {
1067
+ this.ephemeralLocals.set(checkpointKey, { ...local || {} });
1054
1068
  const localSansMemory = { ...local || {} };
1055
1069
  if ("memory" in localSansMemory) delete localSansMemory.memory;
1056
1070
  const state = {
@@ -1058,10 +1072,10 @@ var GraphExecutor = class {
1058
1072
  schemaVersion: ENGINE_STATE_SCHEMA_VERSION,
1059
1073
  local: localSansMemory
1060
1074
  };
1061
- await this.checkpointer.save(conversationId, state);
1075
+ await this.checkpointer.save(checkpointKey, state);
1062
1076
  }
1063
- async setNode(conversationId, nodeId, localPatch) {
1064
- const current = await this.checkpointer.load(conversationId) || {
1077
+ async setNode(checkpointKey, nodeId, localPatch) {
1078
+ const current = await this.checkpointer.load(checkpointKey) || {
1065
1079
  schemaVersion: ENGINE_STATE_SCHEMA_VERSION,
1066
1080
  local: {}
1067
1081
  };
@@ -1072,19 +1086,46 @@ var GraphExecutor = class {
1072
1086
  schemaVersion: current.schemaVersion ?? ENGINE_STATE_SCHEMA_VERSION,
1073
1087
  local: mergedLocal
1074
1088
  };
1075
- await this.checkpointer.save(conversationId, next);
1089
+ await this.checkpointer.save(checkpointKey, next);
1076
1090
  }
1077
- async runUntilYield(conversationId) {
1091
+ async runUntilYield(checkpointKey) {
1078
1092
  const runId = `run_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
1079
1093
  let lifecyclePhase = "completed";
1094
+ let initialState = null;
1095
+ try {
1096
+ initialState = await this.loadInitialState(checkpointKey);
1097
+ } catch (err) {
1098
+ lifecyclePhase = "failed";
1099
+ this.telemetryPort.emit({
1100
+ kind: "run_lifecycle",
1101
+ runId,
1102
+ phase: "spawned",
1103
+ scope: {}
1104
+ });
1105
+ this.telemetryPort.emit({
1106
+ kind: "run_lifecycle",
1107
+ runId,
1108
+ phase: lifecyclePhase,
1109
+ scope: {}
1110
+ });
1111
+ throw err;
1112
+ }
1113
+ let lifecycleConversationId = readRuntimeConversationId(initialState);
1114
+ let lifecycleTurnId = readRuntimeTurnId(initialState);
1080
1115
  this.telemetryPort.emit({
1081
1116
  kind: "run_lifecycle",
1082
1117
  runId,
1083
1118
  phase: "spawned",
1084
- scope: { conversationId: conversationId || void 0 }
1119
+ scope: {
1120
+ conversationId: lifecycleConversationId,
1121
+ turnId: lifecycleTurnId
1122
+ }
1085
1123
  });
1086
1124
  try {
1087
- return await this.runUntilYieldInternal(conversationId);
1125
+ const result = await this.runUntilYieldInternal(checkpointKey, initialState);
1126
+ lifecycleConversationId = readRuntimeConversationId(result.checkpoint);
1127
+ lifecycleTurnId = readRuntimeTurnId(result.checkpoint);
1128
+ return result;
1088
1129
  } catch (err) {
1089
1130
  lifecyclePhase = err?.name === "AbortError" ? "cancelled" : "failed";
1090
1131
  throw err;
@@ -1093,17 +1134,23 @@ var GraphExecutor = class {
1093
1134
  kind: "run_lifecycle",
1094
1135
  runId,
1095
1136
  phase: lifecyclePhase,
1096
- scope: { conversationId: conversationId || void 0 }
1137
+ scope: {
1138
+ conversationId: lifecycleConversationId,
1139
+ turnId: lifecycleTurnId
1140
+ }
1097
1141
  });
1098
1142
  }
1099
1143
  }
1100
- async runUntilYieldInternal(conversationId) {
1101
- let state = await this.checkpointer.load(conversationId) || {
1144
+ async loadInitialState(checkpointKey) {
1145
+ return await this.checkpointer.load(checkpointKey) || {
1102
1146
  nodeId: "user",
1103
1147
  schemaVersion: ENGINE_STATE_SCHEMA_VERSION,
1104
1148
  local: {}
1105
1149
  };
1106
- const ephemeral = this.ephemeralLocals.get(conversationId) || {};
1150
+ }
1151
+ async runUntilYieldInternal(checkpointKey, initialState) {
1152
+ let state = initialState;
1153
+ const ephemeral = this.ephemeralLocals.get(checkpointKey) || {};
1107
1154
  state = {
1108
1155
  ...state,
1109
1156
  schemaVersion: state.schemaVersion ?? ENGINE_STATE_SCHEMA_VERSION,
@@ -1132,7 +1179,7 @@ var GraphExecutor = class {
1132
1179
  const signalRaw = state.local?.signal;
1133
1180
  if (isAbortSignal2(signalRaw) && signalRaw.aborted) {
1134
1181
  logger.warn("[GraphExecutor] \u6536\u5230 AbortSignal\uFF0C\u7ACB\u5373\u505C\u6B62\u63A8\u7406\u5FAA\u73AF");
1135
- this.ephemeralLocals.delete(conversationId);
1182
+ this.ephemeralLocals.delete(checkpointKey);
1136
1183
  throwAbortError();
1137
1184
  }
1138
1185
  const isLastStep = cycleStepCount >= this.config.maxSteps;
@@ -1180,8 +1227,8 @@ var GraphExecutor = class {
1180
1227
  checkpointCount
1181
1228
  });
1182
1229
  const cp2 = this.sanitize(state);
1183
- await this.checkpointer.save(conversationId, cp2);
1184
- this.ephemeralLocals.delete(conversationId);
1230
+ await this.checkpointer.save(checkpointKey, cp2);
1231
+ this.ephemeralLocals.delete(checkpointKey);
1185
1232
  return { events: allEvents, checkpoint: cp2, stepCount };
1186
1233
  }
1187
1234
  logger.info("[GraphExecutor] \u8282\u70B9\u5207\u6362", {
@@ -1192,18 +1239,18 @@ var GraphExecutor = class {
1192
1239
  });
1193
1240
  const nodeRunStartedAt = Date.now();
1194
1241
  const nodeIdForTelemetry = state.nodeId;
1242
+ const conversationIdForTelemetry = readRuntimeConversationId(state);
1195
1243
  let result;
1196
1244
  try {
1197
1245
  result = await node.run(state);
1198
1246
  } finally {
1199
- const turnIdForTelemetry = typeof state.local?.turnId === "string" ? state.local.turnId : void 0;
1200
1247
  this.telemetryPort.emit({
1201
1248
  kind: "graph_node",
1202
1249
  nodeId: nodeIdForTelemetry,
1203
1250
  durationMs: Date.now() - nodeRunStartedAt,
1204
1251
  scope: {
1205
- conversationId: conversationId || void 0,
1206
- turnId: turnIdForTelemetry
1252
+ conversationId: conversationIdForTelemetry,
1253
+ turnId: readRuntimeTurnId(state)
1207
1254
  }
1208
1255
  });
1209
1256
  }
@@ -1242,7 +1289,7 @@ var GraphExecutor = class {
1242
1289
  });
1243
1290
  state = { ...state, nodeId: nextNodeId };
1244
1291
  const cp2 = this.sanitize(state);
1245
- await this.checkpointer.save(conversationId, cp2);
1292
+ await this.checkpointer.save(checkpointKey, cp2);
1246
1293
  continue;
1247
1294
  }
1248
1295
  if (result.kind === "yield") {
@@ -1253,7 +1300,7 @@ var GraphExecutor = class {
1253
1300
  checkpointCount
1254
1301
  });
1255
1302
  const cp2 = this.sanitize(state);
1256
- await this.checkpointer.save(conversationId, cp2);
1303
+ await this.checkpointer.save(checkpointKey, cp2);
1257
1304
  return { events: allEvents, checkpoint: cp2, stepCount };
1258
1305
  }
1259
1306
  if (result.kind === "pause") {
@@ -1264,7 +1311,7 @@ var GraphExecutor = class {
1264
1311
  checkpointCount
1265
1312
  });
1266
1313
  const cp2 = this.sanitize(state);
1267
- await this.checkpointer.save(conversationId, cp2);
1314
+ await this.checkpointer.save(checkpointKey, cp2);
1268
1315
  return { events: allEvents, checkpoint: cp2, stepCount };
1269
1316
  }
1270
1317
  }
@@ -1275,8 +1322,8 @@ var GraphExecutor = class {
1275
1322
  checkpointCount
1276
1323
  });
1277
1324
  const cp = this.sanitize(state);
1278
- await this.checkpointer.save(conversationId, cp);
1279
- this.ephemeralLocals.delete(conversationId);
1325
+ await this.checkpointer.save(checkpointKey, cp);
1326
+ this.ephemeralLocals.delete(checkpointKey);
1280
1327
  return { events: allEvents, checkpoint: cp, stepCount };
1281
1328
  }
1282
1329
  };
@@ -1473,15 +1520,15 @@ function splitConcatenatedJsonObjects(input) {
1473
1520
  }
1474
1521
 
1475
1522
  // src/runtime-kernel/graph-engine/tick-pipeline/helpers.ts
1476
- function readNonEmptyString(value) {
1523
+ function readNonEmptyString2(value) {
1477
1524
  if (typeof value !== "string") return void 0;
1478
1525
  const trimmed = value.trim();
1479
1526
  return trimmed.length > 0 ? trimmed : void 0;
1480
1527
  }
1481
1528
  function resolveConversationIdForRuntimeEvents(toolContext) {
1482
- const fromCamel = readNonEmptyString(toolContext?.conversationId);
1529
+ const fromCamel = readNonEmptyString2(toolContext?.conversationId);
1483
1530
  if (fromCamel) return fromCamel;
1484
- const fromSnake = toolContext ? readNonEmptyString(toolContext["conversation_id"]) : void 0;
1531
+ const fromSnake = toolContext ? readNonEmptyString2(toolContext["conversation_id"]) : void 0;
1485
1532
  if (fromSnake) return fromSnake;
1486
1533
  return generateMessageId();
1487
1534
  }
@@ -1840,7 +1887,7 @@ var runModelLockMiddleware = async (ctx, stage, next) => {
1840
1887
  if (stage.id !== "execute_llm") {
1841
1888
  return;
1842
1889
  }
1843
- const normalized = readNonEmptyString(ctx.cloudQuotaFallbackAppliedModelId);
1890
+ const normalized = readNonEmptyString2(ctx.cloudQuotaFallbackAppliedModelId);
1844
1891
  if (!normalized) {
1845
1892
  return;
1846
1893
  }
@@ -2441,7 +2488,7 @@ function createExecuteLlmStage(dependencies) {
2441
2488
  streamEventHandler,
2442
2489
  ctx.signal,
2443
2490
  (fallbackModelId) => {
2444
- ctx.cloudQuotaFallbackAppliedModelId = readNonEmptyString(fallbackModelId);
2491
+ ctx.cloudQuotaFallbackAppliedModelId = readNonEmptyString2(fallbackModelId);
2445
2492
  },
2446
2493
  (info) => {
2447
2494
  ctx.modelFallbackAudit = info;
@@ -2485,7 +2532,7 @@ function createPrepareCallStage(dependencies) {
2485
2532
  return {
2486
2533
  id: "prepare_call",
2487
2534
  async run(ctx) {
2488
- const lockedRunModelId = readNonEmptyString(ctx.executorLocal?.runLockedModelId);
2535
+ const lockedRunModelId = readNonEmptyString2(ctx.executorLocal?.runLockedModelId);
2489
2536
  const requestedModelId = lockedRunModelId ?? ctx.request.model_id;
2490
2537
  ctx.modelId = dependencies.modelResolver.resolveModelId(requestedModelId);
2491
2538
  await emitAuditEnvelope(ctx.audit, {
@@ -2557,7 +2604,7 @@ var GraphAgentExecutor = class {
2557
2604
  this.llmCaller = dependencies.llmCaller;
2558
2605
  this.toolRuntime = dependencies.toolRuntime;
2559
2606
  this.contextBuilder = dependencies.contextBuilder;
2560
- this.cloudQuotaFallbackModelId = readNonEmptyString(dependencies.cloudQuotaFallbackModelId);
2607
+ this.cloudQuotaFallbackModelId = readNonEmptyString2(dependencies.cloudQuotaFallbackModelId);
2561
2608
  this.modelCatalog = dependencies.modelCatalog ?? createEmptyModelCatalog();
2562
2609
  this.modelResolver = dependencies.modelResolver ?? new ModelResolver({
2563
2610
  modelCatalog: this.modelCatalog
@@ -2605,7 +2652,7 @@ var GraphAgentExecutor = class {
2605
2652
  llmMessages: [],
2606
2653
  mode: input.request.mode === "chat" ? "chat" : "agent",
2607
2654
  conversationId: resolveConversationIdForRuntimeEvents(input.toolContext),
2608
- turnId: readNonEmptyString(input.toolContext?.turnId) ?? `turn_${Date.now()}`,
2655
+ turnId: readNonEmptyString2(input.toolContext?.turnId) ?? `turn_${Date.now()}`,
2609
2656
  telemetry: this.telemetryPort,
2610
2657
  audit: this.auditPort
2611
2658
  };
@@ -2655,18 +2702,18 @@ function isSummarizationCallbacks(value) {
2655
2702
  function isGraphSseSink(value) {
2656
2703
  return typeof value === "function";
2657
2704
  }
2658
- function readNonEmptyString2(value) {
2705
+ function readNonEmptyString3(value) {
2659
2706
  if (typeof value !== "string") return void 0;
2660
2707
  const trimmed = value.trim();
2661
2708
  return trimmed.length > 0 ? trimmed : void 0;
2662
2709
  }
2663
2710
  function readGraphAgentLocal(local) {
2664
2711
  const source = local ?? {};
2665
- const answerId = readNonEmptyString2(source.answerId);
2712
+ const answerId = readNonEmptyString3(source.answerId);
2666
2713
  const chunkSeq = Number.isInteger(source.chunkSeq) ? Number(source.chunkSeq) : 0;
2667
2714
  return {
2668
- conversationId: readNonEmptyString2(source.conversationId) ?? "",
2669
- turnId: readNonEmptyString2(source.turnId),
2715
+ conversationId: readNonEmptyString3(source.conversationId) ?? "",
2716
+ turnId: readNonEmptyString3(source.turnId),
2670
2717
  request: isAgentInvocationRequest(source.request) ? source.request : void 0,
2671
2718
  toolContext: isToolExecutionContext(source.toolContext) ? source.toolContext : void 0,
2672
2719
  history: isRuntimeEventArray(source.history) ? source.history : [],
@@ -3431,7 +3478,7 @@ var LlmNode = class {
3431
3478
  function isRecord8(value) {
3432
3479
  return typeof value === "object" && value !== null && !Array.isArray(value);
3433
3480
  }
3434
- function readNonEmptyString3(value) {
3481
+ function readNonEmptyString4(value) {
3435
3482
  if (typeof value !== "string") {
3436
3483
  return void 0;
3437
3484
  }
@@ -3453,7 +3500,7 @@ function resolveFinalAnswerFromToolResult(toolName, parsedResult) {
3453
3500
  return void 0;
3454
3501
  }
3455
3502
  if (toolName === "write_report") {
3456
- const report = readNonEmptyString3(data.report);
3503
+ const report = readNonEmptyString4(data.report);
3457
3504
  if (!report) {
3458
3505
  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");
3459
3506
  }
@@ -3463,7 +3510,7 @@ function resolveFinalAnswerFromToolResult(toolName, parsedResult) {
3463
3510
  if (data.success !== true) {
3464
3511
  return void 0;
3465
3512
  }
3466
- const finalAnswer = readNonEmptyString3(data.final_answer);
3513
+ const finalAnswer = readNonEmptyString4(data.final_answer);
3467
3514
  if (!finalAnswer) {
3468
3515
  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");
3469
3516
  }
@@ -4008,6 +4055,31 @@ function ensureToolContextRuntimeCapability(params) {
4008
4055
  function getToolContextRuntimeBinding(context) {
4009
4056
  return readBinding(context);
4010
4057
  }
4058
+ function copyToolContextRuntimeCapability(source, target) {
4059
+ const sourceBinding = readBinding(source);
4060
+ if (!sourceBinding) {
4061
+ return void 0;
4062
+ }
4063
+ const existingTargetBinding = readBinding(target);
4064
+ if (existingTargetBinding) {
4065
+ exposeCompatibilitySurface(target, existingTargetBinding);
4066
+ return existingTargetBinding;
4067
+ }
4068
+ const targetBinding = createRuntimeBinding({
4069
+ context: target,
4070
+ persistedHistory: () => sourceBinding.getPersistedHistoryEvents(),
4071
+ workingHistory: () => sourceBinding.getWorkingHistoryEvents(),
4072
+ executionMeta: sourceBinding.readExecutionMeta()
4073
+ });
4074
+ Object.defineProperty(target, TOOL_CONTEXT_RUNTIME_BINDING_KEY, {
4075
+ value: targetBinding,
4076
+ enumerable: false,
4077
+ configurable: true,
4078
+ writable: false
4079
+ });
4080
+ exposeCompatibilitySurface(target, targetBinding);
4081
+ return targetBinding;
4082
+ }
4011
4083
  function readToolContextWorkingHistory(context) {
4012
4084
  if (context.conversationView) {
4013
4085
  return context.conversationView.getWorkingHistoryEvents();
@@ -4859,12 +4931,12 @@ function asRecord(value) {
4859
4931
  }
4860
4932
  return value;
4861
4933
  }
4862
- function summarizeCheckpoint(conversationId, state, savedAt) {
4934
+ function summarizeCheckpoint(checkpointKey, state, savedAt) {
4863
4935
  const local = asRecord(state.local);
4864
4936
  const executorLocal = asRecord(local?.executorLocal);
4865
4937
  const pendingToolCalls = local?.pendingToolCalls;
4866
4938
  return {
4867
- conversationId,
4939
+ checkpointKey,
4868
4940
  schemaVersion: state.schemaVersion ?? 1,
4869
4941
  savedAt,
4870
4942
  currentNode: state.nodeId,
@@ -4883,25 +4955,25 @@ var MemoryCheckpointer = class {
4883
4955
  local: state.local && typeof state.local === "object" && !Array.isArray(state.local) ? { ...state.local } : state.local
4884
4956
  };
4885
4957
  }
4886
- async load(conversationId) {
4887
- const entry = this.store.get(conversationId);
4958
+ async load(checkpointKey) {
4959
+ const entry = this.store.get(checkpointKey);
4888
4960
  return entry ? this.cloneState(entry.state) : null;
4889
4961
  }
4890
- async save(conversationId, state) {
4891
- this.store.set(conversationId, {
4962
+ async save(checkpointKey, state) {
4963
+ this.store.set(checkpointKey, {
4892
4964
  state: this.cloneState(state),
4893
4965
  savedAt: Date.now()
4894
4966
  });
4895
4967
  }
4896
- async clear(conversationId) {
4897
- this.store.delete(conversationId);
4968
+ async clear(checkpointKey) {
4969
+ this.store.delete(checkpointKey);
4898
4970
  }
4899
- async peekMeta(conversationId) {
4900
- const entry = this.store.get(conversationId);
4901
- return entry ? summarizeCheckpoint(conversationId, entry.state, entry.savedAt) : null;
4971
+ async peekMeta(checkpointKey) {
4972
+ const entry = this.store.get(checkpointKey);
4973
+ return entry ? summarizeCheckpoint(checkpointKey, entry.state, entry.savedAt) : null;
4902
4974
  }
4903
4975
  async list(filter = {}) {
4904
- 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);
4976
+ 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);
4905
4977
  if (filter.limit === void 0) {
4906
4978
  return summaries;
4907
4979
  }
@@ -4973,6 +5045,7 @@ __export(tools_exports, {
4973
5045
  CommonParameterTypes: () => CommonParameterTypes,
4974
5046
  ContextCheckpointTool: () => ContextCheckpointTool,
4975
5047
  computeToolIdempotencyKey: () => computeToolIdempotencyKey,
5048
+ copyToolContextRuntimeCapability: () => copyToolContextRuntimeCapability,
4976
5049
  createContextCheckpointTool: () => createContextCheckpointTool,
4977
5050
  ensureToolContextRuntimeCapability: () => ensureToolContextRuntimeCapability,
4978
5051
  findCachedToolOutputByIdempotencyKey: () => findCachedToolOutputByIdempotencyKey,
@@ -5166,7 +5239,7 @@ function createContextCheckpointTool(options) {
5166
5239
  function isRecord15(value) {
5167
5240
  return !!value && typeof value === "object" && !Array.isArray(value);
5168
5241
  }
5169
- function readNonEmptyString4(value) {
5242
+ function readNonEmptyString5(value) {
5170
5243
  if (typeof value !== "string") {
5171
5244
  return void 0;
5172
5245
  }
@@ -5186,13 +5259,13 @@ function readToolContextUserQuery(context) {
5186
5259
  if (!context) {
5187
5260
  return void 0;
5188
5261
  }
5189
- return readNonEmptyString4(context["user_query"]);
5262
+ return readNonEmptyString5(context["user_query"]);
5190
5263
  }
5191
5264
  function readToolContextModelId(context) {
5192
5265
  if (!context) {
5193
5266
  return void 0;
5194
5267
  }
5195
- return readNonEmptyString4(context["modelId"]);
5268
+ return readNonEmptyString5(context["modelId"]);
5196
5269
  }
5197
5270
  function readToolContextRunContext(context) {
5198
5271
  if (!context) {
@@ -6900,6 +6973,7 @@ var DefaultTokenizerPort = class {
6900
6973
  constructor(config = {}) {
6901
6974
  this.config = config;
6902
6975
  }
6976
+ config;
6903
6977
  estimateText(text, _modelId) {
6904
6978
  return TokenCalculator.estimateTokens(text, {
6905
6979
  encoding: this.config.encoding,
@@ -6927,7 +7001,6 @@ __export(child_runs_exports, {
6927
7001
 
6928
7002
  // src/runtime-kernel/child-runs/childToolContext.ts
6929
7003
  function createChildRunToolContext(params) {
6930
- const inheritedConversationId = typeof params.parentToolContext.conversationId === "string" && params.parentToolContext.conversationId.trim().length > 0 ? params.parentToolContext.conversationId.trim() : void 0;
6931
7004
  const inheritedContext = stripRuntimeReservedToolContextPatch(params.parentToolContext);
6932
7005
  const childToolContext = {
6933
7006
  ...inheritedContext,
@@ -6939,7 +7012,7 @@ function createChildRunToolContext(params) {
6939
7012
  persistedHistory: params.seedHistory,
6940
7013
  workingHistory: params.seedHistory,
6941
7014
  executionMeta: {
6942
- conversationId: inheritedConversationId ?? params.internalConversationId,
7015
+ conversationId: params.conversationId,
6943
7016
  turnId: params.turnId,
6944
7017
  runId: params.runId,
6945
7018
  parentRunId: params.parentRunId
@@ -7041,6 +7114,8 @@ var FinalAnswerCollector = class {
7041
7114
  this.conversationId = conversationId;
7042
7115
  this.turnId = turnId;
7043
7116
  }
7117
+ conversationId;
7118
+ turnId;
7044
7119
  answerId;
7045
7120
  chunks = [];
7046
7121
  chunkCount = 0;
@@ -7257,7 +7332,7 @@ function readCheckpointHistory(checkpoint) {
7257
7332
  });
7258
7333
  }
7259
7334
  async function recoverChildRunEventsFromCheckpoint(params) {
7260
- const checkpoint = await params.checkpointer.load(params.conversationId);
7335
+ const checkpoint = await params.checkpointer.load(params.checkpointKey);
7261
7336
  const history = readCheckpointHistory(checkpoint);
7262
7337
  if (history.length === 0) {
7263
7338
  return [];
@@ -7265,7 +7340,7 @@ async function recoverChildRunEventsFromCheckpoint(params) {
7265
7340
  if (hasSeedHistoryPrefix(history, params.seedHistory)) {
7266
7341
  return history.slice(params.seedHistory.length);
7267
7342
  }
7268
- return history.filter((event) => event.conversation_id === params.internalConversationId);
7343
+ return history.filter((event) => event.conversation_id === params.childConversationId);
7269
7344
  }
7270
7345
 
7271
7346
  // src/runtime-kernel/child-runs/childRunInvoker.ts
@@ -7294,6 +7369,7 @@ var ChildRunInvoker = class {
7294
7369
  agentConfig,
7295
7370
  userMessage,
7296
7371
  parentToolContext,
7372
+ conversationId,
7297
7373
  runId,
7298
7374
  parentRunId,
7299
7375
  subrunTracePublisher,
@@ -7302,12 +7378,18 @@ var ChildRunInvoker = class {
7302
7378
  modelId,
7303
7379
  abortSignal
7304
7380
  } = config;
7305
- const internalConversationId = `internal_${generateMessageId()}`;
7381
+ const internalCheckpointKey = `internal_${generateMessageId()}`;
7382
+ const runtimeConversationId = resolveChildRunConversationId({
7383
+ explicitConversationId: conversationId,
7384
+ parentToolContext,
7385
+ fallbackConversationId: internalCheckpointKey
7386
+ });
7306
7387
  const turnId = `turn_${Date.now()}`;
7307
- const childRunId = typeof runId === "string" && runId.trim().length > 0 ? runId.trim() : internalConversationId;
7388
+ const childRunId = typeof runId === "string" && runId.trim().length > 0 ? runId.trim() : internalCheckpointKey;
7308
7389
  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;
7309
7390
  logger13.info(`\u542F\u52A8 child-run: ${agentConfig.id}`, {
7310
- conversationId: internalConversationId,
7391
+ conversationId: runtimeConversationId,
7392
+ checkpointKey: internalCheckpointKey,
7311
7393
  maxSteps,
7312
7394
  userMessage: userMessage.slice(0, 100) + (userMessage.length > 100 ? "..." : "")
7313
7395
  });
@@ -7368,7 +7450,7 @@ var ChildRunInvoker = class {
7368
7450
  const seedHistory = Array.isArray(seedHistoryEvents) ? seedHistoryEvents : [];
7369
7451
  const childToolContext = createChildRunToolContext({
7370
7452
  parentToolContext,
7371
- internalConversationId,
7453
+ conversationId: runtimeConversationId,
7372
7454
  turnId,
7373
7455
  runId: childRunId,
7374
7456
  parentRunId: resolvedParentRunId,
@@ -7377,13 +7459,13 @@ var ChildRunInvoker = class {
7377
7459
  });
7378
7460
  const subrunSseSink = subrunTracePublisher ? createChildRunTraceSink({
7379
7461
  publisher: subrunTracePublisher,
7380
- conversationId: internalConversationId,
7462
+ conversationId: runtimeConversationId,
7381
7463
  turnId
7382
7464
  }) : void 0;
7383
7465
  const initialLocal = {
7384
7466
  request,
7385
7467
  history: seedHistory,
7386
- conversationId: internalConversationId,
7468
+ conversationId: runtimeConversationId,
7387
7469
  turnId,
7388
7470
  toolContext: childToolContext,
7389
7471
  ...abortSignal ? { signal: abortSignal } : {},
@@ -7391,7 +7473,7 @@ var ChildRunInvoker = class {
7391
7473
  ...subrunSseSink ? { sseSink: subrunSseSink } : {},
7392
7474
  systemPrompt
7393
7475
  };
7394
- await graphExecutor.prime(internalConversationId, initialLocal, "llm");
7476
+ await graphExecutor.prime(internalCheckpointKey, initialLocal, "llm");
7395
7477
  const allEvents = [];
7396
7478
  let stepCount = 0;
7397
7479
  let finalAnswer;
@@ -7403,7 +7485,7 @@ var ChildRunInvoker = class {
7403
7485
  err.name = "AbortError";
7404
7486
  throw err;
7405
7487
  }
7406
- const result = await graphExecutor.runUntilYield(internalConversationId);
7488
+ const result = await graphExecutor.runUntilYield(internalCheckpointKey);
7407
7489
  appendUniqueEvents(allEvents, result.events);
7408
7490
  stepCount = result.stepCount;
7409
7491
  if (subrunSseSink && typeof subrunSseSink.finalize === "function") {
@@ -7437,8 +7519,8 @@ var ChildRunInvoker = class {
7437
7519
  }
7438
7520
  const recoveredEvents = await recoverChildRunEventsFromCheckpoint({
7439
7521
  checkpointer,
7440
- conversationId: internalConversationId,
7441
- internalConversationId,
7522
+ checkpointKey: internalCheckpointKey,
7523
+ childConversationId: runtimeConversationId,
7442
7524
  seedHistory
7443
7525
  });
7444
7526
  appendUniqueEvents(allEvents, recoveredEvents);
@@ -7455,7 +7537,7 @@ var ChildRunInvoker = class {
7455
7537
  stack: err.stack
7456
7538
  } : { error: String(err) });
7457
7539
  }
7458
- await checkpointer.clear(internalConversationId);
7540
+ await checkpointer.clear(internalCheckpointKey);
7459
7541
  return {
7460
7542
  success: !error,
7461
7543
  runId: childRunId,
@@ -7468,6 +7550,16 @@ var ChildRunInvoker = class {
7468
7550
  };
7469
7551
  }
7470
7552
  };
7553
+ function readNonEmptyString6(value) {
7554
+ if (typeof value !== "string") {
7555
+ return void 0;
7556
+ }
7557
+ const trimmed = value.trim();
7558
+ return trimmed.length > 0 ? trimmed : void 0;
7559
+ }
7560
+ function resolveChildRunConversationId(params) {
7561
+ return readNonEmptyString6(params.explicitConversationId) ?? readNonEmptyString6(params.parentToolContext.conversationId) ?? params.fallbackConversationId;
7562
+ }
7471
7563
  function resolveChildRunSystemReminderPolicy(agentConfig) {
7472
7564
  const configured = agentConfig.systemReminderPolicy ?? agentConfig.contextPolicy?.systemReminder;
7473
7565
  const threshold = agentConfig.stepPolicy?.lastStepsHintThreshold;
@@ -7658,7 +7750,7 @@ function cloneRunRecord(record) {
7658
7750
  ...record,
7659
7751
  iterationBudget: record.iterationBudget ? { ...record.iterationBudget } : void 0,
7660
7752
  errorIfAny: record.errorIfAny ? { ...record.errorIfAny } : void 0,
7661
- metadata: record.metadata ? { ...record.metadata } : void 0
7753
+ metadata: record.metadata ? structuredClone(record.metadata) : void 0
7662
7754
  };
7663
7755
  }
7664
7756
  function matchesStatus(candidate, filter) {
@@ -8070,7 +8162,7 @@ function isTerminalStatus(status) {
8070
8162
  return status === "completed" || status === "failed" || status === "cancelled";
8071
8163
  }
8072
8164
  function cloneMetadata(metadata) {
8073
- return metadata ? { ...metadata } : void 0;
8165
+ return metadata ? structuredClone(metadata) : void 0;
8074
8166
  }
8075
8167
  function recordToSnapshot(record) {
8076
8168
  return {
@@ -8157,7 +8249,7 @@ var DefaultRunSupervisor = class {
8157
8249
  startedAt,
8158
8250
  updatedAt: startedAt,
8159
8251
  iterationBudget: spec.iterationBudget ? { ...spec.iterationBudget } : void 0,
8160
- metadata: spec.metadata ? { ...spec.metadata } : void 0
8252
+ metadata: cloneMetadata(spec.metadata)
8161
8253
  };
8162
8254
  await this.registryStore.save(record);
8163
8255
  const handle = new DefaultRunHandle({
@@ -8331,12 +8423,13 @@ var DefaultRunSupervisor = class {
8331
8423
  }
8332
8424
  try {
8333
8425
  await handle.markRunning({ currentNode: "detached" });
8426
+ const registeredRecord = await this.registryStore.load(handle.runId);
8334
8427
  const executorOutcome = await this.executor.execute({
8335
8428
  runId: handle.runId,
8336
- parentRunId: spec.parentRunId,
8337
- conversationId: spec.conversationId,
8338
- agentSpec: spec.agentSpec,
8339
- request: spec.request,
8429
+ parentRunId: handle.parentRunId,
8430
+ conversationId: registeredRecord?.conversationId ?? spec.conversationId,
8431
+ agentSpec: await handle.spec(),
8432
+ request: await handle.request(),
8340
8433
  signal: handle.signal,
8341
8434
  eventBus: spec.eventBus,
8342
8435
  eventStore: spec.eventStore,
@@ -8345,7 +8438,7 @@ var DefaultRunSupervisor = class {
8345
8438
  contextFences: spec.contextFences,
8346
8439
  wakeSource: spec.wakeSource,
8347
8440
  ephemeral: spec.ephemeral,
8348
- metadata: spec.metadata
8441
+ metadata: cloneMetadata(registeredRecord?.metadata ?? spec.metadata)
8349
8442
  });
8350
8443
  const outcome = await this.persistExecutorOutcome(handle, executorOutcome);
8351
8444
  this.notifyTerminalWaiters(outcome);
@@ -8409,10 +8502,14 @@ var DefaultRunSupervisor = class {
8409
8502
  await this.registryStore.save(record);
8410
8503
  }
8411
8504
  const completedAt = executorOutcome?.completedAt ?? this.now();
8505
+ const fallbackMeta = record ? void 0 : await handle.meta();
8412
8506
  const outcome = recordToTerminalOutcome(record ?? {
8413
8507
  runId: handle.runId,
8414
8508
  parentRunId: handle.parentRunId,
8415
- status: executorOutcome?.status ?? "completed"}, completedAt);
8509
+ conversationId: fallbackMeta?.conversationId ?? "",
8510
+ agentSpecId: fallbackMeta?.agentSpecId,
8511
+ status: executorOutcome?.status ?? "completed",
8512
+ startedAt: fallbackMeta?.startedAt ?? completedAt}, completedAt);
8416
8513
  const nextOutcome = {
8417
8514
  ...outcome,
8418
8515
  metadata: {
@@ -8640,6 +8737,7 @@ function createGraphLoopHarness(options) {
8640
8737
  };
8641
8738
  return {
8642
8739
  async run() {
8740
+ const checkpointKey = options.conversationId;
8643
8741
  const executor = createDefaultGraphExecutor({
8644
8742
  llmNode: options.createLlmNode({
8645
8743
  llmCaller: options.llmCaller,
@@ -8668,8 +8766,8 @@ function createGraphLoopHarness(options) {
8668
8766
  signal: options.signal ?? options.toolContext.abortSignal,
8669
8767
  executorLocal
8670
8768
  };
8671
- await executor.prime(options.conversationId, local, "user");
8672
- const result = await executor.runUntilYield(options.conversationId);
8769
+ await executor.prime(checkpointKey, local, "user");
8770
+ const result = await executor.runUntilYield(checkpointKey);
8673
8771
  return {
8674
8772
  checkpointNodeId: result.checkpoint.nodeId,
8675
8773
  stepCount: result.stepCount
@@ -8718,6 +8816,7 @@ exports.compactReasoningDetailsInValue = compactReasoningDetailsInValue;
8718
8816
  exports.computeToolIdempotencyKey = computeToolIdempotencyKey;
8719
8817
  exports.consoleAudit = consoleAudit;
8720
8818
  exports.contextBudgetWarningTemplate = contextBudgetWarningTemplate;
8819
+ exports.copyToolContextRuntimeCapability = copyToolContextRuntimeCapability;
8721
8820
  exports.countToolCallsInCurrentRequest = countToolCallsInCurrentRequest;
8722
8821
  exports.createCompositeAudit = createCompositeAudit;
8723
8822
  exports.createConsoleAudit = createConsoleAudit;