@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.js CHANGED
@@ -200,6 +200,7 @@ var AgentSpecBudgetPolicy = z.object({
200
200
  });
201
201
  var AgentSpecToolHistoryPolicy = z.object({
202
202
  strategy: z.enum(["per-pair", "per-run", "none"]).optional(),
203
+ retentionMode: z.enum(["drop", "compress"]).optional(),
203
204
  keepLatestToolPairs: z.number().int().nonnegative().optional(),
204
205
  keepLatestRuns: z.number().int().nonnegative().optional(),
205
206
  maxInteractionGroups: z.number().int().nonnegative().optional(),
@@ -1081,6 +1082,7 @@ var Logger = class {
1081
1082
  constructor(moduleName) {
1082
1083
  this.moduleName = moduleName;
1083
1084
  }
1085
+ moduleName;
1084
1086
  debug(message, data) {
1085
1087
  this.log(0 /* DEBUG */, "debug", message, data);
1086
1088
  }
@@ -1153,6 +1155,17 @@ var logger = new Logger("GraphExecutor");
1153
1155
  function asLocalRecord(local) {
1154
1156
  return local && typeof local === "object" ? { ...local } : {};
1155
1157
  }
1158
+ function readNonEmptyString(value) {
1159
+ return typeof value === "string" && value.trim().length > 0 ? value : void 0;
1160
+ }
1161
+ function readRuntimeConversationId(state) {
1162
+ const local = state?.local && typeof state.local === "object" ? state.local : void 0;
1163
+ return readNonEmptyString(local?.conversationId);
1164
+ }
1165
+ function readRuntimeTurnId(state) {
1166
+ const local = state?.local && typeof state.local === "object" ? state.local : void 0;
1167
+ return readNonEmptyString(local?.turnId);
1168
+ }
1156
1169
  var GraphExecutor = class {
1157
1170
  constructor(checkpointer, config = {}) {
1158
1171
  this.checkpointer = checkpointer;
@@ -1162,6 +1175,7 @@ var GraphExecutor = class {
1162
1175
  };
1163
1176
  this.telemetryPort = config.telemetryPort ?? noopTelemetry;
1164
1177
  }
1178
+ checkpointer;
1165
1179
  nodes = /* @__PURE__ */ new Map();
1166
1180
  ephemeralLocals = /* @__PURE__ */ new Map();
1167
1181
  config;
@@ -1169,8 +1183,8 @@ var GraphExecutor = class {
1169
1183
  registerNode(node) {
1170
1184
  this.nodes.set(node.id, node);
1171
1185
  }
1172
- async peekCheckpoint(conversationId) {
1173
- return await this.checkpointer.load(conversationId);
1186
+ async peekCheckpoint(checkpointKey) {
1187
+ return await this.checkpointer.load(checkpointKey);
1174
1188
  }
1175
1189
  sanitize(state) {
1176
1190
  const local = asLocalRecord(state.local);
@@ -1182,8 +1196,8 @@ var GraphExecutor = class {
1182
1196
  local
1183
1197
  };
1184
1198
  }
1185
- async prime(conversationId, local, nodeId = "user") {
1186
- this.ephemeralLocals.set(conversationId, { ...local || {} });
1199
+ async prime(checkpointKey, local, nodeId = "user") {
1200
+ this.ephemeralLocals.set(checkpointKey, { ...local || {} });
1187
1201
  const localSansMemory = { ...local || {} };
1188
1202
  if ("memory" in localSansMemory) delete localSansMemory.memory;
1189
1203
  const state = {
@@ -1191,10 +1205,10 @@ var GraphExecutor = class {
1191
1205
  schemaVersion: ENGINE_STATE_SCHEMA_VERSION,
1192
1206
  local: localSansMemory
1193
1207
  };
1194
- await this.checkpointer.save(conversationId, state);
1208
+ await this.checkpointer.save(checkpointKey, state);
1195
1209
  }
1196
- async setNode(conversationId, nodeId, localPatch) {
1197
- const current = await this.checkpointer.load(conversationId) || {
1210
+ async setNode(checkpointKey, nodeId, localPatch) {
1211
+ const current = await this.checkpointer.load(checkpointKey) || {
1198
1212
  schemaVersion: ENGINE_STATE_SCHEMA_VERSION,
1199
1213
  local: {}
1200
1214
  };
@@ -1205,19 +1219,46 @@ var GraphExecutor = class {
1205
1219
  schemaVersion: current.schemaVersion ?? ENGINE_STATE_SCHEMA_VERSION,
1206
1220
  local: mergedLocal
1207
1221
  };
1208
- await this.checkpointer.save(conversationId, next);
1222
+ await this.checkpointer.save(checkpointKey, next);
1209
1223
  }
1210
- async runUntilYield(conversationId) {
1224
+ async runUntilYield(checkpointKey) {
1211
1225
  const runId = `run_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
1212
1226
  let lifecyclePhase = "completed";
1227
+ let initialState = null;
1228
+ try {
1229
+ initialState = await this.loadInitialState(checkpointKey);
1230
+ } catch (err) {
1231
+ lifecyclePhase = "failed";
1232
+ this.telemetryPort.emit({
1233
+ kind: "run_lifecycle",
1234
+ runId,
1235
+ phase: "spawned",
1236
+ scope: {}
1237
+ });
1238
+ this.telemetryPort.emit({
1239
+ kind: "run_lifecycle",
1240
+ runId,
1241
+ phase: lifecyclePhase,
1242
+ scope: {}
1243
+ });
1244
+ throw err;
1245
+ }
1246
+ let lifecycleConversationId = readRuntimeConversationId(initialState);
1247
+ let lifecycleTurnId = readRuntimeTurnId(initialState);
1213
1248
  this.telemetryPort.emit({
1214
1249
  kind: "run_lifecycle",
1215
1250
  runId,
1216
1251
  phase: "spawned",
1217
- scope: { conversationId: conversationId || void 0 }
1252
+ scope: {
1253
+ conversationId: lifecycleConversationId,
1254
+ turnId: lifecycleTurnId
1255
+ }
1218
1256
  });
1219
1257
  try {
1220
- return await this.runUntilYieldInternal(conversationId);
1258
+ const result = await this.runUntilYieldInternal(checkpointKey, initialState);
1259
+ lifecycleConversationId = readRuntimeConversationId(result.checkpoint);
1260
+ lifecycleTurnId = readRuntimeTurnId(result.checkpoint);
1261
+ return result;
1221
1262
  } catch (err) {
1222
1263
  lifecyclePhase = err?.name === "AbortError" ? "cancelled" : "failed";
1223
1264
  throw err;
@@ -1226,17 +1267,23 @@ var GraphExecutor = class {
1226
1267
  kind: "run_lifecycle",
1227
1268
  runId,
1228
1269
  phase: lifecyclePhase,
1229
- scope: { conversationId: conversationId || void 0 }
1270
+ scope: {
1271
+ conversationId: lifecycleConversationId,
1272
+ turnId: lifecycleTurnId
1273
+ }
1230
1274
  });
1231
1275
  }
1232
1276
  }
1233
- async runUntilYieldInternal(conversationId) {
1234
- let state = await this.checkpointer.load(conversationId) || {
1277
+ async loadInitialState(checkpointKey) {
1278
+ return await this.checkpointer.load(checkpointKey) || {
1235
1279
  nodeId: "user",
1236
1280
  schemaVersion: ENGINE_STATE_SCHEMA_VERSION,
1237
1281
  local: {}
1238
1282
  };
1239
- const ephemeral = this.ephemeralLocals.get(conversationId) || {};
1283
+ }
1284
+ async runUntilYieldInternal(checkpointKey, initialState) {
1285
+ let state = initialState;
1286
+ const ephemeral = this.ephemeralLocals.get(checkpointKey) || {};
1240
1287
  state = {
1241
1288
  ...state,
1242
1289
  schemaVersion: state.schemaVersion ?? ENGINE_STATE_SCHEMA_VERSION,
@@ -1265,7 +1312,7 @@ var GraphExecutor = class {
1265
1312
  const signalRaw = state.local?.signal;
1266
1313
  if (isAbortSignal2(signalRaw) && signalRaw.aborted) {
1267
1314
  logger.warn("[GraphExecutor] \u6536\u5230 AbortSignal\uFF0C\u7ACB\u5373\u505C\u6B62\u63A8\u7406\u5FAA\u73AF");
1268
- this.ephemeralLocals.delete(conversationId);
1315
+ this.ephemeralLocals.delete(checkpointKey);
1269
1316
  throwAbortError();
1270
1317
  }
1271
1318
  const isLastStep = cycleStepCount >= this.config.maxSteps;
@@ -1313,8 +1360,8 @@ var GraphExecutor = class {
1313
1360
  checkpointCount
1314
1361
  });
1315
1362
  const cp2 = this.sanitize(state);
1316
- await this.checkpointer.save(conversationId, cp2);
1317
- this.ephemeralLocals.delete(conversationId);
1363
+ await this.checkpointer.save(checkpointKey, cp2);
1364
+ this.ephemeralLocals.delete(checkpointKey);
1318
1365
  return { events: allEvents, checkpoint: cp2, stepCount };
1319
1366
  }
1320
1367
  logger.info("[GraphExecutor] \u8282\u70B9\u5207\u6362", {
@@ -1325,18 +1372,18 @@ var GraphExecutor = class {
1325
1372
  });
1326
1373
  const nodeRunStartedAt = Date.now();
1327
1374
  const nodeIdForTelemetry = state.nodeId;
1375
+ const conversationIdForTelemetry = readRuntimeConversationId(state);
1328
1376
  let result;
1329
1377
  try {
1330
1378
  result = await node.run(state);
1331
1379
  } finally {
1332
- const turnIdForTelemetry = typeof state.local?.turnId === "string" ? state.local.turnId : void 0;
1333
1380
  this.telemetryPort.emit({
1334
1381
  kind: "graph_node",
1335
1382
  nodeId: nodeIdForTelemetry,
1336
1383
  durationMs: Date.now() - nodeRunStartedAt,
1337
1384
  scope: {
1338
- conversationId: conversationId || void 0,
1339
- turnId: turnIdForTelemetry
1385
+ conversationId: conversationIdForTelemetry,
1386
+ turnId: readRuntimeTurnId(state)
1340
1387
  }
1341
1388
  });
1342
1389
  }
@@ -1375,7 +1422,7 @@ var GraphExecutor = class {
1375
1422
  });
1376
1423
  state = { ...state, nodeId: nextNodeId };
1377
1424
  const cp2 = this.sanitize(state);
1378
- await this.checkpointer.save(conversationId, cp2);
1425
+ await this.checkpointer.save(checkpointKey, cp2);
1379
1426
  continue;
1380
1427
  }
1381
1428
  if (result.kind === "yield") {
@@ -1386,7 +1433,7 @@ var GraphExecutor = class {
1386
1433
  checkpointCount
1387
1434
  });
1388
1435
  const cp2 = this.sanitize(state);
1389
- await this.checkpointer.save(conversationId, cp2);
1436
+ await this.checkpointer.save(checkpointKey, cp2);
1390
1437
  return { events: allEvents, checkpoint: cp2, stepCount };
1391
1438
  }
1392
1439
  if (result.kind === "pause") {
@@ -1397,7 +1444,7 @@ var GraphExecutor = class {
1397
1444
  checkpointCount
1398
1445
  });
1399
1446
  const cp2 = this.sanitize(state);
1400
- await this.checkpointer.save(conversationId, cp2);
1447
+ await this.checkpointer.save(checkpointKey, cp2);
1401
1448
  return { events: allEvents, checkpoint: cp2, stepCount };
1402
1449
  }
1403
1450
  }
@@ -1408,8 +1455,8 @@ var GraphExecutor = class {
1408
1455
  checkpointCount
1409
1456
  });
1410
1457
  const cp = this.sanitize(state);
1411
- await this.checkpointer.save(conversationId, cp);
1412
- this.ephemeralLocals.delete(conversationId);
1458
+ await this.checkpointer.save(checkpointKey, cp);
1459
+ this.ephemeralLocals.delete(checkpointKey);
1413
1460
  return { events: allEvents, checkpoint: cp, stepCount };
1414
1461
  }
1415
1462
  };
@@ -1572,15 +1619,15 @@ function splitConcatenatedJsonObjects(input) {
1572
1619
  }
1573
1620
 
1574
1621
  // src/runtime-kernel/graph-engine/tick-pipeline/helpers.ts
1575
- function readNonEmptyString(value) {
1622
+ function readNonEmptyString2(value) {
1576
1623
  if (typeof value !== "string") return void 0;
1577
1624
  const trimmed = value.trim();
1578
1625
  return trimmed.length > 0 ? trimmed : void 0;
1579
1626
  }
1580
1627
  function resolveConversationIdForRuntimeEvents(toolContext) {
1581
- const fromCamel = readNonEmptyString(toolContext?.conversationId);
1628
+ const fromCamel = readNonEmptyString2(toolContext?.conversationId);
1582
1629
  if (fromCamel) return fromCamel;
1583
- const fromSnake = toolContext ? readNonEmptyString(toolContext["conversation_id"]) : void 0;
1630
+ const fromSnake = toolContext ? readNonEmptyString2(toolContext["conversation_id"]) : void 0;
1584
1631
  if (fromSnake) return fromSnake;
1585
1632
  return generateMessageId();
1586
1633
  }
@@ -1937,7 +1984,7 @@ var runModelLockMiddleware = async (ctx, stage, next) => {
1937
1984
  if (stage.id !== "execute_llm") {
1938
1985
  return;
1939
1986
  }
1940
- const normalized = readNonEmptyString(ctx.cloudQuotaFallbackAppliedModelId);
1987
+ const normalized = readNonEmptyString2(ctx.cloudQuotaFallbackAppliedModelId);
1941
1988
  if (!normalized) {
1942
1989
  return;
1943
1990
  }
@@ -2525,7 +2572,7 @@ function createExecuteLlmStage(dependencies) {
2525
2572
  streamEventHandler,
2526
2573
  ctx.signal,
2527
2574
  (fallbackModelId) => {
2528
- ctx.cloudQuotaFallbackAppliedModelId = readNonEmptyString(fallbackModelId);
2575
+ ctx.cloudQuotaFallbackAppliedModelId = readNonEmptyString2(fallbackModelId);
2529
2576
  },
2530
2577
  (info) => {
2531
2578
  ctx.modelFallbackAudit = info;
@@ -2569,7 +2616,7 @@ function createPrepareCallStage(dependencies) {
2569
2616
  return {
2570
2617
  id: "prepare_call",
2571
2618
  async run(ctx) {
2572
- const lockedRunModelId = readNonEmptyString(ctx.executorLocal?.runLockedModelId);
2619
+ const lockedRunModelId = readNonEmptyString2(ctx.executorLocal?.runLockedModelId);
2573
2620
  const requestedModelId = lockedRunModelId ?? ctx.request.model_id;
2574
2621
  ctx.modelId = dependencies.modelResolver.resolveModelId(requestedModelId);
2575
2622
  await emitAuditEnvelope(ctx.audit, {
@@ -2641,7 +2688,7 @@ var GraphAgentExecutor = class {
2641
2688
  this.llmCaller = dependencies.llmCaller;
2642
2689
  this.toolRuntime = dependencies.toolRuntime;
2643
2690
  this.contextBuilder = dependencies.contextBuilder;
2644
- this.cloudQuotaFallbackModelId = readNonEmptyString(dependencies.cloudQuotaFallbackModelId);
2691
+ this.cloudQuotaFallbackModelId = readNonEmptyString2(dependencies.cloudQuotaFallbackModelId);
2645
2692
  this.modelCatalog = dependencies.modelCatalog ?? createEmptyModelCatalog();
2646
2693
  this.modelResolver = dependencies.modelResolver ?? new ModelResolver({
2647
2694
  modelCatalog: this.modelCatalog
@@ -2689,7 +2736,7 @@ var GraphAgentExecutor = class {
2689
2736
  llmMessages: [],
2690
2737
  mode: input.request.mode === "chat" ? "chat" : "agent",
2691
2738
  conversationId: resolveConversationIdForRuntimeEvents(input.toolContext),
2692
- turnId: readNonEmptyString(input.toolContext?.turnId) ?? `turn_${Date.now()}`,
2739
+ turnId: readNonEmptyString2(input.toolContext?.turnId) ?? `turn_${Date.now()}`,
2693
2740
  telemetry: this.telemetryPort,
2694
2741
  audit: this.auditPort
2695
2742
  };
@@ -2739,18 +2786,18 @@ function isSummarizationCallbacks(value) {
2739
2786
  function isGraphSseSink(value) {
2740
2787
  return typeof value === "function";
2741
2788
  }
2742
- function readNonEmptyString2(value) {
2789
+ function readNonEmptyString3(value) {
2743
2790
  if (typeof value !== "string") return void 0;
2744
2791
  const trimmed = value.trim();
2745
2792
  return trimmed.length > 0 ? trimmed : void 0;
2746
2793
  }
2747
2794
  function readGraphAgentLocal(local) {
2748
2795
  const source = local ?? {};
2749
- const answerId = readNonEmptyString2(source.answerId);
2796
+ const answerId = readNonEmptyString3(source.answerId);
2750
2797
  const chunkSeq = Number.isInteger(source.chunkSeq) ? Number(source.chunkSeq) : 0;
2751
2798
  return {
2752
- conversationId: readNonEmptyString2(source.conversationId) ?? "",
2753
- turnId: readNonEmptyString2(source.turnId),
2799
+ conversationId: readNonEmptyString3(source.conversationId) ?? "",
2800
+ turnId: readNonEmptyString3(source.turnId),
2754
2801
  request: isAgentInvocationRequest(source.request) ? source.request : void 0,
2755
2802
  toolContext: isToolExecutionContext(source.toolContext) ? source.toolContext : void 0,
2756
2803
  history: isRuntimeEventArray(source.history) ? source.history : [],
@@ -3515,7 +3562,7 @@ var LlmNode = class {
3515
3562
  function isRecord8(value) {
3516
3563
  return typeof value === "object" && value !== null && !Array.isArray(value);
3517
3564
  }
3518
- function readNonEmptyString3(value) {
3565
+ function readNonEmptyString4(value) {
3519
3566
  if (typeof value !== "string") {
3520
3567
  return void 0;
3521
3568
  }
@@ -3537,7 +3584,7 @@ function resolveFinalAnswerFromToolResult(toolName, parsedResult) {
3537
3584
  return void 0;
3538
3585
  }
3539
3586
  if (toolName === "write_report") {
3540
- const report = readNonEmptyString3(data.report);
3587
+ const report = readNonEmptyString4(data.report);
3541
3588
  if (!report) {
3542
3589
  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");
3543
3590
  }
@@ -3547,7 +3594,7 @@ function resolveFinalAnswerFromToolResult(toolName, parsedResult) {
3547
3594
  if (data.success !== true) {
3548
3595
  return void 0;
3549
3596
  }
3550
- const finalAnswer = readNonEmptyString3(data.final_answer);
3597
+ const finalAnswer = readNonEmptyString4(data.final_answer);
3551
3598
  if (!finalAnswer) {
3552
3599
  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");
3553
3600
  }
@@ -4881,12 +4928,12 @@ function asRecord(value) {
4881
4928
  }
4882
4929
  return value;
4883
4930
  }
4884
- function summarizeCheckpoint(conversationId, state, savedAt) {
4931
+ function summarizeCheckpoint(checkpointKey, state, savedAt) {
4885
4932
  const local = asRecord(state.local);
4886
4933
  const executorLocal = asRecord(local?.executorLocal);
4887
4934
  const pendingToolCalls = local?.pendingToolCalls;
4888
4935
  return {
4889
- conversationId,
4936
+ checkpointKey,
4890
4937
  schemaVersion: state.schemaVersion ?? 1,
4891
4938
  savedAt,
4892
4939
  currentNode: state.nodeId,
@@ -4905,25 +4952,25 @@ var MemoryCheckpointer = class {
4905
4952
  local: state.local && typeof state.local === "object" && !Array.isArray(state.local) ? { ...state.local } : state.local
4906
4953
  };
4907
4954
  }
4908
- async load(conversationId) {
4909
- const entry = this.store.get(conversationId);
4955
+ async load(checkpointKey) {
4956
+ const entry = this.store.get(checkpointKey);
4910
4957
  return entry ? this.cloneState(entry.state) : null;
4911
4958
  }
4912
- async save(conversationId, state) {
4913
- this.store.set(conversationId, {
4959
+ async save(checkpointKey, state) {
4960
+ this.store.set(checkpointKey, {
4914
4961
  state: this.cloneState(state),
4915
4962
  savedAt: Date.now()
4916
4963
  });
4917
4964
  }
4918
- async clear(conversationId) {
4919
- this.store.delete(conversationId);
4965
+ async clear(checkpointKey) {
4966
+ this.store.delete(checkpointKey);
4920
4967
  }
4921
- async peekMeta(conversationId) {
4922
- const entry = this.store.get(conversationId);
4923
- return entry ? summarizeCheckpoint(conversationId, entry.state, entry.savedAt) : null;
4968
+ async peekMeta(checkpointKey) {
4969
+ const entry = this.store.get(checkpointKey);
4970
+ return entry ? summarizeCheckpoint(checkpointKey, entry.state, entry.savedAt) : null;
4924
4971
  }
4925
4972
  async list(filter = {}) {
4926
- 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);
4973
+ 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);
4927
4974
  if (filter.limit === void 0) {
4928
4975
  return summaries;
4929
4976
  }
@@ -6463,7 +6510,7 @@ function cloneRunRecord(record) {
6463
6510
  ...record,
6464
6511
  iterationBudget: record.iterationBudget ? { ...record.iterationBudget } : void 0,
6465
6512
  errorIfAny: record.errorIfAny ? { ...record.errorIfAny } : void 0,
6466
- metadata: record.metadata ? { ...record.metadata } : void 0
6513
+ metadata: record.metadata ? structuredClone(record.metadata) : void 0
6467
6514
  };
6468
6515
  }
6469
6516
  function matchesStatus(candidate, filter) {
@@ -6875,7 +6922,7 @@ function isTerminalStatus(status) {
6875
6922
  return status === "completed" || status === "failed" || status === "cancelled";
6876
6923
  }
6877
6924
  function cloneMetadata(metadata) {
6878
- return metadata ? { ...metadata } : void 0;
6925
+ return metadata ? structuredClone(metadata) : void 0;
6879
6926
  }
6880
6927
  function recordToSnapshot(record) {
6881
6928
  return {
@@ -6962,7 +7009,7 @@ var DefaultRunSupervisor = class {
6962
7009
  startedAt,
6963
7010
  updatedAt: startedAt,
6964
7011
  iterationBudget: spec.iterationBudget ? { ...spec.iterationBudget } : void 0,
6965
- metadata: spec.metadata ? { ...spec.metadata } : void 0
7012
+ metadata: cloneMetadata(spec.metadata)
6966
7013
  };
6967
7014
  await this.registryStore.save(record);
6968
7015
  const handle = new DefaultRunHandle({
@@ -7136,12 +7183,13 @@ var DefaultRunSupervisor = class {
7136
7183
  }
7137
7184
  try {
7138
7185
  await handle.markRunning({ currentNode: "detached" });
7186
+ const registeredRecord = await this.registryStore.load(handle.runId);
7139
7187
  const executorOutcome = await this.executor.execute({
7140
7188
  runId: handle.runId,
7141
- parentRunId: spec.parentRunId,
7142
- conversationId: spec.conversationId,
7143
- agentSpec: spec.agentSpec,
7144
- request: spec.request,
7189
+ parentRunId: handle.parentRunId,
7190
+ conversationId: registeredRecord?.conversationId ?? spec.conversationId,
7191
+ agentSpec: await handle.spec(),
7192
+ request: await handle.request(),
7145
7193
  signal: handle.signal,
7146
7194
  eventBus: spec.eventBus,
7147
7195
  eventStore: spec.eventStore,
@@ -7150,7 +7198,7 @@ var DefaultRunSupervisor = class {
7150
7198
  contextFences: spec.contextFences,
7151
7199
  wakeSource: spec.wakeSource,
7152
7200
  ephemeral: spec.ephemeral,
7153
- metadata: spec.metadata
7201
+ metadata: cloneMetadata(registeredRecord?.metadata ?? spec.metadata)
7154
7202
  });
7155
7203
  const outcome = await this.persistExecutorOutcome(handle, executorOutcome);
7156
7204
  this.notifyTerminalWaiters(outcome);
@@ -7214,10 +7262,14 @@ var DefaultRunSupervisor = class {
7214
7262
  await this.registryStore.save(record);
7215
7263
  }
7216
7264
  const completedAt = executorOutcome?.completedAt ?? this.now();
7265
+ const fallbackMeta = record ? void 0 : await handle.meta();
7217
7266
  const outcome = recordToTerminalOutcome(record ?? {
7218
7267
  runId: handle.runId,
7219
7268
  parentRunId: handle.parentRunId,
7220
- status: executorOutcome?.status ?? "completed"}, completedAt);
7269
+ conversationId: fallbackMeta?.conversationId ?? "",
7270
+ agentSpecId: fallbackMeta?.agentSpecId,
7271
+ status: executorOutcome?.status ?? "completed",
7272
+ startedAt: fallbackMeta?.startedAt ?? completedAt}, completedAt);
7221
7273
  const nextOutcome = {
7222
7274
  ...outcome,
7223
7275
  metadata: {
@@ -7545,6 +7597,7 @@ async function emitRunEvent(event, sink) {
7545
7597
  async function runAgent(agent, options) {
7546
7598
  const modelId = resolveModelId(agent, options);
7547
7599
  const conversationId = options.conversationId ?? `conv_${Date.now()}`;
7600
+ const checkpointKey = conversationId;
7548
7601
  const runId = options.runId ?? generateRunId();
7549
7602
  const turnId = runId;
7550
7603
  const costCollector = new QuickstartRunCostCollector();
@@ -7599,7 +7652,7 @@ async function runAgent(agent, options) {
7599
7652
  };
7600
7653
  await handle.markRunning({ currentNode: "user" });
7601
7654
  try {
7602
- await executor.prime(conversationId, {
7655
+ await executor.prime(checkpointKey, {
7603
7656
  conversationId,
7604
7657
  turnId,
7605
7658
  request: {
@@ -7624,7 +7677,7 @@ async function runAgent(agent, options) {
7624
7677
  return void 0;
7625
7678
  }
7626
7679
  });
7627
- const result = await executor.runUntilYield(conversationId);
7680
+ const result = await executor.runUntilYield(checkpointKey);
7628
7681
  runtimeEvents.push(...result.events);
7629
7682
  for (const event of result.events) {
7630
7683
  if (event.type === "final_answer_chunk") continue;
@@ -7787,7 +7840,7 @@ function createQuickstartTemplateFiles(projectName) {
7787
7840
  start: 'linnkit run hello --input "\u4F60\u597D\uFF0C\u4ECB\u7ECD\u4E00\u4E0B\u4F60\u81EA\u5DF1"'
7788
7841
  },
7789
7842
  dependencies: {
7790
- "@linnlabs/linnkit": "^0.8.0",
7843
+ "@linnlabs/linnkit": "^0.10.0",
7791
7844
  zod: "^3.22.0"
7792
7845
  },
7793
7846
  devDependencies: {}