@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
@@ -1,15 +1,15 @@
1
- import { Q as QuickstartToolRuntime } from './runAgent-HYKlXbVr.cjs';
2
- export { D as DefineAgentInput, a as DefinedAgent, L as LinnkitQuickstartConfig, R as RunAgentOptions, b as RunAgentResult, d as defineAgent, c as defineConfig, r as resolveConfiguredLlm, e as runAgent } from './runAgent-HYKlXbVr.cjs';
3
- import { B as BaseTool, a as ToolArgs, O as OpenAIToolSchema, T as ToolExecutionContext } from './toolContracts-CLkQmhTG.cjs';
4
- import { g as ToolRuntimeDefinition, f as ToolExecutionResult } from './ports-DaatKJXp.cjs';
1
+ import { Q as QuickstartToolRuntime } from './runAgent-ilEj66Ik.cjs';
2
+ export { D as DefineAgentInput, a as DefinedAgent, L as LinnkitQuickstartConfig, R as RunAgentOptions, b as RunAgentResult, d as defineAgent, c as defineConfig, r as resolveConfiguredLlm, e as runAgent } from './runAgent-ilEj66Ik.cjs';
3
+ import { B as BaseTool, T as ToolArgs, O as OpenAIToolSchema, a as ToolExecutionContext } from './toolContracts-Bm3EZ1UM.cjs';
4
+ import { T as ToolRuntimeDefinition, a as ToolExecutionResult } from './ports-s-tSp3sB.cjs';
5
5
  import './audit-LeOrm2hX.cjs';
6
6
  import './ai-engine.types-BpeU_XQG.cjs';
7
7
  import './messages-XthmnHZ3.cjs';
8
8
  import 'zod';
9
9
  import './audit-BaRUGaqv.cjs';
10
- import './agentSpec-EkmviZjy.cjs';
11
- import './todo-B1PmDlp3.cjs';
12
- import './runHandle-D3gPsD7B.cjs';
10
+ import './agentSpec-Du4Iye0q.cjs';
11
+ import './todo-Ca8llpRQ.cjs';
12
+ import './runHandle-BNOqS-Bl.cjs';
13
13
  import './execution-CAIypb41.cjs';
14
14
 
