@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/cli.cjs CHANGED
@@ -203,6 +203,7 @@ var AgentSpecBudgetPolicy = zod.z.object({
203
203
  });
204
204
  var AgentSpecToolHistoryPolicy = zod.z.object({
205
205
  strategy: zod.z.enum(["per-pair", "per-run", "none"]).optional(),
206
+ retentionMode: zod.z.enum(["drop", "compress"]).optional(),
206
207
  keepLatestToolPairs: zod.z.number().int().nonnegative().optional(),
207
208
  keepLatestRuns: zod.z.number().int().nonnegative().optional(),
208
209
  maxInteractionGroups: zod.z.number().int().nonnegative().optional(),
@@ -1084,6 +1085,7 @@ var Logger = class {
1084
1085
  constructor(moduleName) {
1085
1086
  this.moduleName = moduleName;
1086
1087
  }
1088
+ moduleName;
1087
1089
  debug(message, data) {
1088
1090
  this.log(0 /* DEBUG */, "debug", message, data);
1089
1091
  }
@@ -1156,6 +1158,17 @@ var logger = new Logger("GraphExecutor");
1156
1158
  function asLocalRecord(local) {
1157
1159
  return local && typeof local === "object" ? { ...local } : {};
1158
1160
  }
1161
+ function readNonEmptyString(value) {
1162
+ return typeof value === "string" && value.trim().length > 0 ? value : void 0;
1163
+ }
1164
+ function readRuntimeConversationId(state) {
1165
+ const local = state?.local && typeof state.local === "object" ? state.local : void 0;
1166
+ return readNonEmptyString(local?.conversationId);
1167
+ }
1168
+ function readRuntimeTurnId(state) {
1169
+ const local = state?.local && typeof state.local === "object" ? state.local : void 0;
1170
+ return readNonEmptyString(local?.turnId);
1171
+ }
1159
1172
  var GraphExecutor = class {
1160
1173
  constructor(checkpointer, config = {}) {
1161
1174
  this.checkpointer = checkpointer;
@@ -1165,6 +1178,7 @@ var GraphExecutor = class {
1165
1178
  };
1166
1179
  this.telemetryPort = config.telemetryPort ?? noopTelemetry;
1167
1180
  }
1181
+ checkpointer;
1168
1182
  nodes = /* @__PURE__ */ new Map();
1169
1183
  ephemeralLocals = /* @__PURE__ */ new Map();
1170
1184
  config;
@@ -1172,8 +1186,8 @@ var GraphExecutor = class {
1172
1186
  registerNode(node) {
1173
1187
  this.nodes.set(node.id, node);
1174
1188
  }
1175
- async peekCheckpoint(conversationId) {
1176
- return await this.checkpointer.load(conversationId);
1189
+ async peekCheckpoint(checkpointKey) {
1190
+ return await this.checkpointer.load(checkpointKey);
1177
1191
  }
1178
1192
  sanitize(state) {
1179
1193
  const local = asLocalRecord(state.local);
@@ -1185,8 +1199,8 @@ var GraphExecutor = class {
1185
1199
  local
1186
1200
  };
1187
1201
  }
1188
- async prime(conversationId, local, nodeId = "user") {
1189
- this.ephemeralLocals.set(conversationId, { ...local || {} });
1202
+ async prime(checkpointKey, local, nodeId = "user") {
1203
+ this.ephemeralLocals.set(checkpointKey, { ...local || {} });
1190
1204
  const localSansMemory = { ...local || {} };
1191
1205
  if ("memory" in localSansMemory) delete localSansMemory.memory;
1192
1206
  const state = {
@@ -1194,10 +1208,10 @@ var GraphExecutor = class {
1194
1208
  schemaVersion: ENGINE_STATE_SCHEMA_VERSION,
1195
1209
  local: localSansMemory
1196
1210
  };
1197
- await this.checkpointer.save(conversationId, state);
1211
+ await this.checkpointer.save(checkpointKey, state);
1198
1212
  }
1199
- async setNode(conversationId, nodeId, localPatch) {
1200
- const current = await this.checkpointer.load(conversationId) || {
1213
+ async setNode(checkpointKey, nodeId, localPatch) {
1214
+ const current = await this.checkpointer.load(checkpointKey) || {
1201
1215
  schemaVersion: ENGINE_STATE_SCHEMA_VERSION,
1202
1216
  local: {}
1203
1217
  };
@@ -1208,19 +1222,46 @@ var GraphExecutor = class {
1208
1222
  schemaVersion: current.schemaVersion ?? ENGINE_STATE_SCHEMA_VERSION,
1209
1223
  local: mergedLocal
1210
1224
  };
1211
- await this.checkpointer.save(conversationId, next);
1225
+ await this.checkpointer.save(checkpointKey, next);
1212
1226
  }
1213
- async runUntilYield(conversationId) {
1227
+ async runUntilYield(checkpointKey) {
1214
1228
  const runId = `run_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
1215
1229
  let lifecyclePhase = "completed";
1230
+ let initialState = null;
1231
+ try {
1232
+ initialState = await this.loadInitialState(checkpointKey);
1233
+ } catch (err) {
1234
+ lifecyclePhase = "failed";
1235
+ this.telemetryPort.emit({
1236
+ kind: "run_lifecycle",
1237
+ runId,
1238
+ phase: "spawned",
1239
+ scope: {}
1240
+ });
1241
+ this.telemetryPort.emit({
1242
+ kind: "run_lifecycle",
1243
+ runId,
1244
+ phase: lifecyclePhase,
1245
+ scope: {}
1246
+ });
1247
+ throw err;
1248
+ }
1249
+ let lifecycleConversationId = readRuntimeConversationId(initialState);
1250
+ let lifecycleTurnId = readRuntimeTurnId(initialState);
1216
1251
  this.telemetryPort.emit({
1217
1252
  kind: "run_lifecycle",
1218
1253
  runId,
1219
1254
  phase: "spawned",
1220
- scope: { conversationId: conversationId || void 0 }
1255
+ scope: {
1256
+ conversationId: lifecycleConversationId,
1257
+ turnId: lifecycleTurnId
1258
+ }
1221
1259
  });
1222
1260
  try {
1223
- return await this.runUntilYieldInternal(conversationId);
1261
+ const result = await this.runUntilYieldInternal(checkpointKey, initialState);
1262
+ lifecycleConversationId = readRuntimeConversationId(result.checkpoint);
1263
+ lifecycleTurnId = readRuntimeTurnId(result.checkpoint);
1264
+ return result;
1224
1265
  } catch (err) {
1225
1266
  lifecyclePhase = err?.name === "AbortError" ? "cancelled" : "failed";
1226
1267
  throw err;
@@ -1229,17 +1270,23 @@ var GraphExecutor = class {
1229
1270
  kind: "run_lifecycle",
1230
1271
  runId,
1231
1272
  phase: lifecyclePhase,
1232
- scope: { conversationId: conversationId || void 0 }
1273
+ scope: {
1274
+ conversationId: lifecycleConversationId,
1275
+ turnId: lifecycleTurnId
1276
+ }
1233
1277
  });
1234
1278
  }
1235
1279
  }
1236
- async runUntilYieldInternal(conversationId) {
1237
- let state = await this.checkpointer.load(conversationId) || {
1280
+ async loadInitialState(checkpointKey) {
1281
+ return await this.checkpointer.load(checkpointKey) || {
1238
1282
  nodeId: "user",
1239
1283
  schemaVersion: ENGINE_STATE_SCHEMA_VERSION,
1240
1284
  local: {}
1241
1285
  };
1242
- const ephemeral = this.ephemeralLocals.get(conversationId) || {};
1286
+ }
1287
+ async runUntilYieldInternal(checkpointKey, initialState) {
1288
+ let state = initialState;
1289
+ const ephemeral = this.ephemeralLocals.get(checkpointKey) || {};
1243
1290
  state = {
1244
1291
  ...state,
1245
1292
  schemaVersion: state.schemaVersion ?? ENGINE_STATE_SCHEMA_VERSION,
@@ -1268,7 +1315,7 @@ var GraphExecutor = class {
1268
1315
  const signalRaw = state.local?.signal;
1269
1316
  if (isAbortSignal2(signalRaw) && signalRaw.aborted) {
1270
1317
  logger.warn("[GraphExecutor] \u6536\u5230 AbortSignal\uFF0C\u7ACB\u5373\u505C\u6B62\u63A8\u7406\u5FAA\u73AF");
1271
- this.ephemeralLocals.delete(conversationId);
1318
+ this.ephemeralLocals.delete(checkpointKey);
1272
1319
  throwAbortError();
1273
1320
  }
1274
1321
  const isLastStep = cycleStepCount >= this.config.maxSteps;
@@ -1316,8 +1363,8 @@ var GraphExecutor = class {
1316
1363
  checkpointCount
1317
1364
  });
1318
1365
  const cp2 = this.sanitize(state);
1319
- await this.checkpointer.save(conversationId, cp2);
1320
- this.ephemeralLocals.delete(conversationId);
1366
+ await this.checkpointer.save(checkpointKey, cp2);
1367
+ this.ephemeralLocals.delete(checkpointKey);
1321
1368
  return { events: allEvents, checkpoint: cp2, stepCount };
1322
1369
  }
1323
1370
  logger.info("[GraphExecutor] \u8282\u70B9\u5207\u6362", {
@@ -1328,18 +1375,18 @@ var GraphExecutor = class {
1328
1375
  });
1329
1376
  const nodeRunStartedAt = Date.now();
1330
1377
  const nodeIdForTelemetry = state.nodeId;
1378
+ const conversationIdForTelemetry = readRuntimeConversationId(state);
1331
1379
  let result;
1332
1380
  try {
1333
1381
  result = await node.run(state);
1334
1382
  } finally {
1335
- const turnIdForTelemetry = typeof state.local?.turnId === "string" ? state.local.turnId : void 0;
1336
1383
  this.telemetryPort.emit({
1337
1384
  kind: "graph_node",
1338
1385
  nodeId: nodeIdForTelemetry,
1339
1386
  durationMs: Date.now() - nodeRunStartedAt,
1340
1387
  scope: {
1341
- conversationId: conversationId || void 0,
1342
- turnId: turnIdForTelemetry
1388
+ conversationId: conversationIdForTelemetry,
1389
+ turnId: readRuntimeTurnId(state)
1343
1390
  }
1344
1391
  });
1345
1392
  }
@@ -1378,7 +1425,7 @@ var GraphExecutor = class {
1378
1425
  });
1379
1426
  state = { ...state, nodeId: nextNodeId };
1380
1427
  const cp2 = this.sanitize(state);
1381
- await this.checkpointer.save(conversationId, cp2);
1428
+ await this.checkpointer.save(checkpointKey, cp2);
1382
1429
  continue;
1383
1430
  }
1384
1431
  if (result.kind === "yield") {
@@ -1389,7 +1436,7 @@ var GraphExecutor = class {
1389
1436
  checkpointCount
1390
1437
  });
1391
1438
  const cp2 = this.sanitize(state);
1392
- await this.checkpointer.save(conversationId, cp2);
1439
+ await this.checkpointer.save(checkpointKey, cp2);
1393
1440
  return { events: allEvents, checkpoint: cp2, stepCount };
1394
1441
  }
1395
1442
  if (result.kind === "pause") {
@@ -1400,7 +1447,7 @@ var GraphExecutor = class {
1400
1447
  checkpointCount
1401
1448
  });
1402
1449
  const cp2 = this.sanitize(state);
1403
- await this.checkpointer.save(conversationId, cp2);
1450
+ await this.checkpointer.save(checkpointKey, cp2);
1404
1451
  return { events: allEvents, checkpoint: cp2, stepCount };
1405
1452
  }
1406
1453
  }
@@ -1411,8 +1458,8 @@ var GraphExecutor = class {
1411
1458
  checkpointCount
1412
1459
  });
1413
1460
  const cp = this.sanitize(state);
1414
- await this.checkpointer.save(conversationId, cp);
1415
- this.ephemeralLocals.delete(conversationId);
1461
+ await this.checkpointer.save(checkpointKey, cp);
1462
+ this.ephemeralLocals.delete(checkpointKey);
1416
1463
  return { events: allEvents, checkpoint: cp, stepCount };
1417
1464
  }
1418
1465
  };
@@ -1575,15 +1622,15 @@ function splitConcatenatedJsonObjects(input) {
1575
1622
  }
1576
1623
 
1577
1624
  // src/runtime-kernel/graph-engine/tick-pipeline/helpers.ts
1578
- function readNonEmptyString(value) {
1625
+ function readNonEmptyString2(value) {
1579
1626
  if (typeof value !== "string") return void 0;
1580
1627
  const trimmed = value.trim();
1581
1628
  return trimmed.length > 0 ? trimmed : void 0;
1582
1629
  }
1583
1630
  function resolveConversationIdForRuntimeEvents(toolContext) {
1584
- const fromCamel = readNonEmptyString(toolContext?.conversationId);
1631
+ const fromCamel = readNonEmptyString2(toolContext?.conversationId);
1585
1632
  if (fromCamel) return fromCamel;
1586
- const fromSnake = toolContext ? readNonEmptyString(toolContext["conversation_id"]) : void 0;
1633
+ const fromSnake = toolContext ? readNonEmptyString2(toolContext["conversation_id"]) : void 0;
1587
1634
  if (fromSnake) return fromSnake;
1588
1635
  return generateMessageId();
1589
1636
  }
@@ -1940,7 +1987,7 @@ var runModelLockMiddleware = async (ctx, stage, next) => {
1940
1987
  if (stage.id !== "execute_llm") {
1941
1988
  return;
1942
1989
  }
1943
- const normalized = readNonEmptyString(ctx.cloudQuotaFallbackAppliedModelId);
1990
+ const normalized = readNonEmptyString2(ctx.cloudQuotaFallbackAppliedModelId);
1944
1991
  if (!normalized) {
1945
1992
  return;
1946
1993
  }
@@ -2528,7 +2575,7 @@ function createExecuteLlmStage(dependencies) {
2528
2575
  streamEventHandler,
2529
2576
  ctx.signal,
2530
2577
  (fallbackModelId) => {
2531
- ctx.cloudQuotaFallbackAppliedModelId = readNonEmptyString(fallbackModelId);
2578
+ ctx.cloudQuotaFallbackAppliedModelId = readNonEmptyString2(fallbackModelId);
2532
2579
  },
2533
2580
  (info) => {
2534
2581
  ctx.modelFallbackAudit = info;
@@ -2572,7 +2619,7 @@ function createPrepareCallStage(dependencies) {
2572
2619
  return {
2573
2620
  id: "prepare_call",
2574
2621
  async run(ctx) {
2575
- const lockedRunModelId = readNonEmptyString(ctx.executorLocal?.runLockedModelId);
2622
+ const lockedRunModelId = readNonEmptyString2(ctx.executorLocal?.runLockedModelId);
2576
2623
  const requestedModelId = lockedRunModelId ?? ctx.request.model_id;
2577
2624
  ctx.modelId = dependencies.modelResolver.resolveModelId(requestedModelId);
2578
2625
  await emitAuditEnvelope(ctx.audit, {
@@ -2644,7 +2691,7 @@ var GraphAgentExecutor = class {
2644
2691
  this.llmCaller = dependencies.llmCaller;
2645
2692
  this.toolRuntime = dependencies.toolRuntime;
2646
2693
  this.contextBuilder = dependencies.contextBuilder;
2647
- this.cloudQuotaFallbackModelId = readNonEmptyString(dependencies.cloudQuotaFallbackModelId);
2694
+ this.cloudQuotaFallbackModelId = readNonEmptyString2(dependencies.cloudQuotaFallbackModelId);
2648
2695
  this.modelCatalog = dependencies.modelCatalog ?? createEmptyModelCatalog();
2649
2696
  this.modelResolver = dependencies.modelResolver ?? new ModelResolver({
2650
2697
  modelCatalog: this.modelCatalog
@@ -2692,7 +2739,7 @@ var GraphAgentExecutor = class {
2692
2739
  llmMessages: [],
2693
2740
  mode: input.request.mode === "chat" ? "chat" : "agent",
2694
2741
  conversationId: resolveConversationIdForRuntimeEvents(input.toolContext),
2695
- turnId: readNonEmptyString(input.toolContext?.turnId) ?? `turn_${Date.now()}`,
2742
+ turnId: readNonEmptyString2(input.toolContext?.turnId) ?? `turn_${Date.now()}`,
2696
2743
  telemetry: this.telemetryPort,
2697
2744
  audit: this.auditPort
2698
2745
  };
@@ -2742,18 +2789,18 @@ function isSummarizationCallbacks(value) {
2742
2789
  function isGraphSseSink(value) {
2743
2790
  return typeof value === "function";
2744
2791
  }
2745
- function readNonEmptyString2(value) {
2792
+ function readNonEmptyString3(value) {
2746
2793
  if (typeof value !== "string") return void 0;
2747
2794
  const trimmed = value.trim();
2748
2795
  return trimmed.length > 0 ? trimmed : void 0;
2749
2796
  }
2750
2797
  function readGraphAgentLocal(local) {
2751
2798
  const source = local ?? {};
2752
- const answerId = readNonEmptyString2(source.answerId);
2799
+ const answerId = readNonEmptyString3(source.answerId);
2753
2800
  const chunkSeq = Number.isInteger(source.chunkSeq) ? Number(source.chunkSeq) : 0;
2754
2801
  return {
2755
- conversationId: readNonEmptyString2(source.conversationId) ?? "",
2756
- turnId: readNonEmptyString2(source.turnId),
2802
+ conversationId: readNonEmptyString3(source.conversationId) ?? "",
2803
+ turnId: readNonEmptyString3(source.turnId),
2757
2804
  request: isAgentInvocationRequest(source.request) ? source.request : void 0,
2758
2805
  toolContext: isToolExecutionContext(source.toolContext) ? source.toolContext : void 0,
2759
2806
  history: isRuntimeEventArray(source.history) ? source.history : [],
@@ -3518,7 +3565,7 @@ var LlmNode = class {
3518
3565
  function isRecord8(value) {
3519
3566
  return typeof value === "object" && value !== null && !Array.isArray(value);
3520
3567
  }
3521
- function readNonEmptyString3(value) {
3568
+ function readNonEmptyString4(value) {
3522
3569
  if (typeof value !== "string") {
3523
3570
  return void 0;
3524
3571
  }
@@ -3540,7 +3587,7 @@ function resolveFinalAnswerFromToolResult(toolName, parsedResult) {
3540
3587
  return void 0;
3541
3588
  }
3542
3589
  if (toolName === "write_report") {
3543
- const report = readNonEmptyString3(data.report);
3590
+ const report = readNonEmptyString4(data.report);
3544
3591
  if (!report) {
3545
3592
  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");
3546
3593
  }
@@ -3550,7 +3597,7 @@ function resolveFinalAnswerFromToolResult(toolName, parsedResult) {
3550
3597
  if (data.success !== true) {
3551
3598
  return void 0;
3552
3599
  }
3553
- const finalAnswer = readNonEmptyString3(data.final_answer);
3600
+ const finalAnswer = readNonEmptyString4(data.final_answer);
3554
3601
  if (!finalAnswer) {
3555
3602
  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");
3556
3603
  }
@@ -4884,12 +4931,12 @@ function asRecord(value) {
4884
4931
  }
4885
4932
  return value;
4886
4933
  }
4887
- function summarizeCheckpoint(conversationId, state, savedAt) {
4934
+ function summarizeCheckpoint(checkpointKey, state, savedAt) {
4888
4935
  const local = asRecord(state.local);
4889
4936
  const executorLocal = asRecord(local?.executorLocal);
4890
4937
  const pendingToolCalls = local?.pendingToolCalls;
4891
4938
  return {
4892
- conversationId,
4939
+ checkpointKey,
4893
4940
  schemaVersion: state.schemaVersion ?? 1,
4894
4941
  savedAt,
4895
4942
  currentNode: state.nodeId,
@@ -4908,25 +4955,25 @@ var MemoryCheckpointer = class {
4908
4955
  local: state.local && typeof state.local === "object" && !Array.isArray(state.local) ? { ...state.local } : state.local
4909
4956
  };
4910
4957
  }
4911
- async load(conversationId) {
4912
- const entry = this.store.get(conversationId);
4958
+ async load(checkpointKey) {
4959
+ const entry = this.store.get(checkpointKey);
4913
4960
  return entry ? this.cloneState(entry.state) : null;
4914
4961
  }
4915
- async save(conversationId, state) {
4916
- this.store.set(conversationId, {
4962
+ async save(checkpointKey, state) {
4963
+ this.store.set(checkpointKey, {
4917
4964
  state: this.cloneState(state),
4918
4965
  savedAt: Date.now()
4919
4966
  });
4920
4967
  }
4921
- async clear(conversationId) {
4922
- this.store.delete(conversationId);
4968
+ async clear(checkpointKey) {
4969
+ this.store.delete(checkpointKey);
4923
4970
  }
4924
- async peekMeta(conversationId) {
4925
- const entry = this.store.get(conversationId);
4926
- 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;
4927
4974
  }
4928
4975
  async list(filter = {}) {
4929
- 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);
4930
4977
  if (filter.limit === void 0) {
4931
4978
  return summaries;
4932
4979
  }
@@ -6466,7 +6513,7 @@ function cloneRunRecord(record) {
6466
6513
  ...record,
6467
6514
  iterationBudget: record.iterationBudget ? { ...record.iterationBudget } : void 0,
6468
6515
  errorIfAny: record.errorIfAny ? { ...record.errorIfAny } : void 0,
6469
- metadata: record.metadata ? { ...record.metadata } : void 0
6516
+ metadata: record.metadata ? structuredClone(record.metadata) : void 0
6470
6517
  };
6471
6518
  }
6472
6519
  function matchesStatus(candidate, filter) {
@@ -6878,7 +6925,7 @@ function isTerminalStatus(status) {
6878
6925
  return status === "completed" || status === "failed" || status === "cancelled";
6879
6926
  }
6880
6927
  function cloneMetadata(metadata) {
6881
- return metadata ? { ...metadata } : void 0;
6928
+ return metadata ? structuredClone(metadata) : void 0;
6882
6929
  }
6883
6930
  function recordToSnapshot(record) {
6884
6931
  return {
@@ -6965,7 +7012,7 @@ var DefaultRunSupervisor = class {
6965
7012
  startedAt,
6966
7013
  updatedAt: startedAt,
6967
7014
  iterationBudget: spec.iterationBudget ? { ...spec.iterationBudget } : void 0,
6968
- metadata: spec.metadata ? { ...spec.metadata } : void 0
7015
+ metadata: cloneMetadata(spec.metadata)
6969
7016
  };
6970
7017
  await this.registryStore.save(record);
6971
7018
  const handle = new DefaultRunHandle({
@@ -7139,12 +7186,13 @@ var DefaultRunSupervisor = class {
7139
7186
  }
7140
7187
  try {
7141
7188
  await handle.markRunning({ currentNode: "detached" });
7189
+ const registeredRecord = await this.registryStore.load(handle.runId);
7142
7190
  const executorOutcome = await this.executor.execute({
7143
7191
  runId: handle.runId,
7144
- parentRunId: spec.parentRunId,
7145
- conversationId: spec.conversationId,
7146
- agentSpec: spec.agentSpec,
7147
- request: spec.request,
7192
+ parentRunId: handle.parentRunId,
7193
+ conversationId: registeredRecord?.conversationId ?? spec.conversationId,
7194
+ agentSpec: await handle.spec(),
7195
+ request: await handle.request(),
7148
7196
  signal: handle.signal,
7149
7197
  eventBus: spec.eventBus,
7150
7198
  eventStore: spec.eventStore,
@@ -7153,7 +7201,7 @@ var DefaultRunSupervisor = class {
7153
7201
  contextFences: spec.contextFences,
7154
7202
  wakeSource: spec.wakeSource,
7155
7203
  ephemeral: spec.ephemeral,
7156
- metadata: spec.metadata
7204
+ metadata: cloneMetadata(registeredRecord?.metadata ?? spec.metadata)
7157
7205
  });
7158
7206
  const outcome = await this.persistExecutorOutcome(handle, executorOutcome);
7159
7207
  this.notifyTerminalWaiters(outcome);
@@ -7217,10 +7265,14 @@ var DefaultRunSupervisor = class {
7217
7265
  await this.registryStore.save(record);
7218
7266
  }
7219
7267
  const completedAt = executorOutcome?.completedAt ?? this.now();
7268
+ const fallbackMeta = record ? void 0 : await handle.meta();
7220
7269
  const outcome = recordToTerminalOutcome(record ?? {
7221
7270
  runId: handle.runId,
7222
7271
  parentRunId: handle.parentRunId,
7223
- status: executorOutcome?.status ?? "completed"}, completedAt);
7272
+ conversationId: fallbackMeta?.conversationId ?? "",
7273
+ agentSpecId: fallbackMeta?.agentSpecId,
7274
+ status: executorOutcome?.status ?? "completed",
7275
+ startedAt: fallbackMeta?.startedAt ?? completedAt}, completedAt);
7224
7276
  const nextOutcome = {
7225
7277
  ...outcome,
7226
7278
  metadata: {
@@ -7548,6 +7600,7 @@ async function emitRunEvent(event, sink) {
7548
7600
  async function runAgent(agent, options) {
7549
7601
  const modelId = resolveModelId(agent, options);
7550
7602
  const conversationId = options.conversationId ?? `conv_${Date.now()}`;
7603
+ const checkpointKey = conversationId;
7551
7604
  const runId = options.runId ?? generateRunId();
7552
7605
  const turnId = runId;
7553
7606
  const costCollector = new QuickstartRunCostCollector();
@@ -7602,7 +7655,7 @@ async function runAgent(agent, options) {
7602
7655
  };
7603
7656
  await handle.markRunning({ currentNode: "user" });
7604
7657
  try {
7605
- await executor.prime(conversationId, {
7658
+ await executor.prime(checkpointKey, {
7606
7659
  conversationId,
7607
7660
  turnId,
7608
7661
  request: {
@@ -7627,7 +7680,7 @@ async function runAgent(agent, options) {
7627
7680
  return void 0;
7628
7681
  }
7629
7682
  });
7630
- const result = await executor.runUntilYield(conversationId);
7683
+ const result = await executor.runUntilYield(checkpointKey);
7631
7684
  runtimeEvents.push(...result.events);
7632
7685
  for (const event of result.events) {
7633
7686
  if (event.type === "final_answer_chunk") continue;
@@ -7790,7 +7843,7 @@ function createQuickstartTemplateFiles(projectName) {
7790
7843
  start: 'linnkit run hello --input "\u4F60\u597D\uFF0C\u4ECB\u7ECD\u4E00\u4E0B\u4F60\u81EA\u5DF1"'
7791
7844
  },
7792
7845
  dependencies: {
7793
- "@linnlabs/linnkit": "^0.8.0",
7846
+ "@linnlabs/linnkit": "^0.10.0",
7794
7847
  zod: "^3.22.0"
7795
7848
  },
7796
7849
  devDependencies: {}