@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
package/dist/testkit.js CHANGED
@@ -116,6 +116,7 @@ __export(runtime_kernel_exports, {
116
116
  computeToolIdempotencyKey: () => computeToolIdempotencyKey,
117
117
  consoleAudit: () => consoleAudit,
118
118
  contextBudgetWarningTemplate: () => contextBudgetWarningTemplate,
119
+ copyToolContextRuntimeCapability: () => copyToolContextRuntimeCapability,
119
120
  countToolCallsInCurrentRequest: () => countToolCallsInCurrentRequest,
120
121
  createCompositeAudit: () => createCompositeAudit,
121
122
  createConsoleAudit: () => createConsoleAudit,
@@ -197,6 +198,7 @@ var Logger = class {
197
198
  constructor(moduleName) {
198
199
  this.moduleName = moduleName;
199
200
  }
201
+ moduleName;
200
202
  debug(message, data) {
201
203
  this.log(0 /* DEBUG */, "debug", message, data);
202
204
  }
@@ -419,6 +421,7 @@ var AgentSpecBudgetPolicy = z.object({
419
421
  });
420
422
  var AgentSpecToolHistoryPolicy = z.object({
421
423
  strategy: z.enum(["per-pair", "per-run", "none"]).optional(),
424
+ retentionMode: z.enum(["drop", "compress"]).optional(),
422
425
  keepLatestToolPairs: z.number().int().nonnegative().optional(),
423
426
  keepLatestRuns: z.number().int().nonnegative().optional(),
424
427
  maxInteractionGroups: z.number().int().nonnegative().optional(),
@@ -1175,6 +1178,17 @@ var logger = new Logger("GraphExecutor");
1175
1178
  function asLocalRecord(local) {
1176
1179
  return local && typeof local === "object" ? { ...local } : {};
1177
1180
  }
1181
+ function readNonEmptyString(value) {
1182
+ return typeof value === "string" && value.trim().length > 0 ? value : void 0;
1183
+ }
1184
+ function readRuntimeConversationId(state) {
1185
+ const local = state?.local && typeof state.local === "object" ? state.local : void 0;
1186
+ return readNonEmptyString(local?.conversationId);
1187
+ }
1188
+ function readRuntimeTurnId(state) {
1189
+ const local = state?.local && typeof state.local === "object" ? state.local : void 0;
1190
+ return readNonEmptyString(local?.turnId);
1191
+ }
1178
1192
  var GraphExecutor = class {
1179
1193
  constructor(checkpointer, config = {}) {
1180
1194
  this.checkpointer = checkpointer;
@@ -1184,6 +1198,7 @@ var GraphExecutor = class {
1184
1198
  };
1185
1199
  this.telemetryPort = config.telemetryPort ?? noopTelemetry;
1186
1200
  }
1201
+ checkpointer;
1187
1202
  nodes = /* @__PURE__ */ new Map();
1188
1203
  ephemeralLocals = /* @__PURE__ */ new Map();
1189
1204
  config;
@@ -1191,8 +1206,8 @@ var GraphExecutor = class {
1191
1206
  registerNode(node) {
1192
1207
  this.nodes.set(node.id, node);
1193
1208
  }
1194
- async peekCheckpoint(conversationId) {
1195
- return await this.checkpointer.load(conversationId);
1209
+ async peekCheckpoint(checkpointKey) {
1210
+ return await this.checkpointer.load(checkpointKey);
1196
1211
  }
1197
1212
  sanitize(state) {
1198
1213
  const local = asLocalRecord(state.local);
@@ -1204,8 +1219,8 @@ var GraphExecutor = class {
1204
1219
  local
1205
1220
  };
1206
1221
  }
1207
- async prime(conversationId, local, nodeId = "user") {
1208
- this.ephemeralLocals.set(conversationId, { ...local || {} });
1222
+ async prime(checkpointKey, local, nodeId = "user") {
1223
+ this.ephemeralLocals.set(checkpointKey, { ...local || {} });
1209
1224
  const localSansMemory = { ...local || {} };
1210
1225
  if ("memory" in localSansMemory) delete localSansMemory.memory;
1211
1226
  const state = {
@@ -1213,10 +1228,10 @@ var GraphExecutor = class {
1213
1228
  schemaVersion: ENGINE_STATE_SCHEMA_VERSION,
1214
1229
  local: localSansMemory
1215
1230
  };
1216
- await this.checkpointer.save(conversationId, state);
1231
+ await this.checkpointer.save(checkpointKey, state);
1217
1232
  }
1218
- async setNode(conversationId, nodeId, localPatch) {
1219
- const current = await this.checkpointer.load(conversationId) || {
1233
+ async setNode(checkpointKey, nodeId, localPatch) {
1234
+ const current = await this.checkpointer.load(checkpointKey) || {
1220
1235
  schemaVersion: ENGINE_STATE_SCHEMA_VERSION,
1221
1236
  local: {}
1222
1237
  };
@@ -1227,19 +1242,46 @@ var GraphExecutor = class {
1227
1242
  schemaVersion: current.schemaVersion ?? ENGINE_STATE_SCHEMA_VERSION,
1228
1243
  local: mergedLocal
1229
1244
  };
1230
- await this.checkpointer.save(conversationId, next);
1245
+ await this.checkpointer.save(checkpointKey, next);
1231
1246
  }
1232
- async runUntilYield(conversationId) {
1247
+ async runUntilYield(checkpointKey) {
1233
1248
  const runId = `run_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
1234
1249
  let lifecyclePhase = "completed";
1250
+ let initialState = null;
1251
+ try {
1252
+ initialState = await this.loadInitialState(checkpointKey);
1253
+ } catch (err) {
1254
+ lifecyclePhase = "failed";
1255
+ this.telemetryPort.emit({
1256
+ kind: "run_lifecycle",
1257
+ runId,
1258
+ phase: "spawned",
1259
+ scope: {}
1260
+ });
1261
+ this.telemetryPort.emit({
1262
+ kind: "run_lifecycle",
1263
+ runId,
1264
+ phase: lifecyclePhase,
1265
+ scope: {}
1266
+ });
1267
+ throw err;
1268
+ }
1269
+ let lifecycleConversationId = readRuntimeConversationId(initialState);
1270
+ let lifecycleTurnId = readRuntimeTurnId(initialState);
1235
1271
  this.telemetryPort.emit({
1236
1272
  kind: "run_lifecycle",
1237
1273
  runId,
1238
1274
  phase: "spawned",
1239
- scope: { conversationId: conversationId || void 0 }
1275
+ scope: {
1276
+ conversationId: lifecycleConversationId,
1277
+ turnId: lifecycleTurnId
1278
+ }
1240
1279
  });
1241
1280
  try {
1242
- return await this.runUntilYieldInternal(conversationId);
1281
+ const result = await this.runUntilYieldInternal(checkpointKey, initialState);
1282
+ lifecycleConversationId = readRuntimeConversationId(result.checkpoint);
1283
+ lifecycleTurnId = readRuntimeTurnId(result.checkpoint);
1284
+ return result;
1243
1285
  } catch (err) {
1244
1286
  lifecyclePhase = err?.name === "AbortError" ? "cancelled" : "failed";
1245
1287
  throw err;
@@ -1248,17 +1290,23 @@ var GraphExecutor = class {
1248
1290
  kind: "run_lifecycle",
1249
1291
  runId,
1250
1292
  phase: lifecyclePhase,
1251
- scope: { conversationId: conversationId || void 0 }
1293
+ scope: {
1294
+ conversationId: lifecycleConversationId,
1295
+ turnId: lifecycleTurnId
1296
+ }
1252
1297
  });
1253
1298
  }
1254
1299
  }
1255
- async runUntilYieldInternal(conversationId) {
1256
- let state = await this.checkpointer.load(conversationId) || {
1300
+ async loadInitialState(checkpointKey) {
1301
+ return await this.checkpointer.load(checkpointKey) || {
1257
1302
  nodeId: "user",
1258
1303
  schemaVersion: ENGINE_STATE_SCHEMA_VERSION,
1259
1304
  local: {}
1260
1305
  };
1261
- const ephemeral = this.ephemeralLocals.get(conversationId) || {};
1306
+ }
1307
+ async runUntilYieldInternal(checkpointKey, initialState) {
1308
+ let state = initialState;
1309
+ const ephemeral = this.ephemeralLocals.get(checkpointKey) || {};
1262
1310
  state = {
1263
1311
  ...state,
1264
1312
  schemaVersion: state.schemaVersion ?? ENGINE_STATE_SCHEMA_VERSION,
@@ -1287,7 +1335,7 @@ var GraphExecutor = class {
1287
1335
  const signalRaw = state.local?.signal;
1288
1336
  if (isAbortSignal2(signalRaw) && signalRaw.aborted) {
1289
1337
  logger.warn("[GraphExecutor] \u6536\u5230 AbortSignal\uFF0C\u7ACB\u5373\u505C\u6B62\u63A8\u7406\u5FAA\u73AF");
1290
- this.ephemeralLocals.delete(conversationId);
1338
+ this.ephemeralLocals.delete(checkpointKey);
1291
1339
  throwAbortError();
1292
1340
  }
1293
1341
  const isLastStep = cycleStepCount >= this.config.maxSteps;
@@ -1335,8 +1383,8 @@ var GraphExecutor = class {
1335
1383
  checkpointCount
1336
1384
  });
1337
1385
  const cp2 = this.sanitize(state);
1338
- await this.checkpointer.save(conversationId, cp2);
1339
- this.ephemeralLocals.delete(conversationId);
1386
+ await this.checkpointer.save(checkpointKey, cp2);
1387
+ this.ephemeralLocals.delete(checkpointKey);
1340
1388
  return { events: allEvents, checkpoint: cp2, stepCount };
1341
1389
  }
1342
1390
  logger.info("[GraphExecutor] \u8282\u70B9\u5207\u6362", {
@@ -1347,18 +1395,18 @@ var GraphExecutor = class {
1347
1395
  });
1348
1396
  const nodeRunStartedAt = Date.now();
1349
1397
  const nodeIdForTelemetry = state.nodeId;
1398
+ const conversationIdForTelemetry = readRuntimeConversationId(state);
1350
1399
  let result;
1351
1400
  try {
1352
1401
  result = await node.run(state);
1353
1402
  } finally {
1354
- const turnIdForTelemetry = typeof state.local?.turnId === "string" ? state.local.turnId : void 0;
1355
1403
  this.telemetryPort.emit({
1356
1404
  kind: "graph_node",
1357
1405
  nodeId: nodeIdForTelemetry,
1358
1406
  durationMs: Date.now() - nodeRunStartedAt,
1359
1407
  scope: {
1360
- conversationId: conversationId || void 0,
1361
- turnId: turnIdForTelemetry
1408
+ conversationId: conversationIdForTelemetry,
1409
+ turnId: readRuntimeTurnId(state)
1362
1410
  }
1363
1411
  });
1364
1412
  }
@@ -1397,7 +1445,7 @@ var GraphExecutor = class {
1397
1445
  });
1398
1446
  state = { ...state, nodeId: nextNodeId };
1399
1447
  const cp2 = this.sanitize(state);
1400
- await this.checkpointer.save(conversationId, cp2);
1448
+ await this.checkpointer.save(checkpointKey, cp2);
1401
1449
  continue;
1402
1450
  }
1403
1451
  if (result.kind === "yield") {
@@ -1408,7 +1456,7 @@ var GraphExecutor = class {
1408
1456
  checkpointCount
1409
1457
  });
1410
1458
  const cp2 = this.sanitize(state);
1411
- await this.checkpointer.save(conversationId, cp2);
1459
+ await this.checkpointer.save(checkpointKey, cp2);
1412
1460
  return { events: allEvents, checkpoint: cp2, stepCount };
1413
1461
  }
1414
1462
  if (result.kind === "pause") {
@@ -1419,7 +1467,7 @@ var GraphExecutor = class {
1419
1467
  checkpointCount
1420
1468
  });
1421
1469
  const cp2 = this.sanitize(state);
1422
- await this.checkpointer.save(conversationId, cp2);
1470
+ await this.checkpointer.save(checkpointKey, cp2);
1423
1471
  return { events: allEvents, checkpoint: cp2, stepCount };
1424
1472
  }
1425
1473
  }
@@ -1430,8 +1478,8 @@ var GraphExecutor = class {
1430
1478
  checkpointCount
1431
1479
  });
1432
1480
  const cp = this.sanitize(state);
1433
- await this.checkpointer.save(conversationId, cp);
1434
- this.ephemeralLocals.delete(conversationId);
1481
+ await this.checkpointer.save(checkpointKey, cp);
1482
+ this.ephemeralLocals.delete(checkpointKey);
1435
1483
  return { events: allEvents, checkpoint: cp, stepCount };
1436
1484
  }
1437
1485
  };
@@ -1628,15 +1676,15 @@ function splitConcatenatedJsonObjects(input) {
1628
1676
  }
1629
1677
 
1630
1678
  // src/runtime-kernel/graph-engine/tick-pipeline/helpers.ts
1631
- function readNonEmptyString(value) {
1679
+ function readNonEmptyString2(value) {
1632
1680
  if (typeof value !== "string") return void 0;
1633
1681
  const trimmed = value.trim();
1634
1682
  return trimmed.length > 0 ? trimmed : void 0;
1635
1683
  }
1636
1684
  function resolveConversationIdForRuntimeEvents(toolContext) {
1637
- const fromCamel = readNonEmptyString(toolContext?.conversationId);
1685
+ const fromCamel = readNonEmptyString2(toolContext?.conversationId);
1638
1686
  if (fromCamel) return fromCamel;
1639
- const fromSnake = toolContext ? readNonEmptyString(toolContext["conversation_id"]) : void 0;
1687
+ const fromSnake = toolContext ? readNonEmptyString2(toolContext["conversation_id"]) : void 0;
1640
1688
  if (fromSnake) return fromSnake;
1641
1689
  return generateMessageId();
1642
1690
  }
@@ -1995,7 +2043,7 @@ var runModelLockMiddleware = async (ctx, stage, next) => {
1995
2043
  if (stage.id !== "execute_llm") {
1996
2044
  return;
1997
2045
  }
1998
- const normalized = readNonEmptyString(ctx.cloudQuotaFallbackAppliedModelId);
2046
+ const normalized = readNonEmptyString2(ctx.cloudQuotaFallbackAppliedModelId);
1999
2047
  if (!normalized) {
2000
2048
  return;
2001
2049
  }
@@ -2596,7 +2644,7 @@ function createExecuteLlmStage(dependencies) {
2596
2644
  streamEventHandler,
2597
2645
  ctx.signal,
2598
2646
  (fallbackModelId) => {
2599
- ctx.cloudQuotaFallbackAppliedModelId = readNonEmptyString(fallbackModelId);
2647
+ ctx.cloudQuotaFallbackAppliedModelId = readNonEmptyString2(fallbackModelId);
2600
2648
  },
2601
2649
  (info) => {
2602
2650
  ctx.modelFallbackAudit = info;
@@ -2640,7 +2688,7 @@ function createPrepareCallStage(dependencies) {
2640
2688
  return {
2641
2689
  id: "prepare_call",
2642
2690
  async run(ctx) {
2643
- const lockedRunModelId = readNonEmptyString(ctx.executorLocal?.runLockedModelId);
2691
+ const lockedRunModelId = readNonEmptyString2(ctx.executorLocal?.runLockedModelId);
2644
2692
  const requestedModelId = lockedRunModelId ?? ctx.request.model_id;
2645
2693
  ctx.modelId = dependencies.modelResolver.resolveModelId(requestedModelId);
2646
2694
  await emitAuditEnvelope(ctx.audit, {
@@ -2712,7 +2760,7 @@ var GraphAgentExecutor = class {
2712
2760
  this.llmCaller = dependencies.llmCaller;
2713
2761
  this.toolRuntime = dependencies.toolRuntime;
2714
2762
  this.contextBuilder = dependencies.contextBuilder;
2715
- this.cloudQuotaFallbackModelId = readNonEmptyString(dependencies.cloudQuotaFallbackModelId);
2763
+ this.cloudQuotaFallbackModelId = readNonEmptyString2(dependencies.cloudQuotaFallbackModelId);
2716
2764
  this.modelCatalog = dependencies.modelCatalog ?? createEmptyModelCatalog();
2717
2765
  this.modelResolver = dependencies.modelResolver ?? new ModelResolver({
2718
2766
  modelCatalog: this.modelCatalog
@@ -2760,7 +2808,7 @@ var GraphAgentExecutor = class {
2760
2808
  llmMessages: [],
2761
2809
  mode: input.request.mode === "chat" ? "chat" : "agent",
2762
2810
  conversationId: resolveConversationIdForRuntimeEvents(input.toolContext),
2763
- turnId: readNonEmptyString(input.toolContext?.turnId) ?? `turn_${Date.now()}`,
2811
+ turnId: readNonEmptyString2(input.toolContext?.turnId) ?? `turn_${Date.now()}`,
2764
2812
  telemetry: this.telemetryPort,
2765
2813
  audit: this.auditPort
2766
2814
  };
@@ -2810,18 +2858,18 @@ function isSummarizationCallbacks(value) {
2810
2858
  function isGraphSseSink(value) {
2811
2859
  return typeof value === "function";
2812
2860
  }
2813
- function readNonEmptyString2(value) {
2861
+ function readNonEmptyString3(value) {
2814
2862
  if (typeof value !== "string") return void 0;
2815
2863
  const trimmed = value.trim();
2816
2864
  return trimmed.length > 0 ? trimmed : void 0;
2817
2865
  }
2818
2866
  function readGraphAgentLocal(local) {
2819
2867
  const source = local ?? {};
2820
- const answerId = readNonEmptyString2(source.answerId);
2868
+ const answerId = readNonEmptyString3(source.answerId);
2821
2869
  const chunkSeq = Number.isInteger(source.chunkSeq) ? Number(source.chunkSeq) : 0;
2822
2870
  return {
2823
- conversationId: readNonEmptyString2(source.conversationId) ?? "",
2824
- turnId: readNonEmptyString2(source.turnId),
2871
+ conversationId: readNonEmptyString3(source.conversationId) ?? "",
2872
+ turnId: readNonEmptyString3(source.turnId),
2825
2873
  request: isAgentInvocationRequest(source.request) ? source.request : void 0,
2826
2874
  toolContext: isToolExecutionContext(source.toolContext) ? source.toolContext : void 0,
2827
2875
  history: isRuntimeEventArray(source.history) ? source.history : [],
@@ -3586,7 +3634,7 @@ var LlmNode = class {
3586
3634
  function isRecord8(value) {
3587
3635
  return typeof value === "object" && value !== null && !Array.isArray(value);
3588
3636
  }
3589
- function readNonEmptyString3(value) {
3637
+ function readNonEmptyString4(value) {
3590
3638
  if (typeof value !== "string") {
3591
3639
  return void 0;
3592
3640
  }
@@ -3608,7 +3656,7 @@ function resolveFinalAnswerFromToolResult(toolName, parsedResult) {
3608
3656
  return void 0;
3609
3657
  }
3610
3658
  if (toolName === "write_report") {
3611
- const report = readNonEmptyString3(data.report);
3659
+ const report = readNonEmptyString4(data.report);
3612
3660
  if (!report) {
3613
3661
  throw new Error("[write_report] \u5DE5\u5177\u8F93\u51FA\u7F3A\u5C11 data.report\uFF08\u5FC5\u987B\u63D0\u4F9B\u5B8C\u6574\u62A5\u544A\u6B63\u6587\uFF09");
3614
3662
  }
@@ -3618,7 +3666,7 @@ function resolveFinalAnswerFromToolResult(toolName, parsedResult) {
3618
3666
  if (data.success !== true) {
3619
3667
  return void 0;
3620
3668
  }
3621
- const finalAnswer = readNonEmptyString3(data.final_answer);
3669
+ const finalAnswer = readNonEmptyString4(data.final_answer);
3622
3670
  if (!finalAnswer) {
3623
3671
  throw new Error("[research_run_writer] \u5DE5\u5177\u8F93\u51FA\u7F3A\u5C11 data.final_answer\uFF08success=true \u65F6\u5FC5\u987B\u63D0\u4F9B\u6700\u7EC8\u62A5\u544A\u6B63\u6587\uFF09");
3624
3672
  }
@@ -4163,6 +4211,31 @@ function ensureToolContextRuntimeCapability(params) {
4163
4211
  function getToolContextRuntimeBinding(context) {
4164
4212
  return readBinding(context);
4165
4213
  }
4214
+ function copyToolContextRuntimeCapability(source, target) {
4215
+ const sourceBinding = readBinding(source);
4216
+ if (!sourceBinding) {
4217
+ return void 0;
4218
+ }
4219
+ const existingTargetBinding = readBinding(target);
4220
+ if (existingTargetBinding) {
4221
+ exposeCompatibilitySurface(target, existingTargetBinding);
4222
+ return existingTargetBinding;
4223
+ }
4224
+ const targetBinding = createRuntimeBinding({
4225
+ context: target,
4226
+ persistedHistory: () => sourceBinding.getPersistedHistoryEvents(),
4227
+ workingHistory: () => sourceBinding.getWorkingHistoryEvents(),
4228
+ executionMeta: sourceBinding.readExecutionMeta()
4229
+ });
4230
+ Object.defineProperty(target, TOOL_CONTEXT_RUNTIME_BINDING_KEY, {
4231
+ value: targetBinding,
4232
+ enumerable: false,
4233
+ configurable: true,
4234
+ writable: false
4235
+ });
4236
+ exposeCompatibilitySurface(target, targetBinding);
4237
+ return targetBinding;
4238
+ }
4166
4239
  function readToolContextWorkingHistory(context) {
4167
4240
  if (context.conversationView) {
4168
4241
  return context.conversationView.getWorkingHistoryEvents();
@@ -5014,12 +5087,12 @@ function asRecord(value) {
5014
5087
  }
5015
5088
  return value;
5016
5089
  }
5017
- function summarizeCheckpoint(conversationId, state, savedAt) {
5090
+ function summarizeCheckpoint(checkpointKey, state, savedAt) {
5018
5091
  const local = asRecord(state.local);
5019
5092
  const executorLocal = asRecord(local?.executorLocal);
5020
5093
  const pendingToolCalls = local?.pendingToolCalls;
5021
5094
  return {
5022
- conversationId,
5095
+ checkpointKey,
5023
5096
  schemaVersion: state.schemaVersion ?? 1,
5024
5097
  savedAt,
5025
5098
  currentNode: state.nodeId,
@@ -5038,25 +5111,25 @@ var MemoryCheckpointer = class {
5038
5111
  local: state.local && typeof state.local === "object" && !Array.isArray(state.local) ? { ...state.local } : state.local
5039
5112
  };
5040
5113
  }
5041
- async load(conversationId) {
5042
- const entry = this.store.get(conversationId);
5114
+ async load(checkpointKey) {
5115
+ const entry = this.store.get(checkpointKey);
5043
5116
  return entry ? this.cloneState(entry.state) : null;
5044
5117
  }
5045
- async save(conversationId, state) {
5046
- this.store.set(conversationId, {
5118
+ async save(checkpointKey, state) {
5119
+ this.store.set(checkpointKey, {
5047
5120
  state: this.cloneState(state),
5048
5121
  savedAt: Date.now()
5049
5122
  });
5050
5123
  }
5051
- async clear(conversationId) {
5052
- this.store.delete(conversationId);
5124
+ async clear(checkpointKey) {
5125
+ this.store.delete(checkpointKey);
5053
5126
  }
5054
- async peekMeta(conversationId) {
5055
- const entry = this.store.get(conversationId);
5056
- return entry ? summarizeCheckpoint(conversationId, entry.state, entry.savedAt) : null;
5127
+ async peekMeta(checkpointKey) {
5128
+ const entry = this.store.get(checkpointKey);
5129
+ return entry ? summarizeCheckpoint(checkpointKey, entry.state, entry.savedAt) : null;
5057
5130
  }
5058
5131
  async list(filter = {}) {
5059
- const summaries = Array.from(this.store.entries()).map(([conversationId, entry]) => summarizeCheckpoint(conversationId, entry.state, entry.savedAt)).filter((summary) => filter.savedAfter === void 0 ? true : summary.savedAt > filter.savedAfter).sort((left, right) => right.savedAt - left.savedAt);
5132
+ const summaries = Array.from(this.store.entries()).map(([checkpointKey, entry]) => summarizeCheckpoint(checkpointKey, entry.state, entry.savedAt)).filter((summary) => filter.savedAfter === void 0 ? true : summary.savedAt > filter.savedAfter).sort((left, right) => right.savedAt - left.savedAt);
5060
5133
  if (filter.limit === void 0) {
5061
5134
  return summaries;
5062
5135
  }
@@ -5128,6 +5201,7 @@ __export(tools_exports, {
5128
5201
  CommonParameterTypes: () => CommonParameterTypes,
5129
5202
  ContextCheckpointTool: () => ContextCheckpointTool,
5130
5203
  computeToolIdempotencyKey: () => computeToolIdempotencyKey,
5204
+ copyToolContextRuntimeCapability: () => copyToolContextRuntimeCapability,
5131
5205
  createContextCheckpointTool: () => createContextCheckpointTool,
5132
5206
  ensureToolContextRuntimeCapability: () => ensureToolContextRuntimeCapability,
5133
5207
  findCachedToolOutputByIdempotencyKey: () => findCachedToolOutputByIdempotencyKey,
@@ -5321,7 +5395,7 @@ function createContextCheckpointTool(options) {
5321
5395
  function isRecord15(value) {
5322
5396
  return !!value && typeof value === "object" && !Array.isArray(value);
5323
5397
  }
5324
- function readNonEmptyString4(value) {
5398
+ function readNonEmptyString5(value) {
5325
5399
  if (typeof value !== "string") {
5326
5400
  return void 0;
5327
5401
  }
@@ -5341,13 +5415,13 @@ function readToolContextUserQuery(context) {
5341
5415
  if (!context) {
5342
5416
  return void 0;
5343
5417
  }
5344
- return readNonEmptyString4(context["user_query"]);
5418
+ return readNonEmptyString5(context["user_query"]);
5345
5419
  }
5346
5420
  function readToolContextModelId(context) {
5347
5421
  if (!context) {
5348
5422
  return void 0;
5349
5423
  }
5350
- return readNonEmptyString4(context["modelId"]);
5424
+ return readNonEmptyString5(context["modelId"]);
5351
5425
  }
5352
5426
  function readToolContextRunContext(context) {
5353
5427
  if (!context) {
@@ -7055,6 +7129,7 @@ var DefaultTokenizerPort = class {
7055
7129
  constructor(config = {}) {
7056
7130
  this.config = config;
7057
7131
  }
7132
+ config;
7058
7133
  estimateText(text, _modelId) {
7059
7134
  return TokenCalculator.estimateTokens(text, {
7060
7135
  encoding: this.config.encoding,
@@ -7082,7 +7157,6 @@ __export(child_runs_exports, {
7082
7157
 
7083
7158
  // src/runtime-kernel/child-runs/childToolContext.ts
7084
7159
  function createChildRunToolContext(params) {
7085
- const inheritedConversationId = typeof params.parentToolContext.conversationId === "string" && params.parentToolContext.conversationId.trim().length > 0 ? params.parentToolContext.conversationId.trim() : void 0;
7086
7160
  const inheritedContext = stripRuntimeReservedToolContextPatch(params.parentToolContext);
7087
7161
  const childToolContext = {
7088
7162
  ...inheritedContext,
@@ -7094,7 +7168,7 @@ function createChildRunToolContext(params) {
7094
7168
  persistedHistory: params.seedHistory,
7095
7169
  workingHistory: params.seedHistory,
7096
7170
  executionMeta: {
7097
- conversationId: inheritedConversationId ?? params.internalConversationId,
7171
+ conversationId: params.conversationId,
7098
7172
  turnId: params.turnId,
7099
7173
  runId: params.runId,
7100
7174
  parentRunId: params.parentRunId
@@ -7196,6 +7270,8 @@ var FinalAnswerCollector = class {
7196
7270
  this.conversationId = conversationId;
7197
7271
  this.turnId = turnId;
7198
7272
  }
7273
+ conversationId;
7274
+ turnId;
7199
7275
  answerId;
7200
7276
  chunks = [];
7201
7277
  chunkCount = 0;
@@ -7412,7 +7488,7 @@ function readCheckpointHistory(checkpoint) {
7412
7488
  });
7413
7489
  }
7414
7490
  async function recoverChildRunEventsFromCheckpoint(params) {
7415
- const checkpoint = await params.checkpointer.load(params.conversationId);
7491
+ const checkpoint = await params.checkpointer.load(params.checkpointKey);
7416
7492
  const history = readCheckpointHistory(checkpoint);
7417
7493
  if (history.length === 0) {
7418
7494
  return [];
@@ -7420,7 +7496,7 @@ async function recoverChildRunEventsFromCheckpoint(params) {
7420
7496
  if (hasSeedHistoryPrefix(history, params.seedHistory)) {
7421
7497
  return history.slice(params.seedHistory.length);
7422
7498
  }
7423
- return history.filter((event) => event.conversation_id === params.internalConversationId);
7499
+ return history.filter((event) => event.conversation_id === params.childConversationId);
7424
7500
  }
7425
7501
 
7426
7502
  // src/runtime-kernel/child-runs/childRunInvoker.ts
@@ -7449,6 +7525,7 @@ var ChildRunInvoker = class {
7449
7525
  agentConfig,
7450
7526
  userMessage,
7451
7527
  parentToolContext,
7528
+ conversationId,
7452
7529
  runId,
7453
7530
  parentRunId,
7454
7531
  subrunTracePublisher,
@@ -7457,12 +7534,18 @@ var ChildRunInvoker = class {
7457
7534
  modelId,
7458
7535
  abortSignal
7459
7536
  } = config;
7460
- const internalConversationId = `internal_${generateMessageId()}`;
7537
+ const internalCheckpointKey = `internal_${generateMessageId()}`;
7538
+ const runtimeConversationId = resolveChildRunConversationId({
7539
+ explicitConversationId: conversationId,
7540
+ parentToolContext,
7541
+ fallbackConversationId: internalCheckpointKey
7542
+ });
7461
7543
  const turnId = `turn_${Date.now()}`;
7462
- const childRunId = typeof runId === "string" && runId.trim().length > 0 ? runId.trim() : internalConversationId;
7544
+ const childRunId = typeof runId === "string" && runId.trim().length > 0 ? runId.trim() : internalCheckpointKey;
7463
7545
  const resolvedParentRunId = typeof parentRunId === "string" && parentRunId.trim().length > 0 ? parentRunId.trim() : typeof parentToolContext.runId === "string" && parentToolContext.runId.trim().length > 0 ? parentToolContext.runId.trim() : void 0;
7464
7546
  logger13.info(`\u542F\u52A8 child-run: ${agentConfig.id}`, {
7465
- conversationId: internalConversationId,
7547
+ conversationId: runtimeConversationId,
7548
+ checkpointKey: internalCheckpointKey,
7466
7549
  maxSteps,
7467
7550
  userMessage: userMessage.slice(0, 100) + (userMessage.length > 100 ? "..." : "")
7468
7551
  });
@@ -7523,7 +7606,7 @@ var ChildRunInvoker = class {
7523
7606
  const seedHistory = Array.isArray(seedHistoryEvents) ? seedHistoryEvents : [];
7524
7607
  const childToolContext = createChildRunToolContext({
7525
7608
  parentToolContext,
7526
- internalConversationId,
7609
+ conversationId: runtimeConversationId,
7527
7610
  turnId,
7528
7611
  runId: childRunId,
7529
7612
  parentRunId: resolvedParentRunId,
@@ -7532,13 +7615,13 @@ var ChildRunInvoker = class {
7532
7615
  });
7533
7616
  const subrunSseSink = subrunTracePublisher ? createChildRunTraceSink({
7534
7617
  publisher: subrunTracePublisher,
7535
- conversationId: internalConversationId,
7618
+ conversationId: runtimeConversationId,
7536
7619
  turnId
7537
7620
  }) : void 0;
7538
7621
  const initialLocal = {
7539
7622
  request,
7540
7623
  history: seedHistory,
7541
- conversationId: internalConversationId,
7624
+ conversationId: runtimeConversationId,
7542
7625
  turnId,
7543
7626
  toolContext: childToolContext,
7544
7627
  ...abortSignal ? { signal: abortSignal } : {},
@@ -7546,7 +7629,7 @@ var ChildRunInvoker = class {
7546
7629
  ...subrunSseSink ? { sseSink: subrunSseSink } : {},
7547
7630
  systemPrompt
7548
7631
  };
7549
- await graphExecutor.prime(internalConversationId, initialLocal, "llm");
7632
+ await graphExecutor.prime(internalCheckpointKey, initialLocal, "llm");
7550
7633
  const allEvents = [];
7551
7634
  let stepCount = 0;
7552
7635
  let finalAnswer;
@@ -7558,7 +7641,7 @@ var ChildRunInvoker = class {
7558
7641
  err.name = "AbortError";
7559
7642
  throw err;
7560
7643
  }
7561
- const result = await graphExecutor.runUntilYield(internalConversationId);
7644
+ const result = await graphExecutor.runUntilYield(internalCheckpointKey);
7562
7645
  appendUniqueEvents(allEvents, result.events);
7563
7646
  stepCount = result.stepCount;
7564
7647
  if (subrunSseSink && typeof subrunSseSink.finalize === "function") {
@@ -7592,8 +7675,8 @@ var ChildRunInvoker = class {
7592
7675
  }
7593
7676
  const recoveredEvents = await recoverChildRunEventsFromCheckpoint({
7594
7677
  checkpointer,
7595
- conversationId: internalConversationId,
7596
- internalConversationId,
7678
+ checkpointKey: internalCheckpointKey,
7679
+ childConversationId: runtimeConversationId,
7597
7680
  seedHistory
7598
7681
  });
7599
7682
  appendUniqueEvents(allEvents, recoveredEvents);
@@ -7610,7 +7693,7 @@ var ChildRunInvoker = class {
7610
7693
  stack: err.stack
7611
7694
  } : { error: String(err) });
7612
7695
  }
7613
- await checkpointer.clear(internalConversationId);
7696
+ await checkpointer.clear(internalCheckpointKey);
7614
7697
  return {
7615
7698
  success: !error,
7616
7699
  runId: childRunId,
@@ -7623,6 +7706,16 @@ var ChildRunInvoker = class {
7623
7706
  };
7624
7707
  }
7625
7708
  };
7709
+ function readNonEmptyString6(value) {
7710
+ if (typeof value !== "string") {
7711
+ return void 0;
7712
+ }
7713
+ const trimmed = value.trim();
7714
+ return trimmed.length > 0 ? trimmed : void 0;
7715
+ }
7716
+ function resolveChildRunConversationId(params) {
7717
+ return readNonEmptyString6(params.explicitConversationId) ?? readNonEmptyString6(params.parentToolContext.conversationId) ?? params.fallbackConversationId;
7718
+ }
7626
7719
  function resolveChildRunSystemReminderPolicy(agentConfig) {
7627
7720
  const configured = agentConfig.systemReminderPolicy ?? agentConfig.contextPolicy?.systemReminder;
7628
7721
  const threshold = agentConfig.stepPolicy?.lastStepsHintThreshold;
@@ -7813,7 +7906,7 @@ function cloneRunRecord(record) {
7813
7906
  ...record,
7814
7907
  iterationBudget: record.iterationBudget ? { ...record.iterationBudget } : void 0,
7815
7908
  errorIfAny: record.errorIfAny ? { ...record.errorIfAny } : void 0,
7816
- metadata: record.metadata ? { ...record.metadata } : void 0
7909
+ metadata: record.metadata ? structuredClone(record.metadata) : void 0
7817
7910
  };
7818
7911
  }
7819
7912
  function matchesStatus(candidate, filter) {
@@ -8225,7 +8318,7 @@ function isTerminalStatus(status) {
8225
8318
  return status === "completed" || status === "failed" || status === "cancelled";
8226
8319
  }
8227
8320
  function cloneMetadata(metadata) {
8228
- return metadata ? { ...metadata } : void 0;
8321
+ return metadata ? structuredClone(metadata) : void 0;
8229
8322
  }
8230
8323
  function recordToSnapshot(record) {
8231
8324
  return {
@@ -8312,7 +8405,7 @@ var DefaultRunSupervisor = class {
8312
8405
  startedAt,
8313
8406
  updatedAt: startedAt,
8314
8407
  iterationBudget: spec.iterationBudget ? { ...spec.iterationBudget } : void 0,
8315
- metadata: spec.metadata ? { ...spec.metadata } : void 0
8408
+ metadata: cloneMetadata(spec.metadata)
8316
8409
  };
8317
8410
  await this.registryStore.save(record);
8318
8411
  const handle = new DefaultRunHandle({
@@ -8486,12 +8579,13 @@ var DefaultRunSupervisor = class {
8486
8579
  }
8487
8580
  try {
8488
8581
  await handle.markRunning({ currentNode: "detached" });
8582
+ const registeredRecord = await this.registryStore.load(handle.runId);
8489
8583
  const executorOutcome = await this.executor.execute({
8490
8584
  runId: handle.runId,
8491
- parentRunId: spec.parentRunId,
8492
- conversationId: spec.conversationId,
8493
- agentSpec: spec.agentSpec,
8494
- request: spec.request,
8585
+ parentRunId: handle.parentRunId,
8586
+ conversationId: registeredRecord?.conversationId ?? spec.conversationId,
8587
+ agentSpec: await handle.spec(),
8588
+ request: await handle.request(),
8495
8589
  signal: handle.signal,
8496
8590
  eventBus: spec.eventBus,
8497
8591
  eventStore: spec.eventStore,
@@ -8500,7 +8594,7 @@ var DefaultRunSupervisor = class {
8500
8594
  contextFences: spec.contextFences,
8501
8595
  wakeSource: spec.wakeSource,
8502
8596
  ephemeral: spec.ephemeral,
8503
- metadata: spec.metadata
8597
+ metadata: cloneMetadata(registeredRecord?.metadata ?? spec.metadata)
8504
8598
  });
8505
8599
  const outcome = await this.persistExecutorOutcome(handle, executorOutcome);
8506
8600
  this.notifyTerminalWaiters(outcome);
@@ -8564,10 +8658,14 @@ var DefaultRunSupervisor = class {
8564
8658
  await this.registryStore.save(record);
8565
8659
  }
8566
8660
  const completedAt = executorOutcome?.completedAt ?? this.now();
8661
+ const fallbackMeta = record ? void 0 : await handle.meta();
8567
8662
  const outcome = recordToTerminalOutcome(record ?? {
8568
8663
  runId: handle.runId,
8569
8664
  parentRunId: handle.parentRunId,
8570
- status: executorOutcome?.status ?? "completed"}, completedAt);
8665
+ conversationId: fallbackMeta?.conversationId ?? "",
8666
+ agentSpecId: fallbackMeta?.agentSpecId,
8667
+ status: executorOutcome?.status ?? "completed",
8668
+ startedAt: fallbackMeta?.startedAt ?? completedAt}, completedAt);
8571
8669
  const nextOutcome = {
8572
8670
  ...outcome,
8573
8671
  metadata: {
@@ -8795,6 +8893,7 @@ function createGraphLoopHarness(options) {
8795
8893
  };
8796
8894
  return {
8797
8895
  async run() {
8896
+ const checkpointKey = options.conversationId;
8798
8897
  const executor = createDefaultGraphExecutor({
8799
8898
  llmNode: options.createLlmNode({
8800
8899
  llmCaller: options.llmCaller,
@@ -8823,8 +8922,8 @@ function createGraphLoopHarness(options) {
8823
8922
  signal: options.signal ?? options.toolContext.abortSignal,
8824
8923
  executorLocal
8825
8924
  };
8826
- await executor.prime(options.conversationId, local, "user");
8827
- const result = await executor.runUntilYield(options.conversationId);
8925
+ await executor.prime(checkpointKey, local, "user");
8926
+ const result = await executor.runUntilYield(checkpointKey);
8828
8927
  return {
8829
8928
  checkpointNodeId: result.checkpoint.nodeId,
8830
8929
  stepCount: result.stepCount