15
15
  declare class QuickstartMemoryToolRuntime implements QuickstartToolRuntime {
@@ -1,15 +1,15 @@
1
- import { Q as QuickstartToolRuntime } from './runAgent-CPj_9e58.js';
2
- export { D as DefineAgentInput, a as DefinedAgent, L as LinnkitQuickstartConfig, R as RunAgentOptions, b as RunAgentResult, d as defineAgent, c as defineConfig, r as resolveConfiguredLlm, e as runAgent } from './runAgent-CPj_9e58.js';
3
- import { B as BaseTool, a as ToolArgs, O as OpenAIToolSchema, T as ToolExecutionContext } from './toolContracts-Blll0241.js';
4
- import { g as ToolRuntimeDefinition, f as ToolExecutionResult } from './ports-DnLuKfpE.js';
1
+ import { Q as QuickstartToolRuntime } from './runAgent-C6F-399C.js';
2
+ export { D as DefineAgentInput, a as DefinedAgent, L as LinnkitQuickstartConfig, R as RunAgentOptions, b as RunAgentResult, d as defineAgent, c as defineConfig, r as resolveConfiguredLlm, e as runAgent } from './runAgent-C6F-399C.js';
3
+ import { B as BaseTool, T as ToolArgs, O as OpenAIToolSchema, a as ToolExecutionContext } from './toolContracts-f8lzZBNa.js';
4
+ import { T as ToolRuntimeDefinition, a as ToolExecutionResult } from './ports-DpPTFhSd.js';
5
5
  import './audit-CtcfART1.js';
6
6
  import './ai-engine.types-vZRnQcJa.js';
7
7
  import './messages-XthmnHZ3.js';
8
8
  import 'zod';
9
9
  import './audit-BaRUGaqv.js';
10
- import './agentSpec-EkmviZjy.js';
11
- import './todo-B1PmDlp3.js';
12
- import './runHandle-CyXvzgzk.js';
10
+ import './agentSpec-Du4Iye0q.js';
11
+ import './todo-Ca8llpRQ.js';
12
+ import './runHandle-BdLXOFqF.js';
13
13
  import './execution-CAIypb41.js';
14
14
 
15
15
  declare class QuickstartMemoryToolRuntime implements QuickstartToolRuntime {
@@ -166,6 +166,7 @@ var AgentSpecBudgetPolicy = z.object({
166
166
  });
167
167
  var AgentSpecToolHistoryPolicy = z.object({
168
168
  strategy: z.enum(["per-pair", "per-run", "none"]).optional(),
169
+ retentionMode: z.enum(["drop", "compress"]).optional(),
169
170
  keepLatestToolPairs: z.number().int().nonnegative().optional(),
170
171
  keepLatestRuns: z.number().int().nonnegative().optional(),
171
172
  maxInteractionGroups: z.number().int().nonnegative().optional(),
@@ -280,12 +281,13 @@ var AgentSpecContextPolicy = z.object({
280
281
  var DEFAULT_CONTEXT_POLICY = {
281
282
  profileId: "agent",
282
283
  budget: {
283
- maxTokens: 12e4,
284
+ maxTokens: 232e3,
284
285
  reservedForResponse: 2400,
285
286
  workingMemoryBudgetPercentage: 0.7
286
287
  },
287
288
  toolHistory: {
288
289
  strategy: "per-run",
290
+ retentionMode: "drop",
289
291
  keepLatestToolPairs: 2,
290
292
  keepLatestRuns: 1,
291
293
  maxInteractionGroups: 12,
@@ -1198,6 +1200,7 @@ var Logger = class {
1198
1200
  constructor(moduleName) {
1199
1201
  this.moduleName = moduleName;
1200
1202
  }
1203
+ moduleName;
1201
1204
  debug(message, data) {
1202
1205
  this.log(0 /* DEBUG */, "debug", message, data);
1203
1206
  }
@@ -1270,6 +1273,17 @@ var logger = new Logger("GraphExecutor");
1270
1273
  function asLocalRecord(local) {
1271
1274
  return local && typeof local === "object" ? { ...local } : {};
1272
1275
  }
1276
+ function readNonEmptyString(value) {
1277
+ return typeof value === "string" && value.trim().length > 0 ? value : void 0;
1278
+ }
1279
+ function readRuntimeConversationId(state) {
1280
+ const local = state?.local && typeof state.local === "object" ? state.local : void 0;
1281
+ return readNonEmptyString(local?.conversationId);
1282
+ }
1283
+ function readRuntimeTurnId(state) {
1284
+ const local = state?.local && typeof state.local === "object" ? state.local : void 0;
1285
+ return readNonEmptyString(local?.turnId);
1286
+ }
1273
1287
  var GraphExecutor = class {
1274
1288
  constructor(checkpointer, config = {}) {
1275
1289
  this.checkpointer = checkpointer;
@@ -1279,6 +1293,7 @@ var GraphExecutor = class {
1279
1293
  };
1280
1294
  this.telemetryPort = config.telemetryPort ?? noopTelemetry;
1281
1295
  }
1296
+ checkpointer;
1282
1297
  nodes = /* @__PURE__ */ new Map();
1283
1298
  ephemeralLocals = /* @__PURE__ */ new Map();
1284
1299
  config;
@@ -1286,8 +1301,8 @@ var GraphExecutor = class {
1286
1301
  registerNode(node) {
1287
1302
  this.nodes.set(node.id, node);
1288
1303
  }
1289
- async peekCheckpoint(conversationId) {
1290
- return await this.checkpointer.load(conversationId);
1304
+ async peekCheckpoint(checkpointKey) {
1305
+ return await this.checkpointer.load(checkpointKey);
1291
1306
  }
1292
1307
  sanitize(state) {
1293
1308
  const local = asLocalRecord(state.local);
@@ -1299,8 +1314,8 @@ var GraphExecutor = class {
1299
1314
  local
1300
1315
  };
1301
1316
  }
1302
- async prime(conversationId, local, nodeId = "user") {
1303
- this.ephemeralLocals.set(conversationId, { ...local || {} });
1317
+ async prime(checkpointKey, local, nodeId = "user") {
1318
+ this.ephemeralLocals.set(checkpointKey, { ...local || {} });
1304
1319
  const localSansMemory = { ...local || {} };
1305
1320
  if ("memory" in localSansMemory) delete localSansMemory.memory;
1306
1321
  const state = {
@@ -1308,10 +1323,10 @@ var GraphExecutor = class {
1308
1323
  schemaVersion: ENGINE_STATE_SCHEMA_VERSION,
1309
1324
  local: localSansMemory
1310
1325
  };
1311
- await this.checkpointer.save(conversationId, state);
1326
+ await this.checkpointer.save(checkpointKey, state);
1312
1327
  }
1313
- async setNode(conversationId, nodeId, localPatch) {
1314
- const current = await this.checkpointer.load(conversationId) || {
1328
+ async setNode(checkpointKey, nodeId, localPatch) {
1329
+ const current = await this.checkpointer.load(checkpointKey) || {
1315
1330
  schemaVersion: ENGINE_STATE_SCHEMA_VERSION,
1316
1331
  local: {}
1317
1332
  };
@@ -1322,19 +1337,46 @@ var GraphExecutor = class {
1322
1337
  schemaVersion: current.schemaVersion ?? ENGINE_STATE_SCHEMA_VERSION,
1323
1338
  local: mergedLocal
1324
1339
  };
1325
- await this.checkpointer.save(conversationId, next);
1340
+ await this.checkpointer.save(checkpointKey, next);
1326
1341
  }
1327
- async runUntilYield(conversationId) {
1342
+ async runUntilYield(checkpointKey) {
1328
1343
  const runId = `run_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
1329
1344
  let lifecyclePhase = "completed";
1345
+ let initialState = null;
1346
+ try {
1347
+ initialState = await this.loadInitialState(checkpointKey);
1348
+ } catch (err) {
1349
+ lifecyclePhase = "failed";
1350
+ this.telemetryPort.emit({
1351
+ kind: "run_lifecycle",
1352
+ runId,
1353
+ phase: "spawned",
1354
+ scope: {}
1355
+ });
1356
+ this.telemetryPort.emit({
1357
+ kind: "run_lifecycle",
1358
+ runId,
1359
+ phase: lifecyclePhase,
1360
+ scope: {}
1361
+ });
1362
+ throw err;
1363
+ }
1364
+ let lifecycleConversationId = readRuntimeConversationId(initialState);
1365
+ let lifecycleTurnId = readRuntimeTurnId(initialState);
1330
1366
  this.telemetryPort.emit({
1331
1367
  kind: "run_lifecycle",
1332
1368
  runId,
1333
1369
  phase: "spawned",
1334
- scope: { conversationId: conversationId || void 0 }
1370
+ scope: {
1371
+ conversationId: lifecycleConversationId,
1372
+ turnId: lifecycleTurnId
1373
+ }
1335
1374
  });
1336
1375
  try {
1337
- return await this.runUntilYieldInternal(conversationId);
1376
+ const result = await this.runUntilYieldInternal(checkpointKey, initialState);
1377
+ lifecycleConversationId = readRuntimeConversationId(result.checkpoint);
1378
+ lifecycleTurnId = readRuntimeTurnId(result.checkpoint);
1379
+ return result;
1338
1380
  } catch (err) {
1339
1381
  lifecyclePhase = err?.name === "AbortError" ? "cancelled" : "failed";
1340
1382
  throw err;
@@ -1343,17 +1385,23 @@ var GraphExecutor = class {
1343
1385
  kind: "run_lifecycle",
1344
1386
  runId,
1345
1387
  phase: lifecyclePhase,
1346
- scope: { conversationId: conversationId || void 0 }
1388
+ scope: {
1389
+ conversationId: lifecycleConversationId,
1390
+ turnId: lifecycleTurnId
1391
+ }
1347
1392
  });
1348
1393
  }
1349
1394
  }
1350
- async runUntilYieldInternal(conversationId) {
1351
- let state = await this.checkpointer.load(conversationId) || {
1395
+ async loadInitialState(checkpointKey) {
1396
+ return await this.checkpointer.load(checkpointKey) || {
1352
1397
  nodeId: "user",
1353
1398
  schemaVersion: ENGINE_STATE_SCHEMA_VERSION,
1354
1399
  local: {}
1355
1400
  };
1356
- const ephemeral = this.ephemeralLocals.get(conversationId) || {};
1401
+ }
1402
+ async runUntilYieldInternal(checkpointKey, initialState) {
1403
+ let state = initialState;
1404
+ const ephemeral = this.ephemeralLocals.get(checkpointKey) || {};
1357
1405
  state = {
1358
1406
  ...state,
1359
1407
  schemaVersion: state.schemaVersion ?? ENGINE_STATE_SCHEMA_VERSION,
@@ -1382,7 +1430,7 @@ var GraphExecutor = class {
1382
1430
  const signalRaw = state.local?.signal;
1383
1431
  if (isAbortSignal2(signalRaw) && signalRaw.aborted) {
1384
1432
  logger.warn("[GraphExecutor] \u6536\u5230 AbortSignal\uFF0C\u7ACB\u5373\u505C\u6B62\u63A8\u7406\u5FAA\u73AF");
1385
- this.ephemeralLocals.delete(conversationId);
1433
+ this.ephemeralLocals.delete(checkpointKey);
1386
1434
  throwAbortError();
1387
1435
  }
1388
1436
  const isLastStep = cycleStepCount >= this.config.maxSteps;
@@ -1430,8 +1478,8 @@ var GraphExecutor = class {
1430
1478
  checkpointCount
1431
1479
  });
1432
1480
  const cp2 = this.sanitize(state);
1433
- await this.checkpointer.save(conversationId, cp2);
1434
- this.ephemeralLocals.delete(conversationId);
1481
+ await this.checkpointer.save(checkpointKey, cp2);
1482
+ this.ephemeralLocals.delete(checkpointKey);
1435
1483
  return { events: allEvents, checkpoint: cp2, stepCount };
1436
1484
  }
1437
1485
  logger.info("[GraphExecutor] \u8282\u70B9\u5207\u6362", {
@@ -1442,18 +1490,18 @@ var GraphExecutor = class {
1442
1490
  });
1443
1491
  const nodeRunStartedAt = Date.now();
1444
1492
  const nodeIdForTelemetry = state.nodeId;
1493
+ const conversationIdForTelemetry = readRuntimeConversationId(state);
1445
1494
  let result;
1446
1495
  try {
1447
1496
  result = await node.run(state);
1448
1497
  } finally {
1449
- const turnIdForTelemetry = typeof state.local?.turnId === "string" ? state.local.turnId : void 0;
1450
1498
  this.telemetryPort.emit({
1451
1499
  kind: "graph_node",
1452
1500
  nodeId: nodeIdForTelemetry,
1453
1501
  durationMs: Date.now() - nodeRunStartedAt,
1454
1502
  scope: {
1455
- conversationId: conversationId || void 0,
1456
- turnId: turnIdForTelemetry
1503
+ conversationId: conversationIdForTelemetry,
1504
+ turnId: readRuntimeTurnId(state)
1457
1505
  }
1458
1506
  });
1459
1507
  }
@@ -1492,7 +1540,7 @@ var GraphExecutor = class {
1492
1540
  });
1493
1541
  state = { ...state, nodeId: nextNodeId };
1494
1542
  const cp2 = this.sanitize(state);
1495
- await this.checkpointer.save(conversationId, cp2);
1543
+ await this.checkpointer.save(checkpointKey, cp2);
1496
1544
  continue;
1497
1545
  }
1498
1546
  if (result.kind === "yield") {
@@ -1503,7 +1551,7 @@ var GraphExecutor = class {
1503
1551
  checkpointCount
1504
1552
  });
1505
1553
  const cp2 = this.sanitize(state);
1506
- await this.checkpointer.save(conversationId, cp2);
1554
+ await this.checkpointer.save(checkpointKey, cp2);
1507
1555
  return { events: allEvents, checkpoint: cp2, stepCount };
1508
1556
  }
1509
1557
  if (result.kind === "pause") {
@@ -1514,7 +1562,7 @@ var GraphExecutor = class {
1514
1562
  checkpointCount
1515
1563
  });
1516
1564
  const cp2 = this.sanitize(state);
1517
- await this.checkpointer.save(conversationId, cp2);
1565
+ await this.checkpointer.save(checkpointKey, cp2);
1518
1566
  return { events: allEvents, checkpoint: cp2, stepCount };
1519
1567
  }
1520
1568
  }
@@ -1525,8 +1573,8 @@ var GraphExecutor = class {
1525
1573
  checkpointCount
1526
1574
  });
1527
1575
  const cp = this.sanitize(state);
1528
- await this.checkpointer.save(conversationId, cp);
1529
- this.ephemeralLocals.delete(conversationId);
1576
+ await this.checkpointer.save(checkpointKey, cp);
1577
+ this.ephemeralLocals.delete(checkpointKey);
1530
1578
  return { events: allEvents, checkpoint: cp, stepCount };
1531
1579
  }
1532
1580
  };
@@ -1689,15 +1737,15 @@ function splitConcatenatedJsonObjects(input) {
1689
1737
  }
1690
1738
 
1691
1739
  // src/runtime-kernel/graph-engine/tick-pipeline/helpers.ts
1692
- function readNonEmptyString(value) {
1740
+ function readNonEmptyString2(value) {
1693
1741
  if (typeof value !== "string") return void 0;
1694
1742
  const trimmed = value.trim();
1695
1743
  return trimmed.length > 0 ? trimmed : void 0;
1696
1744
  }
1697
1745
  function resolveConversationIdForRuntimeEvents(toolContext) {
1698
- const fromCamel = readNonEmptyString(toolContext?.conversationId);
1746
+ const fromCamel = readNonEmptyString2(toolContext?.conversationId);
1699
1747
  if (fromCamel) return fromCamel;
1700
- const fromSnake = toolContext ? readNonEmptyString(toolContext["conversation_id"]) : void 0;
1748
+ const fromSnake = toolContext ? readNonEmptyString2(toolContext["conversation_id"]) : void 0;
1701
1749
  if (fromSnake) return fromSnake;
1702
1750
  return generateMessageId();
1703
1751
  }
@@ -2054,7 +2102,7 @@ var runModelLockMiddleware = async (ctx, stage, next) => {
2054
2102
  if (stage.id !== "execute_llm") {
2055
2103
  return;
2056
2104
  }
2057
- const normalized = readNonEmptyString(ctx.cloudQuotaFallbackAppliedModelId);
2105
+ const normalized = readNonEmptyString2(ctx.cloudQuotaFallbackAppliedModelId);
2058
2106
  if (!normalized) {
2059
2107
  return;
2060
2108
  }
@@ -2642,7 +2690,7 @@ function createExecuteLlmStage(dependencies) {
2642
2690
  streamEventHandler,
2643
2691
  ctx.signal,
2644
2692
  (fallbackModelId) => {
2645
- ctx.cloudQuotaFallbackAppliedModelId = readNonEmptyString(fallbackModelId);
2693
+ ctx.cloudQuotaFallbackAppliedModelId = readNonEmptyString2(fallbackModelId);
2646
2694
  },
2647
2695
  (info) => {
2648
2696
  ctx.modelFallbackAudit = info;
@@ -2686,7 +2734,7 @@ function createPrepareCallStage(dependencies) {
2686
2734
  return {
2687
2735
  id: "prepare_call",
2688
2736
  async run(ctx) {
2689
- const lockedRunModelId = readNonEmptyString(ctx.executorLocal?.runLockedModelId);
2737
+ const lockedRunModelId = readNonEmptyString2(ctx.executorLocal?.runLockedModelId);
2690
2738
  const requestedModelId = lockedRunModelId ?? ctx.request.model_id;
2691
2739
  ctx.modelId = dependencies.modelResolver.resolveModelId(requestedModelId);
2692
2740
  await emitAuditEnvelope(ctx.audit, {
@@ -2758,7 +2806,7 @@ var GraphAgentExecutor = class {
2758
2806
  this.llmCaller = dependencies.llmCaller;
2759
2807
  this.toolRuntime = dependencies.toolRuntime;
2760
2808
  this.contextBuilder = dependencies.contextBuilder;
2761
- this.cloudQuotaFallbackModelId = readNonEmptyString(dependencies.cloudQuotaFallbackModelId);
2809
+ this.cloudQuotaFallbackModelId = readNonEmptyString2(dependencies.cloudQuotaFallbackModelId);
2762
2810
  this.modelCatalog = dependencies.modelCatalog ?? createEmptyModelCatalog();
2763
2811
  this.modelResolver = dependencies.modelResolver ?? new ModelResolver({
2764
2812
  modelCatalog: this.modelCatalog
@@ -2806,7 +2854,7 @@ var GraphAgentExecutor = class {
2806
2854
  llmMessages: [],
2807
2855
  mode: input.request.mode === "chat" ? "chat" : "agent",
2808
2856
  conversationId: resolveConversationIdForRuntimeEvents(input.toolContext),
2809
- turnId: readNonEmptyString(input.toolContext?.turnId) ?? `turn_${Date.now()}`,
2857
+ turnId: readNonEmptyString2(input.toolContext?.turnId) ?? `turn_${Date.now()}`,
2810
2858
  telemetry: this.telemetryPort,
2811
2859
  audit: this.auditPort
2812
2860
  };
@@ -2856,18 +2904,18 @@ function isSummarizationCallbacks(value) {
2856
2904
  function isGraphSseSink(value) {
2857
2905
  return typeof value === "function";
2858
2906
  }
2859
- function readNonEmptyString2(value) {
2907
+ function readNonEmptyString3(value) {
2860
2908
  if (typeof value !== "string") return void 0;
2861
2909
  const trimmed = value.trim();
2862
2910
  return trimmed.length > 0 ? trimmed : void 0;
2863
2911
  }
2864
2912
  function readGraphAgentLocal(local) {
2865
2913
  const source = local ?? {};
2866
- const answerId = readNonEmptyString2(source.answerId);
2914
+ const answerId = readNonEmptyString3(source.answerId);
2867
2915
  const chunkSeq = Number.isInteger(source.chunkSeq) ? Number(source.chunkSeq) : 0;
2868
2916
  return {
2869
- conversationId: readNonEmptyString2(source.conversationId) ?? "",
2870
- turnId: readNonEmptyString2(source.turnId),
2917
+ conversationId: readNonEmptyString3(source.conversationId) ?? "",
2918
+ turnId: readNonEmptyString3(source.turnId),
2871
2919
  request: isAgentInvocationRequest(source.request) ? source.request : void 0,
2872
2920
  toolContext: isToolExecutionContext(source.toolContext) ? source.toolContext : void 0,
2873
2921
  history: isRuntimeEventArray(source.history) ? source.history : [],
@@ -3632,7 +3680,7 @@ var LlmNode = class {
3632
3680
  function isRecord8(value) {
3633
3681
  return typeof value === "object" && value !== null && !Array.isArray(value);
3634
3682
  }
3635
- function readNonEmptyString3(value) {
3683
+ function readNonEmptyString4(value) {
3636
3684
  if (typeof value !== "string") {
3637
3685
  return void 0;
3638
3686
  }
@@ -3654,7 +3702,7 @@ function resolveFinalAnswerFromToolResult(toolName, parsedResult) {
3654
3702
  return void 0;
3655
3703
  }
3656
3704
  if (toolName === "write_report") {
3657
- const report = readNonEmptyString3(data.report);
3705
+ const report = readNonEmptyString4(data.report);
3658
3706
  if (!report) {
3659
3707
  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");
3660
3708
  }
@@ -3664,7 +3712,7 @@ function resolveFinalAnswerFromToolResult(toolName, parsedResult) {
3664
3712
  if (data.success !== true) {
3665
3713
  return void 0;
3666
3714
  }
3667
- const finalAnswer = readNonEmptyString3(data.final_answer);
3715
+ const finalAnswer = readNonEmptyString4(data.final_answer);
3668
3716
  if (!finalAnswer) {
3669
3717
  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");
3670
3718
  }
@@ -4998,12 +5046,12 @@ function asRecord(value) {
4998
5046
  }
4999
5047
  return value;
5000
5048
  }
5001
- function summarizeCheckpoint(conversationId, state, savedAt) {
5049
+ function summarizeCheckpoint(checkpointKey, state, savedAt) {
5002
5050
  const local = asRecord(state.local);
5003
5051
  const executorLocal = asRecord(local?.executorLocal);
5004
5052
  const pendingToolCalls = local?.pendingToolCalls;
5005
5053
  return {
5006
- conversationId,
5054
+ checkpointKey,
5007
5055
  schemaVersion: state.schemaVersion ?? 1,
5008
5056
  savedAt,
5009
5057
  currentNode: state.nodeId,
@@ -5022,25 +5070,25 @@ var MemoryCheckpointer = class {
5022
5070
  local: state.local && typeof state.local === "object" && !Array.isArray(state.local) ? { ...state.local } : state.local
5023
5071
  };
5024
5072
  }
5025
- async load(conversationId) {
5026
- const entry = this.store.get(conversationId);
5073
+ async load(checkpointKey) {
5074
+ const entry = this.store.get(checkpointKey);
5027
5075
  return entry ? this.cloneState(entry.state) : null;
5028
5076
  }
5029
- async save(conversationId, state) {
5030
- this.store.set(conversationId, {
5077
+ async save(checkpointKey, state) {
5078
+ this.store.set(checkpointKey, {
5031
5079
  state: this.cloneState(state),
5032
5080
  savedAt: Date.now()
5033
5081
  });
5034
5082
  }
5035
- async clear(conversationId) {
5036
- this.store.delete(conversationId);
5083
+ async clear(checkpointKey) {
5084
+ this.store.delete(checkpointKey);
5037
5085
  }
5038
- async peekMeta(conversationId) {
5039
- const entry = this.store.get(conversationId);
5040
- return entry ? summarizeCheckpoint(conversationId, entry.state, entry.savedAt) : null;
5086
+ async peekMeta(checkpointKey) {
5087
+ const entry = this.store.get(checkpointKey);
5088
+ return entry ? summarizeCheckpoint(checkpointKey, entry.state, entry.savedAt) : null;
5041
5089
  }
5042
5090
  async list(filter = {}) {
5043
- 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);
5091
+ 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);
5044
5092
  if (filter.limit === void 0) {
5045
5093
  return summaries;
5046
5094
  }
@@ -6580,7 +6628,7 @@ function cloneRunRecord(record) {
6580
6628
  ...record,
6581
6629
  iterationBudget: record.iterationBudget ? { ...record.iterationBudget } : void 0,
6582
6630
  errorIfAny: record.errorIfAny ? { ...record.errorIfAny } : void 0,
6583
- metadata: record.metadata ? { ...record.metadata } : void 0
6631
+ metadata: record.metadata ? structuredClone(record.metadata) : void 0
6584
6632
  };
6585
6633
  }
6586
6634
  function matchesStatus(candidate, filter) {
@@ -6992,7 +7040,7 @@ function isTerminalStatus(status) {
6992
7040
  return status === "completed" || status === "failed" || status === "cancelled";
6993
7041
  }
6994
7042
  function cloneMetadata(metadata) {
6995
- return metadata ? { ...metadata } : void 0;
7043
+ return metadata ? structuredClone(metadata) : void 0;
6996
7044
  }
6997
7045
  function recordToSnapshot(record) {
6998
7046
  return {
@@ -7079,7 +7127,7 @@ var DefaultRunSupervisor = class {
7079
7127
  startedAt,
7080
7128
  updatedAt: startedAt,
7081
7129
  iterationBudget: spec.iterationBudget ? { ...spec.iterationBudget } : void 0,
7082
- metadata: spec.metadata ? { ...spec.metadata } : void 0
7130
+ metadata: cloneMetadata(spec.metadata)
7083
7131
  };
7084
7132
  await this.registryStore.save(record);
7085
7133
  const handle = new DefaultRunHandle({
@@ -7253,12 +7301,13 @@ var DefaultRunSupervisor = class {
7253
7301
  }
7254
7302
  try {
7255
7303
  await handle.markRunning({ currentNode: "detached" });
7304
+ const registeredRecord = await this.registryStore.load(handle.runId);
7256
7305
  const executorOutcome = await this.executor.execute({
7257
7306
  runId: handle.runId,
7258
- parentRunId: spec.parentRunId,
7259
- conversationId: spec.conversationId,
7260
- agentSpec: spec.agentSpec,
7261
- request: spec.request,
7307
+ parentRunId: handle.parentRunId,
7308
+ conversationId: registeredRecord?.conversationId ?? spec.conversationId,
7309
+ agentSpec: await handle.spec(),
7310
+ request: await handle.request(),
7262
7311
  signal: handle.signal,
7263
7312
  eventBus: spec.eventBus,
7264
7313
  eventStore: spec.eventStore,
@@ -7267,7 +7316,7 @@ var DefaultRunSupervisor = class {
7267
7316
  contextFences: spec.contextFences,
7268
7317
  wakeSource: spec.wakeSource,
7269
7318
  ephemeral: spec.ephemeral,
7270
- metadata: spec.metadata
7319
+ metadata: cloneMetadata(registeredRecord?.metadata ?? spec.metadata)
7271
7320
  });
7272
7321
  const outcome = await this.persistExecutorOutcome(handle, executorOutcome);
7273
7322
  this.notifyTerminalWaiters(outcome);
@@ -7331,10 +7380,14 @@ var DefaultRunSupervisor = class {
7331
7380
  await this.registryStore.save(record);
7332
7381
  }
7333
7382
  const completedAt = executorOutcome?.completedAt ?? this.now();
7383
+ const fallbackMeta = record ? void 0 : await handle.meta();
7334
7384
  const outcome = recordToTerminalOutcome(record ?? {
7335
7385
  runId: handle.runId,
7336
7386
  parentRunId: handle.parentRunId,
7337
- status: executorOutcome?.status ?? "completed"}, completedAt);
7387
+ conversationId: fallbackMeta?.conversationId ?? "",
7388
+ agentSpecId: fallbackMeta?.agentSpecId,
7389
+ status: executorOutcome?.status ?? "completed",
7390
+ startedAt: fallbackMeta?.startedAt ?? completedAt}, completedAt);
7338
7391
  const nextOutcome = {
7339
7392
  ...outcome,
7340
7393
  metadata: {
@@ -7662,6 +7715,7 @@ async function emitRunEvent(event, sink) {
7662
7715
  async function runAgent(agent, options) {
7663
7716
  const modelId = resolveModelId(agent, options);
7664
7717
  const conversationId = options.conversationId ?? `conv_${Date.now()}`;
7718
+ const checkpointKey = conversationId;
7665
7719
  const runId = options.runId ?? generateRunId();
7666
7720
  const turnId = runId;
7667
7721
  const costCollector = new QuickstartRunCostCollector();
@@ -7716,7 +7770,7 @@ async function runAgent(agent, options) {
7716
7770
  };
7717
7771
  await handle.markRunning({ currentNode: "user" });
7718
7772
  try {
7719
- await executor.prime(conversationId, {
7773
+ await executor.prime(checkpointKey, {
7720
7774
  conversationId,
7721
7775
  turnId,
7722
7776
  request: {
@@ -7741,7 +7795,7 @@ async function runAgent(agent, options) {
7741
7795
  return void 0;
7742
7796
  }
7743
7797
  });
7744
- const result = await executor.runUntilYield(conversationId);
7798
+ const result = await executor.runUntilYield(checkpointKey);
7745
7799
  runtimeEvents.push(...result.events);
7746
7800
  for (const event of result.events) {
7747
7801
  if (event.type === "final_answer_chunk") continue;