@linnlabs/linnkit 0.8.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 (83) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +1 -1
  3. package/README.zh-CN.md +1 -1
  4. package/bin/linnkit.cjs +7 -0
  5. package/dist/{agentSpec-EkmviZjy.d.cts → agentSpec-Du4Iye0q.d.cts} +16 -1
  6. package/dist/{agentSpec-EkmviZjy.d.ts → agentSpec-Du4Iye0q.d.ts} +16 -1
  7. package/dist/cli.cjs +234 -91
  8. package/dist/cli.cjs.map +1 -1
  9. package/dist/cli.js +234 -91
  10. package/dist/cli.js.map +1 -1
  11. package/dist/context-manager.cjs +230 -32
  12. package/dist/context-manager.cjs.map +1 -1
  13. package/dist/context-manager.d.cts +52 -15
  14. package/dist/context-manager.d.ts +52 -15
  15. package/dist/context-manager.js +230 -33
  16. package/dist/context-manager.js.map +1 -1
  17. package/dist/{context-trace-HE2qY5Q-.d.cts → context-trace-BHKDS-eq.d.cts} +2 -2
  18. package/dist/{context-trace-DRi5M4lX.d.ts → context-trace-CHbqHmyE.d.ts} +2 -2
  19. package/dist/contracts.cjs +3 -1
  20. package/dist/contracts.cjs.map +1 -1
  21. package/dist/contracts.d.cts +3 -3
  22. package/dist/contracts.d.ts +3 -3
  23. package/dist/contracts.js +3 -1
  24. package/dist/contracts.js.map +1 -1
  25. package/dist/{defaultGraphExecutor-BBswR8wn.d.ts → defaultGraphExecutor-B29_qTHy.d.ts} +16 -15
  26. package/dist/{defaultGraphExecutor-BIjJj7WF.d.cts → defaultGraphExecutor-C2E59v_R.d.cts} +16 -15
  27. package/dist/{index-Cm-JbzTH.d.cts → index-BAaUP9yU.d.cts} +38 -15
  28. package/dist/{index-DRBWi1fy.d.ts → index-BaVpVNi2.d.ts} +38 -15
  29. package/dist/{index-DO4dQgf2.d.cts → index-BnYCS8Zg.d.cts} +2 -2
  30. package/dist/{index-CJeWHopy.d.ts → index-C0DAjsdX.d.ts} +2 -2
  31. package/dist/{index-Dl5PLgAv.d.cts → index-CKQzzZ5Y.d.cts} +2 -2
  32. package/dist/{index-CHqwkvGp.d.ts → index-D0mKxTR5.d.ts} +2 -2
  33. package/dist/index.cjs +327 -110
  34. package/dist/index.cjs.map +1 -1
  35. package/dist/index.d.cts +10 -10
  36. package/dist/index.d.ts +10 -10
  37. package/dist/index.js +327 -110
  38. package/dist/index.js.map +1 -1
  39. package/dist/{ports-DnLuKfpE.d.ts → ports-DpPTFhSd.d.ts} +2 -2
  40. package/dist/{ports-DaatKJXp.d.cts → ports-s-tSp3sB.d.cts} +2 -2
  41. package/dist/quickstart.cjs +232 -88
  42. package/dist/quickstart.cjs.map +1 -1
  43. package/dist/quickstart.d.cts +7 -7
  44. package/dist/quickstart.d.ts +7 -7
  45. package/dist/quickstart.js +232 -88
  46. package/dist/quickstart.js.map +1 -1
  47. package/dist/{runAgent-CPj_9e58.d.ts → runAgent-C6F-399C.d.ts} +5 -5
  48. package/dist/{runAgent-HYKlXbVr.d.cts → runAgent-ilEj66Ik.d.cts} +5 -5
  49. package/dist/{runHandle-D3gPsD7B.d.cts → runHandle-BNOqS-Bl.d.cts} +3 -3
  50. package/dist/{runHandle-CyXvzgzk.d.ts → runHandle-BdLXOFqF.d.ts} +3 -3
  51. package/dist/runtime-kernel/events.cjs +1 -0
  52. package/dist/runtime-kernel/events.cjs.map +1 -1
  53. package/dist/runtime-kernel/events.d.cts +4 -4
  54. package/dist/runtime-kernel/events.d.ts +4 -4
  55. package/dist/runtime-kernel/events.js +1 -0
  56. package/dist/runtime-kernel/events.js.map +1 -1
  57. package/dist/runtime-kernel.cjs +318 -103
  58. package/dist/runtime-kernel.cjs.map +1 -1
  59. package/dist/runtime-kernel.d.cts +8 -8
  60. package/dist/runtime-kernel.d.ts +8 -8
  61. package/dist/runtime-kernel.js +315 -104
  62. package/dist/runtime-kernel.js.map +1 -1
  63. package/dist/testkit.cjs +331 -116
  64. package/dist/testkit.cjs.map +1 -1
  65. package/dist/testkit.d.cts +8 -8
  66. package/dist/testkit.d.ts +8 -8
  67. package/dist/testkit.js +331 -116
  68. package/dist/testkit.js.map +1 -1
  69. package/dist/{todo-B1PmDlp3.d.cts → todo-Ca8llpRQ.d.cts} +1 -1
  70. package/dist/{todo-B1PmDlp3.d.ts → todo-Ca8llpRQ.d.ts} +1 -1
  71. package/dist/{toolContracts-CLkQmhTG.d.cts → toolContracts-Bm3EZ1UM.d.cts} +13 -2
  72. package/dist/{toolContracts-Blll0241.d.ts → toolContracts-f8lzZBNa.d.ts} +13 -2
  73. package/docs/integration/README.md +1 -1
  74. package/docs/integration/agent-registration-guide.md +1 -1
  75. package/docs/integration/child-runs.md +4 -1
  76. package/docs/integration/context-engineering.md +30 -15
  77. package/docs/integration/context-fences.md +32 -3
  78. package/docs/integration/llm-provider.md +1 -1
  79. package/docs/integration/persistence.md +1 -0
  80. package/docs/integration/run-supervisor.md +3 -0
  81. package/docs/integration/tool-development-guide.md +7 -5
  82. package/docs/integration/tool-history.md +43 -17
  83. package/package.json +5 -4
package/dist/index.js CHANGED
@@ -46,14 +46,18 @@ __export(runtime_kernel_exports, {
46
46
  UserNode: () => UserNode,
47
47
  WaitUserNode: () => WaitUserNode,
48
48
  agentHasToolTrigger: () => agentHasToolTrigger,
49
+ appendStreamingProviderReasoningDetails: () => appendStreamingProviderReasoningDetails,
49
50
  applySystemReminders: () => applySystemReminders,
50
51
  audit: () => audit_exports,
51
52
  budgetWarningTrigger: () => budgetWarningTrigger,
52
53
  childRunTrace: () => child_run_trace_exports,
53
54
  childRuns: () => child_runs_exports,
55
+ compactProviderReasoningDetails: () => compactProviderReasoningDetails,
56
+ compactReasoningDetailsInValue: () => compactReasoningDetailsInValue,
54
57
  computeToolIdempotencyKey: () => computeToolIdempotencyKey,
55
58
  consoleAudit: () => consoleAudit,
56
59
  contextBudgetWarningTemplate: () => contextBudgetWarningTemplate,
60
+ copyToolContextRuntimeCapability: () => copyToolContextRuntimeCapability,
57
61
  countToolCallsInCurrentRequest: () => countToolCallsInCurrentRequest,
58
62
  createCompositeAudit: () => createCompositeAudit,
59
63
  createConsoleAudit: () => createConsoleAudit,
@@ -559,6 +563,7 @@ var AgentSpecBudgetPolicy = z.object({
559
563
  });
560
564
  var AgentSpecToolHistoryPolicy = z.object({
561
565
  strategy: z.enum(["per-pair", "per-run", "none"]).optional(),
566
+ retentionMode: z.enum(["drop", "compress"]).optional(),
562
567
  keepLatestToolPairs: z.number().int().nonnegative().optional(),
563
568
  keepLatestRuns: z.number().int().nonnegative().optional(),
564
569
  maxInteractionGroups: z.number().int().nonnegative().optional(),
@@ -681,12 +686,13 @@ var AgentSpecContextPolicy = z.object({
681
686
  var DEFAULT_CONTEXT_POLICY = {
682
687
  profileId: "agent",
683
688
  budget: {
684
- maxTokens: 12e4,
689
+ maxTokens: 232e3,
685
690
  reservedForResponse: 2400,
686
691
  workingMemoryBudgetPercentage: 0.7
687
692
  },
688
693
  toolHistory: {
689
694
  strategy: "per-run",
695
+ retentionMode: "drop",
690
696
  keepLatestToolPairs: 2,
691
697
  keepLatestRuns: 1,
692
698
  maxInteractionGroups: 12,
@@ -1538,6 +1544,17 @@ var logger = new Logger("GraphExecutor");
1538
1544
  function asLocalRecord(local) {
1539
1545
  return local && typeof local === "object" ? { ...local } : {};
1540
1546
  }
1547
+ function readNonEmptyString(value) {
1548
+ return typeof value === "string" && value.trim().length > 0 ? value : void 0;
1549
+ }
1550
+ function readRuntimeConversationId(state) {
1551
+ const local = state?.local && typeof state.local === "object" ? state.local : void 0;
1552
+ return readNonEmptyString(local?.conversationId);
1553
+ }
1554
+ function readRuntimeTurnId(state) {
1555
+ const local = state?.local && typeof state.local === "object" ? state.local : void 0;
1556
+ return readNonEmptyString(local?.turnId);
1557
+ }
1541
1558
  var GraphExecutor = class {
1542
1559
  constructor(checkpointer, config = {}) {
1543
1560
  this.checkpointer = checkpointer;
@@ -1555,8 +1572,8 @@ var GraphExecutor = class {
1555
1572
  registerNode(node) {
1556
1573
  this.nodes.set(node.id, node);
1557
1574
  }
1558
- async peekCheckpoint(conversationId) {
1559
- return await this.checkpointer.load(conversationId);
1575
+ async peekCheckpoint(checkpointKey) {
1576
+ return await this.checkpointer.load(checkpointKey);
1560
1577
  }
1561
1578
  sanitize(state) {
1562
1579
  const local = asLocalRecord(state.local);
@@ -1568,8 +1585,8 @@ var GraphExecutor = class {
1568
1585
  local
1569
1586
  };
1570
1587
  }
1571
- async prime(conversationId, local, nodeId = "user") {
1572
- this.ephemeralLocals.set(conversationId, { ...local || {} });
1588
+ async prime(checkpointKey, local, nodeId = "user") {
1589
+ this.ephemeralLocals.set(checkpointKey, { ...local || {} });
1573
1590
  const localSansMemory = { ...local || {} };
1574
1591
  if ("memory" in localSansMemory) delete localSansMemory.memory;
1575
1592
  const state = {
@@ -1577,10 +1594,10 @@ var GraphExecutor = class {
1577
1594
  schemaVersion: ENGINE_STATE_SCHEMA_VERSION,
1578
1595
  local: localSansMemory
1579
1596
  };
1580
- await this.checkpointer.save(conversationId, state);
1597
+ await this.checkpointer.save(checkpointKey, state);
1581
1598
  }
1582
- async setNode(conversationId, nodeId, localPatch) {
1583
- const current = await this.checkpointer.load(conversationId) || {
1599
+ async setNode(checkpointKey, nodeId, localPatch) {
1600
+ const current = await this.checkpointer.load(checkpointKey) || {
1584
1601
  schemaVersion: ENGINE_STATE_SCHEMA_VERSION,
1585
1602
  local: {}
1586
1603
  };
@@ -1591,19 +1608,46 @@ var GraphExecutor = class {
1591
1608
  schemaVersion: current.schemaVersion ?? ENGINE_STATE_SCHEMA_VERSION,
1592
1609
  local: mergedLocal
1593
1610
  };
1594
- await this.checkpointer.save(conversationId, next);
1611
+ await this.checkpointer.save(checkpointKey, next);
1595
1612
  }
1596
- async runUntilYield(conversationId) {
1613
+ async runUntilYield(checkpointKey) {
1597
1614
  const runId = `run_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
1598
1615
  let lifecyclePhase = "completed";
1616
+ let initialState = null;
1617
+ try {
1618
+ initialState = await this.loadInitialState(checkpointKey);
1619
+ } catch (err) {
1620
+ lifecyclePhase = "failed";
1621
+ this.telemetryPort.emit({
1622
+ kind: "run_lifecycle",
1623
+ runId,
1624
+ phase: "spawned",
1625
+ scope: {}
1626
+ });
1627
+ this.telemetryPort.emit({
1628
+ kind: "run_lifecycle",
1629
+ runId,
1630
+ phase: lifecyclePhase,
1631
+ scope: {}
1632
+ });
1633
+ throw err;
1634
+ }
1635
+ let lifecycleConversationId = readRuntimeConversationId(initialState);
1636
+ let lifecycleTurnId = readRuntimeTurnId(initialState);
1599
1637
  this.telemetryPort.emit({
1600
1638
  kind: "run_lifecycle",
1601
1639
  runId,
1602
1640
  phase: "spawned",
1603
- scope: { conversationId: conversationId || void 0 }
1641
+ scope: {
1642
+ conversationId: lifecycleConversationId,
1643
+ turnId: lifecycleTurnId
1644
+ }
1604
1645
  });
1605
1646
  try {
1606
- return await this.runUntilYieldInternal(conversationId);
1647
+ const result = await this.runUntilYieldInternal(checkpointKey, initialState);
1648
+ lifecycleConversationId = readRuntimeConversationId(result.checkpoint);
1649
+ lifecycleTurnId = readRuntimeTurnId(result.checkpoint);
1650
+ return result;
1607
1651
  } catch (err) {
1608
1652
  lifecyclePhase = err?.name === "AbortError" ? "cancelled" : "failed";
1609
1653
  throw err;
@@ -1612,17 +1656,23 @@ var GraphExecutor = class {
1612
1656
  kind: "run_lifecycle",
1613
1657
  runId,
1614
1658
  phase: lifecyclePhase,
1615
- scope: { conversationId: conversationId || void 0 }
1659
+ scope: {
1660
+ conversationId: lifecycleConversationId,
1661
+ turnId: lifecycleTurnId
1662
+ }
1616
1663
  });
1617
1664
  }
1618
1665
  }
1619
- async runUntilYieldInternal(conversationId) {
1620
- let state = await this.checkpointer.load(conversationId) || {
1666
+ async loadInitialState(checkpointKey) {
1667
+ return await this.checkpointer.load(checkpointKey) || {
1621
1668
  nodeId: "user",
1622
1669
  schemaVersion: ENGINE_STATE_SCHEMA_VERSION,
1623
1670
  local: {}
1624
1671
  };
1625
- const ephemeral = this.ephemeralLocals.get(conversationId) || {};
1672
+ }
1673
+ async runUntilYieldInternal(checkpointKey, initialState) {
1674
+ let state = initialState;
1675
+ const ephemeral = this.ephemeralLocals.get(checkpointKey) || {};
1626
1676
  state = {
1627
1677
  ...state,
1628
1678
  schemaVersion: state.schemaVersion ?? ENGINE_STATE_SCHEMA_VERSION,
@@ -1651,7 +1701,7 @@ var GraphExecutor = class {
1651
1701
  const signalRaw = state.local?.signal;
1652
1702
  if (isAbortSignal2(signalRaw) && signalRaw.aborted) {
1653
1703
  logger.warn("[GraphExecutor] \u6536\u5230 AbortSignal\uFF0C\u7ACB\u5373\u505C\u6B62\u63A8\u7406\u5FAA\u73AF");
1654
- this.ephemeralLocals.delete(conversationId);
1704
+ this.ephemeralLocals.delete(checkpointKey);
1655
1705
  throwAbortError();
1656
1706
  }
1657
1707
  const isLastStep = cycleStepCount >= this.config.maxSteps;
@@ -1699,8 +1749,8 @@ var GraphExecutor = class {
1699
1749
  checkpointCount
1700
1750
  });
1701
1751
  const cp2 = this.sanitize(state);
1702
- await this.checkpointer.save(conversationId, cp2);
1703
- this.ephemeralLocals.delete(conversationId);
1752
+ await this.checkpointer.save(checkpointKey, cp2);
1753
+ this.ephemeralLocals.delete(checkpointKey);
1704
1754
  return { events: allEvents, checkpoint: cp2, stepCount };
1705
1755
  }
1706
1756
  logger.info("[GraphExecutor] \u8282\u70B9\u5207\u6362", {
@@ -1711,18 +1761,18 @@ var GraphExecutor = class {
1711
1761
  });
1712
1762
  const nodeRunStartedAt = Date.now();
1713
1763
  const nodeIdForTelemetry = state.nodeId;
1764
+ const conversationIdForTelemetry = readRuntimeConversationId(state);
1714
1765
  let result;
1715
1766
  try {
1716
1767
  result = await node.run(state);
1717
1768
  } finally {
1718
- const turnIdForTelemetry = typeof state.local?.turnId === "string" ? state.local.turnId : void 0;
1719
1769
  this.telemetryPort.emit({
1720
1770
  kind: "graph_node",
1721
1771
  nodeId: nodeIdForTelemetry,
1722
1772
  durationMs: Date.now() - nodeRunStartedAt,
1723
1773
  scope: {
1724
- conversationId: conversationId || void 0,
1725
- turnId: turnIdForTelemetry
1774
+ conversationId: conversationIdForTelemetry,
1775
+ turnId: readRuntimeTurnId(state)
1726
1776
  }
1727
1777
  });
1728
1778
  }
@@ -1761,7 +1811,7 @@ var GraphExecutor = class {
1761
1811
  });
1762
1812
  state = { ...state, nodeId: nextNodeId };
1763
1813
  const cp2 = this.sanitize(state);
1764
- await this.checkpointer.save(conversationId, cp2);
1814
+ await this.checkpointer.save(checkpointKey, cp2);
1765
1815
  continue;
1766
1816
  }
1767
1817
  if (result.kind === "yield") {
@@ -1772,7 +1822,7 @@ var GraphExecutor = class {
1772
1822
  checkpointCount
1773
1823
  });
1774
1824
  const cp2 = this.sanitize(state);
1775
- await this.checkpointer.save(conversationId, cp2);
1825
+ await this.checkpointer.save(checkpointKey, cp2);
1776
1826
  return { events: allEvents, checkpoint: cp2, stepCount };
1777
1827
  }
1778
1828
  if (result.kind === "pause") {
@@ -1783,7 +1833,7 @@ var GraphExecutor = class {
1783
1833
  checkpointCount
1784
1834
  });
1785
1835
  const cp2 = this.sanitize(state);
1786
- await this.checkpointer.save(conversationId, cp2);
1836
+ await this.checkpointer.save(checkpointKey, cp2);
1787
1837
  return { events: allEvents, checkpoint: cp2, stepCount };
1788
1838
  }
1789
1839
  }
@@ -1794,8 +1844,8 @@ var GraphExecutor = class {
1794
1844
  checkpointCount
1795
1845
  });
1796
1846
  const cp = this.sanitize(state);
1797
- await this.checkpointer.save(conversationId, cp);
1798
- this.ephemeralLocals.delete(conversationId);
1847
+ await this.checkpointer.save(checkpointKey, cp);
1848
+ this.ephemeralLocals.delete(checkpointKey);
1799
1849
  return { events: allEvents, checkpoint: cp, stepCount };
1800
1850
  }
1801
1851
  };
@@ -1992,15 +2042,15 @@ function splitConcatenatedJsonObjects(input) {
1992
2042
  }
1993
2043
 
1994
2044
  // src/runtime-kernel/graph-engine/tick-pipeline/helpers.ts
1995
- function readNonEmptyString(value) {
2045
+ function readNonEmptyString2(value) {
1996
2046
  if (typeof value !== "string") return void 0;
1997
2047
  const trimmed = value.trim();
1998
2048
  return trimmed.length > 0 ? trimmed : void 0;
1999
2049
  }
2000
2050
  function resolveConversationIdForRuntimeEvents(toolContext) {
2001
- const fromCamel = readNonEmptyString(toolContext?.conversationId);
2051
+ const fromCamel = readNonEmptyString2(toolContext?.conversationId);
2002
2052
  if (fromCamel) return fromCamel;
2003
- const fromSnake = toolContext ? readNonEmptyString(toolContext["conversation_id"]) : void 0;
2053
+ const fromSnake = toolContext ? readNonEmptyString2(toolContext["conversation_id"]) : void 0;
2004
2054
  if (fromSnake) return fromSnake;
2005
2055
  return generateMessageId();
2006
2056
  }
@@ -2382,7 +2432,7 @@ var runModelLockMiddleware = async (ctx, stage, next) => {
2382
2432
  if (stage.id !== "execute_llm") {
2383
2433
  return;
2384
2434
  }
2385
- const normalized = readNonEmptyString(ctx.cloudQuotaFallbackAppliedModelId);
2435
+ const normalized = readNonEmptyString2(ctx.cloudQuotaFallbackAppliedModelId);
2386
2436
  if (!normalized) {
2387
2437
  return;
2388
2438
  }
@@ -2983,7 +3033,7 @@ function createExecuteLlmStage(dependencies) {
2983
3033
  streamEventHandler,
2984
3034
  ctx.signal,
2985
3035
  (fallbackModelId) => {
2986
- ctx.cloudQuotaFallbackAppliedModelId = readNonEmptyString(fallbackModelId);
3036
+ ctx.cloudQuotaFallbackAppliedModelId = readNonEmptyString2(fallbackModelId);
2987
3037
  },
2988
3038
  (info) => {
2989
3039
  ctx.modelFallbackAudit = info;
@@ -3027,7 +3077,7 @@ function createPrepareCallStage(dependencies) {
3027
3077
  return {
3028
3078
  id: "prepare_call",
3029
3079
  async run(ctx) {
3030
- const lockedRunModelId = readNonEmptyString(ctx.executorLocal?.runLockedModelId);
3080
+ const lockedRunModelId = readNonEmptyString2(ctx.executorLocal?.runLockedModelId);
3031
3081
  const requestedModelId = lockedRunModelId ?? ctx.request.model_id;
3032
3082
  ctx.modelId = dependencies.modelResolver.resolveModelId(requestedModelId);
3033
3083
  await emitAuditEnvelope(ctx.audit, {
@@ -3099,7 +3149,7 @@ var GraphAgentExecutor = class {
3099
3149
  this.llmCaller = dependencies.llmCaller;
3100
3150
  this.toolRuntime = dependencies.toolRuntime;
3101
3151
  this.contextBuilder = dependencies.contextBuilder;
3102
- this.cloudQuotaFallbackModelId = readNonEmptyString(dependencies.cloudQuotaFallbackModelId);
3152
+ this.cloudQuotaFallbackModelId = readNonEmptyString2(dependencies.cloudQuotaFallbackModelId);
3103
3153
  this.modelCatalog = dependencies.modelCatalog ?? createEmptyModelCatalog();
3104
3154
  this.modelResolver = dependencies.modelResolver ?? new ModelResolver({
3105
3155
  modelCatalog: this.modelCatalog
@@ -3147,7 +3197,7 @@ var GraphAgentExecutor = class {
3147
3197
  llmMessages: [],
3148
3198
  mode: input.request.mode === "chat" ? "chat" : "agent",
3149
3199
  conversationId: resolveConversationIdForRuntimeEvents(input.toolContext),
3150
- turnId: readNonEmptyString(input.toolContext?.turnId) ?? `turn_${Date.now()}`,
3200
+ turnId: readNonEmptyString2(input.toolContext?.turnId) ?? `turn_${Date.now()}`,
3151
3201
  telemetry: this.telemetryPort,
3152
3202
  audit: this.auditPort
3153
3203
  };
@@ -3197,18 +3247,18 @@ function isSummarizationCallbacks(value) {
3197
3247
  function isGraphSseSink(value) {
3198
3248
  return typeof value === "function";
3199
3249
  }
3200
- function readNonEmptyString2(value) {
3250
+ function readNonEmptyString3(value) {
3201
3251
  if (typeof value !== "string") return void 0;
3202
3252
  const trimmed = value.trim();
3203
3253
  return trimmed.length > 0 ? trimmed : void 0;
3204
3254
  }
3205
3255
  function readGraphAgentLocal(local) {
3206
3256
  const source = local ?? {};
3207
- const answerId = readNonEmptyString2(source.answerId);
3257
+ const answerId = readNonEmptyString3(source.answerId);
3208
3258
  const chunkSeq = Number.isInteger(source.chunkSeq) ? Number(source.chunkSeq) : 0;
3209
3259
  return {
3210
- conversationId: readNonEmptyString2(source.conversationId) ?? "",
3211
- turnId: readNonEmptyString2(source.turnId),
3260
+ conversationId: readNonEmptyString3(source.conversationId) ?? "",
3261
+ turnId: readNonEmptyString3(source.turnId),
3212
3262
  request: isAgentInvocationRequest(source.request) ? source.request : void 0,
3213
3263
  toolContext: isToolExecutionContext(source.toolContext) ? source.toolContext : void 0,
3214
3264
  history: isRuntimeEventArray(source.history) ? source.history : [],
@@ -3973,7 +4023,7 @@ var LlmNode = class {
3973
4023
  function isRecord8(value) {
3974
4024
  return typeof value === "object" && value !== null && !Array.isArray(value);
3975
4025
  }
3976
- function readNonEmptyString3(value) {
4026
+ function readNonEmptyString4(value) {
3977
4027
  if (typeof value !== "string") {
3978
4028
  return void 0;
3979
4029
  }
@@ -3995,7 +4045,7 @@ function resolveFinalAnswerFromToolResult(toolName, parsedResult) {
3995
4045
  return void 0;
3996
4046
  }
3997
4047
  if (toolName === "write_report") {
3998
- const report = readNonEmptyString3(data.report);
4048
+ const report = readNonEmptyString4(data.report);
3999
4049
  if (!report) {
4000
4050
  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");
4001
4051
  }
@@ -4005,7 +4055,7 @@ function resolveFinalAnswerFromToolResult(toolName, parsedResult) {
4005
4055
  if (data.success !== true) {
4006
4056
  return void 0;
4007
4057
  }
4008
- const finalAnswer = readNonEmptyString3(data.final_answer);
4058
+ const finalAnswer = readNonEmptyString4(data.final_answer);
4009
4059
  if (!finalAnswer) {
4010
4060
  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");
4011
4061
  }
@@ -4555,6 +4605,31 @@ function ensureToolContextRuntimeCapability(params) {
4555
4605
  function getToolContextRuntimeBinding(context) {
4556
4606
  return readBinding(context);
4557
4607
  }
4608
+ function copyToolContextRuntimeCapability(source, target) {
4609
+ const sourceBinding = readBinding(source);
4610
+ if (!sourceBinding) {
4611
+ return void 0;
4612
+ }
4613
+ const existingTargetBinding = readBinding(target);
4614
+ if (existingTargetBinding) {
4615
+ exposeCompatibilitySurface(target, existingTargetBinding);
4616
+ return existingTargetBinding;
4617
+ }
4618
+ const targetBinding = createRuntimeBinding({
4619
+ context: target,
4620
+ persistedHistory: () => sourceBinding.getPersistedHistoryEvents(),
4621
+ workingHistory: () => sourceBinding.getWorkingHistoryEvents(),
4622
+ executionMeta: sourceBinding.readExecutionMeta()
4623
+ });
4624
+ Object.defineProperty(target, TOOL_CONTEXT_RUNTIME_BINDING_KEY, {
4625
+ value: targetBinding,
4626
+ enumerable: false,
4627
+ configurable: true,
4628
+ writable: false
4629
+ });
4630
+ exposeCompatibilitySurface(target, targetBinding);
4631
+ return targetBinding;
4632
+ }
4558
4633
  function readToolContextWorkingHistory(context) {
4559
4634
  if (context.conversationView) {
4560
4635
  return context.conversationView.getWorkingHistoryEvents();
@@ -4968,6 +5043,22 @@ var ToolNode = class {
4968
5043
  });
4969
5044
  }
4970
5045
  async run(state) {
5046
+ const events = [];
5047
+ while (true) {
5048
+ const result = await this.runNextPendingToolCall(state);
5049
+ if (Array.isArray(result.events) && result.events.length > 0) {
5050
+ events.push(...result.events);
5051
+ }
5052
+ if (result.kind === "route" && result.nextNodeId === "tool") {
5053
+ continue;
5054
+ }
5055
+ return {
5056
+ ...result,
5057
+ events
5058
+ };
5059
+ }
5060
+ }
5061
+ async runNextPendingToolCall(state) {
4971
5062
  const calls = state.local?.pendingToolCalls ?? [];
4972
5063
  const signalRaw = state.local?.signal;
4973
5064
  if (isAbortSignal(signalRaw) && signalRaw.aborted) {
@@ -5175,18 +5266,25 @@ var ToolNode = class {
5175
5266
  rawArguments: context.call.function?.arguments,
5176
5267
  parsedArguments: context.toolArgs
5177
5268
  });
5269
+ const remainingCalls = context.calls.slice(1);
5178
5270
  context.state.local = buildErrorLocalState({
5179
5271
  local: context.local,
5180
- remainingCalls: context.calls.slice(1),
5272
+ remainingCalls,
5181
5273
  conversationId: context.conversationId,
5182
5274
  turnId: context.turnId,
5183
5275
  runtimeEvents: context.bridge.getRuntimeEvents(),
5184
5276
  nextProtocolErrorCount: fuse.nextCount
5185
5277
  });
5186
- if (fuse.shouldFuse) {
5278
+ if (fuse.shouldFuse && remainingCalls.length === 0) {
5187
5279
  throw createToolProtocolFuseError(fuse.nextCount, context.exec.error);
5188
5280
  }
5189
- return { kind: "route", nextNodeId: "llm", events: context.bridge.getRuntimeEvents() };
5281
+ return {
5282
+ kind: "route",
5283
+ // 同一个 assistant.tool_calls batch 必须为每个 call 产出 tool_output。
5284
+ // 出错时也继续消费剩余 call,ToolNode.run 会在本节点内 drain 完 batch 再回 LLM。
5285
+ nextNodeId: remainingCalls.length > 0 ? "tool" : "llm",
5286
+ events: context.bridge.getRuntimeEvents()
5287
+ };
5190
5288
  }
5191
5289
  };
5192
5290
 
@@ -5383,12 +5481,12 @@ function asRecord(value) {
5383
5481
  }
5384
5482
  return value;
5385
5483
  }
5386
- function summarizeCheckpoint(conversationId, state, savedAt) {
5484
+ function summarizeCheckpoint(checkpointKey, state, savedAt) {
5387
5485
  const local = asRecord(state.local);
5388
5486
  const executorLocal = asRecord(local?.executorLocal);
5389
5487
  const pendingToolCalls = local?.pendingToolCalls;
5390
5488
  return {
5391
- conversationId,
5489
+ checkpointKey,
5392
5490
  schemaVersion: state.schemaVersion ?? 1,
5393
5491
  savedAt,
5394
5492
  currentNode: state.nodeId,
@@ -5407,25 +5505,25 @@ var MemoryCheckpointer = class {
5407
5505
  local: state.local && typeof state.local === "object" && !Array.isArray(state.local) ? { ...state.local } : state.local
5408
5506
  };
5409
5507
  }
5410
- async load(conversationId) {
5411
- const entry = this.store.get(conversationId);
5508
+ async load(checkpointKey) {
5509
+ const entry = this.store.get(checkpointKey);
5412
5510
  return entry ? this.cloneState(entry.state) : null;
5413
5511
  }
5414
- async save(conversationId, state) {
5415
- this.store.set(conversationId, {
5512
+ async save(checkpointKey, state) {
5513
+ this.store.set(checkpointKey, {
5416
5514
  state: this.cloneState(state),
5417
5515
  savedAt: Date.now()
5418
5516
  });
5419
5517
  }
5420
- async clear(conversationId) {
5421
- this.store.delete(conversationId);
5518
+ async clear(checkpointKey) {
5519
+ this.store.delete(checkpointKey);
5422
5520
  }
5423
- async peekMeta(conversationId) {
5424
- const entry = this.store.get(conversationId);
5425
- return entry ? summarizeCheckpoint(conversationId, entry.state, entry.savedAt) : null;
5521
+ async peekMeta(checkpointKey) {
5522
+ const entry = this.store.get(checkpointKey);
5523
+ return entry ? summarizeCheckpoint(checkpointKey, entry.state, entry.savedAt) : null;
5426
5524
  }
5427
5525
  async list(filter = {}) {
5428
- 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);
5526
+ 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);
5429
5527
  if (filter.limit === void 0) {
5430
5528
  return summaries;
5431
5529
  }
@@ -5497,6 +5595,7 @@ __export(tools_exports, {
5497
5595
  CommonParameterTypes: () => CommonParameterTypes,
5498
5596
  ContextCheckpointTool: () => ContextCheckpointTool,
5499
5597
  computeToolIdempotencyKey: () => computeToolIdempotencyKey,
5598
+ copyToolContextRuntimeCapability: () => copyToolContextRuntimeCapability,
5500
5599
  createContextCheckpointTool: () => createContextCheckpointTool,
5501
5600
  ensureToolContextRuntimeCapability: () => ensureToolContextRuntimeCapability,
5502
5601
  findCachedToolOutputByIdempotencyKey: () => findCachedToolOutputByIdempotencyKey,
@@ -5690,7 +5789,7 @@ function createContextCheckpointTool(options) {
5690
5789
  function isRecord15(value) {
5691
5790
  return !!value && typeof value === "object" && !Array.isArray(value);
5692
5791
  }
5693
- function readNonEmptyString4(value) {
5792
+ function readNonEmptyString5(value) {
5694
5793
  if (typeof value !== "string") {
5695
5794
  return void 0;
5696
5795
  }
@@ -5710,13 +5809,13 @@ function readToolContextUserQuery(context) {
5710
5809
  if (!context) {
5711
5810
  return void 0;
5712
5811
  }
5713
- return readNonEmptyString4(context["user_query"]);
5812
+ return readNonEmptyString5(context["user_query"]);
5714
5813
  }
5715
5814
  function readToolContextModelId(context) {
5716
5815
  if (!context) {
5717
5816
  return void 0;
5718
5817
  }
5719
- return readNonEmptyString4(context["modelId"]);
5818
+ return readNonEmptyString5(context["modelId"]);
5720
5819
  }
5721
5820
  function readToolContextRunContext(context) {
5722
5821
  if (!context) {
@@ -5923,18 +6022,18 @@ function createClassification(category, reason, suggestedDelay, extras) {
5923
6022
  }
5924
6023
  var ErrorClassifier = class {
5925
6024
  static classify(error, context) {
5926
- const isRecord24 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
6025
+ const isRecord25 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
5927
6026
  const baseMsg = (error.message || "").toLowerCase();
5928
6027
  const causeMsg = (() => {
5929
6028
  const cause = error.cause;
5930
6029
  if (typeof cause === "string") return cause.toLowerCase();
5931
6030
  if (cause instanceof Error) return (cause.message || "").toLowerCase();
5932
- if (isRecord24(cause) && typeof cause["message"] === "string") return String(cause["message"]).toLowerCase();
6031
+ if (isRecord25(cause) && typeof cause["message"] === "string") return String(cause["message"]).toLowerCase();
5933
6032
  return "";
5934
6033
  })();
5935
6034
  const causeCode = (() => {
5936
6035
  const cause = error.cause;
5937
- if (isRecord24(cause) && typeof cause["code"] === "string") return String(cause["code"]);
6036
+ if (isRecord25(cause) && typeof cause["code"] === "string") return String(cause["code"]);
5938
6037
  return "";
5939
6038
  })();
5940
6039
  const errorMessage = `${baseMsg} ${causeMsg}`.trim();
@@ -6426,6 +6525,9 @@ __export(llm_exports, {
6426
6525
  LLMPolicyEngine: () => LLMPolicyEngine,
6427
6526
  LlmCaller: () => LlmCaller,
6428
6527
  ModelResolver: () => ModelResolver,
6528
+ appendStreamingProviderReasoningDetails: () => appendStreamingProviderReasoningDetails,
6529
+ compactProviderReasoningDetails: () => compactProviderReasoningDetails,
6530
+ compactReasoningDetailsInValue: () => compactReasoningDetailsInValue,
6429
6531
  createDefaultTokenizerPort: () => createDefaultTokenizerPort,
6430
6532
  defaultPolicyEngine: () => defaultPolicyEngine
6431
6533
  });
@@ -6815,6 +6917,90 @@ function assertToolCallsHaveValidJsonArguments(toolCalls) {
6815
6917
  }
6816
6918
  }
6817
6919
 
6920
+ // src/runtime-kernel/llm/reasoning-details.ts
6921
+ var mergeableTextFields = ["reasoning_content"];
6922
+ function isRecord20(value) {
6923
+ return !!value && typeof value === "object" && !Array.isArray(value);
6924
+ }
6925
+ function findMergeableTextField(detail) {
6926
+ if (!isRecord20(detail)) return void 0;
6927
+ if (typeof detail.provider !== "string") return void 0;
6928
+ if (typeof detail.type !== "string") return void 0;
6929
+ for (const field of mergeableTextFields) {
6930
+ if (typeof detail[field] === "string") {
6931
+ return field;
6932
+ }
6933
+ }
6934
+ return void 0;
6935
+ }
6936
+ function hasOnlyStableTextDetailFields(detail, textField) {
6937
+ const allowedKeys = /* @__PURE__ */ new Set(["provider", "type", textField]);
6938
+ return Object.keys(detail).every((key) => allowedKeys.has(key));
6939
+ }
6940
+ function canMergeTextDetails(previous, incoming) {
6941
+ if (!isRecord20(previous) || !isRecord20(incoming)) return false;
6942
+ const previousField = findMergeableTextField(previous);
6943
+ const incomingField = findMergeableTextField(incoming);
6944
+ if (!previousField || previousField !== incomingField) return false;
6945
+ return previous.provider === incoming.provider && previous.type === incoming.type && hasOnlyStableTextDetailFields(previous, previousField) && hasOnlyStableTextDetailFields(incoming, incomingField);
6946
+ }
6947
+ function mergeStreamingText(previous, incoming) {
6948
+ if (!previous) return incoming;
6949
+ if (!incoming) return previous;
6950
+ if (incoming.startsWith(previous)) {
6951
+ return incoming;
6952
+ }
6953
+ if (previous.endsWith(incoming)) {
6954
+ return previous;
6955
+ }
6956
+ return `${previous}${incoming}`;
6957
+ }
6958
+ function appendStreamingProviderReasoningDetails(existing, incoming) {
6959
+ const next = [...existing];
6960
+ for (const detail of incoming) {
6961
+ const previous = next[next.length - 1];
6962
+ if (canMergeTextDetails(previous, detail)) {
6963
+ const textField = findMergeableTextField(previous);
6964
+ if (textField && isRecord20(detail)) {
6965
+ const mergedText = mergeStreamingText(String(previous[textField]), String(detail[textField]));
6966
+ if (mergedText === previous[textField]) {
6967
+ continue;
6968
+ }
6969
+ next[next.length - 1] = {
6970
+ ...previous,
6971
+ [textField]: mergedText
6972
+ };
6973
+ continue;
6974
+ }
6975
+ }
6976
+ next.push(detail);
6977
+ }
6978
+ return next;
6979
+ }
6980
+ function compactProviderReasoningDetails(reasoningDetails) {
6981
+ return appendStreamingProviderReasoningDetails([], reasoningDetails);
6982
+ }
6983
+ function compactReasoningDetailsInValue(value) {
6984
+ return compactValue(value);
6985
+ }
6986
+ function compactValue(value) {
6987
+ if (Array.isArray(value)) {
6988
+ return value.map((item) => compactValue(item));
6989
+ }
6990
+ if (!isRecord20(value)) {
6991
+ return value;
6992
+ }
6993
+ const compacted = {};
6994
+ for (const [key, childValue] of Object.entries(value)) {
6995
+ if (key === "reasoning_details" && Array.isArray(childValue)) {
6996
+ compacted[key] = compactProviderReasoningDetails(childValue);
6997
+ continue;
6998
+ }
6999
+ compacted[key] = compactValue(childValue);
7000
+ }
7001
+ return compacted;
7002
+ }
7003
+
6818
7004
  // src/runtime-kernel/llm/streaming-adapter.ts
6819
7005
  async function callLlmStream(params) {
6820
7006
  const {
@@ -6827,7 +7013,7 @@ async function callLlmStream(params) {
6827
7013
  } = params;
6828
7014
  let fullResponse = "";
6829
7015
  let streamError = null;
6830
- const reasoningDetails = [];
7016
+ let reasoningDetails = [];
6831
7017
  const streamAnswerId = generateMessageId();
6832
7018
  let streamChunkSeq = 0;
6833
7019
  let capturedUsage = void 0;
@@ -6897,13 +7083,21 @@ async function callLlmStream(params) {
6897
7083
  const reasoning = isRecord19(chunk) ? chunk["reasoning_details"] : void 0;
6898
7084
  if (reasoning !== void 0) {
6899
7085
  const newReasoningDetails = Array.isArray(reasoning) ? reasoning : [reasoning];
6900
- reasoningDetails.push(...newReasoningDetails);
6901
- eventHandler({
6902
- type: "provider_sidecar",
6903
- id: generateMessageId(),
6904
- timestamp: Date.now(),
6905
- reasoning_details: newReasoningDetails
6906
- });
7086
+ const previousReasoningDetails = reasoningDetails;
7087
+ const previousLength = previousReasoningDetails.length;
7088
+ const compactedReasoningDetails = appendStreamingProviderReasoningDetails(reasoningDetails, newReasoningDetails);
7089
+ reasoningDetails = compactedReasoningDetails;
7090
+ const previousLastChanged = previousLength > 0 && compactedReasoningDetails[previousLength - 1] !== previousReasoningDetails[previousLength - 1];
7091
+ const emitFromIndex = previousLastChanged ? previousLength - 1 : previousLength;
7092
+ const emittedReasoningDetails = compactedReasoningDetails.slice(Math.max(0, emitFromIndex));
7093
+ if (emittedReasoningDetails.length > 0) {
7094
+ eventHandler({
7095
+ type: "provider_sidecar",
7096
+ id: generateMessageId(),
7097
+ timestamp: Date.now(),
7098
+ reasoning_details: emittedReasoningDetails
7099
+ });
7100
+ }
6907
7101
  }
6908
7102
  if (chunk.tool_calls) {
6909
7103
  emitThoughtComplete(thoughtSegmenter.onBoundary());
@@ -7357,7 +7551,6 @@ __export(child_runs_exports, {
7357
7551
 
7358
7552
  // src/runtime-kernel/child-runs/childToolContext.ts
7359
7553
  function createChildRunToolContext(params) {
7360
- const inheritedConversationId = typeof params.parentToolContext.conversationId === "string" && params.parentToolContext.conversationId.trim().length > 0 ? params.parentToolContext.conversationId.trim() : void 0;
7361
7554
  const inheritedContext = stripRuntimeReservedToolContextPatch(params.parentToolContext);
7362
7555
  const childToolContext = {
7363
7556
  ...inheritedContext,
@@ -7369,7 +7562,7 @@ function createChildRunToolContext(params) {
7369
7562
  persistedHistory: params.seedHistory,
7370
7563
  workingHistory: params.seedHistory,
7371
7564
  executionMeta: {
7372
- conversationId: inheritedConversationId ?? params.internalConversationId,
7565
+ conversationId: params.conversationId,
7373
7566
  turnId: params.turnId,
7374
7567
  runId: params.runId,
7375
7568
  parentRunId: params.parentRunId
@@ -7520,7 +7713,7 @@ var FinalAnswerCollector = class {
7520
7713
  };
7521
7714
 
7522
7715
  // src/runtime-kernel/child-runs/childRunTraceSink.ts
7523
- function isRecord20(v) {
7716
+ function isRecord21(v) {
7524
7717
  return !!v && typeof v === "object" && !Array.isArray(v);
7525
7718
  }
7526
7719
  function getString2(obj, key) {
@@ -7553,7 +7746,7 @@ function createChildRunTraceSink(params) {
7553
7746
  const { publisher, conversationId, turnId } = params;
7554
7747
  const finalAnswerCollector = new FinalAnswerCollector(conversationId, turnId);
7555
7748
  const sink = (evt) => {
7556
- if (!isRecord20(evt)) {
7749
+ if (!isRecord21(evt)) {
7557
7750
  return [];
7558
7751
  }
7559
7752
  const type = getString2(evt, "type");
@@ -7689,7 +7882,7 @@ function readCheckpointHistory(checkpoint) {
7689
7882
  });
7690
7883
  }
7691
7884
  async function recoverChildRunEventsFromCheckpoint(params) {
7692
- const checkpoint = await params.checkpointer.load(params.conversationId);
7885
+ const checkpoint = await params.checkpointer.load(params.checkpointKey);
7693
7886
  const history = readCheckpointHistory(checkpoint);
7694
7887
  if (history.length === 0) {
7695
7888
  return [];
@@ -7697,7 +7890,7 @@ async function recoverChildRunEventsFromCheckpoint(params) {
7697
7890
  if (hasSeedHistoryPrefix(history, params.seedHistory)) {
7698
7891
  return history.slice(params.seedHistory.length);
7699
7892
  }
7700
- return history.filter((event) => event.conversation_id === params.internalConversationId);
7893
+ return history.filter((event) => event.conversation_id === params.childConversationId);
7701
7894
  }
7702
7895
 
7703
7896
  // src/runtime-kernel/child-runs/childRunInvoker.ts
@@ -7726,6 +7919,7 @@ var ChildRunInvoker = class {
7726
7919
  agentConfig,
7727
7920
  userMessage,
7728
7921
  parentToolContext,
7922
+ conversationId,
7729
7923
  runId,
7730
7924
  parentRunId,
7731
7925
  subrunTracePublisher,
@@ -7734,12 +7928,18 @@ var ChildRunInvoker = class {
7734
7928
  modelId,
7735
7929
  abortSignal
7736
7930
  } = config;
7737
- const internalConversationId = `internal_${generateMessageId()}`;
7931
+ const internalCheckpointKey = `internal_${generateMessageId()}`;
7932
+ const runtimeConversationId = resolveChildRunConversationId({
7933
+ explicitConversationId: conversationId,
7934
+ parentToolContext,
7935
+ fallbackConversationId: internalCheckpointKey
7936
+ });
7738
7937
  const turnId = `turn_${Date.now()}`;
7739
- const childRunId = typeof runId === "string" && runId.trim().length > 0 ? runId.trim() : internalConversationId;
7938
+ const childRunId = typeof runId === "string" && runId.trim().length > 0 ? runId.trim() : internalCheckpointKey;
7740
7939
  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;
7741
7940
  logger13.info(`\u542F\u52A8 child-run: ${agentConfig.id}`, {
7742
- conversationId: internalConversationId,
7941
+ conversationId: runtimeConversationId,
7942
+ checkpointKey: internalCheckpointKey,
7743
7943
  maxSteps,
7744
7944
  userMessage: userMessage.slice(0, 100) + (userMessage.length > 100 ? "..." : "")
7745
7945
  });
@@ -7800,7 +8000,7 @@ var ChildRunInvoker = class {
7800
8000
  const seedHistory = Array.isArray(seedHistoryEvents) ? seedHistoryEvents : [];
7801
8001
  const childToolContext = createChildRunToolContext({
7802
8002
  parentToolContext,
7803
- internalConversationId,
8003
+ conversationId: runtimeConversationId,
7804
8004
  turnId,
7805
8005
  runId: childRunId,
7806
8006
  parentRunId: resolvedParentRunId,
@@ -7809,13 +8009,13 @@ var ChildRunInvoker = class {
7809
8009
  });
7810
8010
  const subrunSseSink = subrunTracePublisher ? createChildRunTraceSink({
7811
8011
  publisher: subrunTracePublisher,
7812
- conversationId: internalConversationId,
8012
+ conversationId: runtimeConversationId,
7813
8013
  turnId
7814
8014
  }) : void 0;
7815
8015
  const initialLocal = {
7816
8016
  request,
7817
8017
  history: seedHistory,
7818
- conversationId: internalConversationId,
8018
+ conversationId: runtimeConversationId,
7819
8019
  turnId,
7820
8020
  toolContext: childToolContext,
7821
8021
  ...abortSignal ? { signal: abortSignal } : {},
@@ -7823,7 +8023,7 @@ var ChildRunInvoker = class {
7823
8023
  ...subrunSseSink ? { sseSink: subrunSseSink } : {},
7824
8024
  systemPrompt
7825
8025
  };
7826
- await graphExecutor.prime(internalConversationId, initialLocal, "llm");
8026
+ await graphExecutor.prime(internalCheckpointKey, initialLocal, "llm");
7827
8027
  const allEvents = [];
7828
8028
  let stepCount = 0;
7829
8029
  let finalAnswer;
@@ -7835,7 +8035,7 @@ var ChildRunInvoker = class {
7835
8035
  err.name = "AbortError";
7836
8036
  throw err;
7837
8037
  }
7838
- const result = await graphExecutor.runUntilYield(internalConversationId);
8038
+ const result = await graphExecutor.runUntilYield(internalCheckpointKey);
7839
8039
  appendUniqueEvents(allEvents, result.events);
7840
8040
  stepCount = result.stepCount;
7841
8041
  if (subrunSseSink && typeof subrunSseSink.finalize === "function") {
@@ -7869,8 +8069,8 @@ var ChildRunInvoker = class {
7869
8069
  }
7870
8070
  const recoveredEvents = await recoverChildRunEventsFromCheckpoint({
7871
8071
  checkpointer,
7872
- conversationId: internalConversationId,
7873
- internalConversationId,
8072
+ checkpointKey: internalCheckpointKey,
8073
+ childConversationId: runtimeConversationId,
7874
8074
  seedHistory
7875
8075
  });
7876
8076
  appendUniqueEvents(allEvents, recoveredEvents);
@@ -7887,7 +8087,7 @@ var ChildRunInvoker = class {
7887
8087
  stack: err.stack
7888
8088
  } : { error: String(err) });
7889
8089
  }
7890
- await checkpointer.clear(internalConversationId);
8090
+ await checkpointer.clear(internalCheckpointKey);
7891
8091
  return {
7892
8092
  success: !error,
7893
8093
  runId: childRunId,
@@ -7900,6 +8100,16 @@ var ChildRunInvoker = class {
7900
8100
  };
7901
8101
  }
7902
8102
  };
8103
+ function readNonEmptyString6(value) {
8104
+ if (typeof value !== "string") {
8105
+ return void 0;
8106
+ }
8107
+ const trimmed = value.trim();
8108
+ return trimmed.length > 0 ? trimmed : void 0;
8109
+ }
8110
+ function resolveChildRunConversationId(params) {
8111
+ return readNonEmptyString6(params.explicitConversationId) ?? readNonEmptyString6(params.parentToolContext.conversationId) ?? params.fallbackConversationId;
8112
+ }
7903
8113
  function resolveChildRunSystemReminderPolicy(agentConfig) {
7904
8114
  const configured = agentConfig.systemReminderPolicy ?? agentConfig.contextPolicy?.systemReminder;
7905
8115
  const threshold = agentConfig.stepPolicy?.lastStepsHintThreshold;
@@ -8090,7 +8300,7 @@ function cloneRunRecord(record) {
8090
8300
  ...record,
8091
8301
  iterationBudget: record.iterationBudget ? { ...record.iterationBudget } : void 0,
8092
8302
  errorIfAny: record.errorIfAny ? { ...record.errorIfAny } : void 0,
8093
- metadata: record.metadata ? { ...record.metadata } : void 0
8303
+ metadata: record.metadata ? structuredClone(record.metadata) : void 0
8094
8304
  };
8095
8305
  }
8096
8306
  function matchesStatus(candidate, filter) {
@@ -8222,7 +8432,7 @@ function runRecordToMeta(record) {
8222
8432
  errorIfAny: record.errorIfAny ? { ...record.errorIfAny } : void 0
8223
8433
  };
8224
8434
  }
8225
- function isRecord21(value) {
8435
+ function isRecord22(value) {
8226
8436
  return typeof value === "object" && value !== null && !Array.isArray(value);
8227
8437
  }
8228
8438
  function readStringField(record, key) {
@@ -8243,7 +8453,7 @@ function getRunIdFromMetadata(event) {
8243
8453
  return snakeCaseRunId;
8244
8454
  }
8245
8455
  const runContext = metadata["run_context"];
8246
- if (isRecord21(runContext)) {
8456
+ if (isRecord22(runContext)) {
8247
8457
  return readStringField(runContext, "runId") ?? readStringField(runContext, "run_id");
8248
8458
  }
8249
8459
  return void 0;
@@ -8461,7 +8671,7 @@ function runMetaFromRecord(record) {
8461
8671
  }
8462
8672
 
8463
8673
  // src/runtime-kernel/run-supervisor/runSupervisor.ts
8464
- function isRecord22(value) {
8674
+ function isRecord23(value) {
8465
8675
  return typeof value === "object" && value !== null && !Array.isArray(value);
8466
8676
  }
8467
8677
  function readStringField2(record, key) {
@@ -8478,7 +8688,7 @@ function readRunIdFromRuntimeEvent(event) {
8478
8688
  return directRunId;
8479
8689
  }
8480
8690
  const runContext = metadata["run_context"];
8481
- if (!isRecord22(runContext)) {
8691
+ if (!isRecord23(runContext)) {
8482
8692
  return void 0;
8483
8693
  }
8484
8694
  return readStringField2(runContext, "runId") ?? readStringField2(runContext, "run_id");
@@ -8490,7 +8700,7 @@ function readAwaitingUserReason(event) {
8490
8700
  if (typeof event.prompt === "string" && event.prompt.trim().length > 0) {
8491
8701
  return event.prompt;
8492
8702
  }
8493
- if (isRecord22(event.form)) {
8703
+ if (isRecord23(event.form)) {
8494
8704
  const prompt = readStringField2(event.form, "prompt");
8495
8705
  if (prompt && prompt.trim().length > 0) {
8496
8706
  return prompt;
@@ -8502,7 +8712,7 @@ function isTerminalStatus(status) {
8502
8712
  return status === "completed" || status === "failed" || status === "cancelled";
8503
8713
  }
8504
8714
  function cloneMetadata(metadata) {
8505
- return metadata ? { ...metadata } : void 0;
8715
+ return metadata ? structuredClone(metadata) : void 0;
8506
8716
  }
8507
8717
  function recordToSnapshot(record) {
8508
8718
  return {
@@ -8589,7 +8799,7 @@ var DefaultRunSupervisor = class {
8589
8799
  startedAt,
8590
8800
  updatedAt: startedAt,
8591
8801
  iterationBudget: spec.iterationBudget ? { ...spec.iterationBudget } : void 0,
8592
- metadata: spec.metadata ? { ...spec.metadata } : void 0
8802
+ metadata: cloneMetadata(spec.metadata)
8593
8803
  };
8594
8804
  await this.registryStore.save(record);
8595
8805
  const handle = new DefaultRunHandle({
@@ -8763,12 +8973,13 @@ var DefaultRunSupervisor = class {
8763
8973
  }
8764
8974
  try {
8765
8975
  await handle.markRunning({ currentNode: "detached" });
8976
+ const registeredRecord = await this.registryStore.load(handle.runId);
8766
8977
  const executorOutcome = await this.executor.execute({
8767
8978
  runId: handle.runId,
8768
- parentRunId: spec.parentRunId,
8769
- conversationId: spec.conversationId,
8770
- agentSpec: spec.agentSpec,
8771
- request: spec.request,
8979
+ parentRunId: handle.parentRunId,
8980
+ conversationId: registeredRecord?.conversationId ?? spec.conversationId,
8981
+ agentSpec: await handle.spec(),
8982
+ request: await handle.request(),
8772
8983
  signal: handle.signal,
8773
8984
  eventBus: spec.eventBus,
8774
8985
  eventStore: spec.eventStore,
@@ -8777,7 +8988,7 @@ var DefaultRunSupervisor = class {
8777
8988
  contextFences: spec.contextFences,
8778
8989
  wakeSource: spec.wakeSource,
8779
8990
  ephemeral: spec.ephemeral,
8780
- metadata: spec.metadata
8991
+ metadata: cloneMetadata(registeredRecord?.metadata ?? spec.metadata)
8781
8992
  });
8782
8993
  const outcome = await this.persistExecutorOutcome(handle, executorOutcome);
8783
8994
  this.notifyTerminalWaiters(outcome);
@@ -8841,10 +9052,14 @@ var DefaultRunSupervisor = class {
8841
9052
  await this.registryStore.save(record);
8842
9053
  }
8843
9054
  const completedAt = executorOutcome?.completedAt ?? this.now();
9055
+ const fallbackMeta = record ? void 0 : await handle.meta();
8844
9056
  const outcome = recordToTerminalOutcome(record ?? {
8845
9057
  runId: handle.runId,
8846
9058
  parentRunId: handle.parentRunId,
8847
- status: executorOutcome?.status ?? "completed"}, completedAt);
9059
+ conversationId: fallbackMeta?.conversationId ?? "",
9060
+ agentSpecId: fallbackMeta?.agentSpecId,
9061
+ status: executorOutcome?.status ?? "completed",
9062
+ startedAt: fallbackMeta?.startedAt ?? completedAt}, completedAt);
8848
9063
  const nextOutcome = {
8849
9064
  ...outcome,
8850
9065
  metadata: {
@@ -9072,6 +9287,7 @@ function createGraphLoopHarness(options) {
9072
9287
  };
9073
9288
  return {
9074
9289
  async run() {
9290
+ const checkpointKey = options.conversationId;
9075
9291
  const executor = createDefaultGraphExecutor({
9076
9292
  llmNode: options.createLlmNode({
9077
9293
  llmCaller: options.llmCaller,
@@ -9100,8 +9316,8 @@ function createGraphLoopHarness(options) {
9100
9316
  signal: options.signal ?? options.toolContext.abortSignal,
9101
9317
  executorLocal
9102
9318
  };
9103
- await executor.prime(options.conversationId, local, "user");
9104
- const result = await executor.runUntilYield(options.conversationId);
9319
+ await executor.prime(checkpointKey, local, "user");
9320
+ const result = await executor.runUntilYield(checkpointKey);
9105
9321
  return {
9106
9322
  checkpointNodeId: result.checkpoint.nodeId,
9107
9323
  stepCount: result.stepCount
@@ -9372,7 +9588,7 @@ function createQuickstartTelemetryPort(collector) {
9372
9588
  }
9373
9589
 
9374
9590
  // src/quickstart/runAgent.ts
9375
- function isRecord23(value) {
9591
+ function isRecord24(value) {
9376
9592
  return typeof value === "object" && value !== null && !Array.isArray(value);
9377
9593
  }
9378
9594
  function readString4(value) {
@@ -9386,7 +9602,7 @@ function resolveModelId(agent, options) {
9386
9602
  return modelId;
9387
9603
  }
9388
9604
  function isQuickstartStreamChunkEvent(value) {
9389
- return isRecord23(value) && value.type === "stream_chunk" && typeof value.content === "string";
9605
+ return isRecord24(value) && value.type === "stream_chunk" && typeof value.content === "string";
9390
9606
  }
9391
9607
  function createNoopObservationPreview() {
9392
9608
  return {
@@ -9426,7 +9642,7 @@ function readFinalAnswer(events, checkpointLocal) {
9426
9642
  if (chunks.length > 0) {
9427
9643
  return chunks.join("");
9428
9644
  }
9429
- if (isRecord23(checkpointLocal)) {
9645
+ if (isRecord24(checkpointLocal)) {
9430
9646
  const finalAnswer = checkpointLocal["finalAnswer"];
9431
9647
  if (typeof finalAnswer === "string") {
9432
9648
  return finalAnswer;
@@ -9435,7 +9651,7 @@ function readFinalAnswer(events, checkpointLocal) {
9435
9651
  return "";
9436
9652
  }
9437
9653
  function readContextTrace(checkpointLocal) {
9438
- if (!isRecord23(checkpointLocal)) return void 0;
9654
+ if (!isRecord24(checkpointLocal)) return void 0;
9439
9655
  return checkpointLocal["contextTrace"];
9440
9656
  }
9441
9657
  async function emitRunEvent(event, sink) {
@@ -9444,6 +9660,7 @@ async function emitRunEvent(event, sink) {
9444
9660
  async function runAgent(agent, options) {
9445
9661
  const modelId = resolveModelId(agent, options);
9446
9662
  const conversationId = options.conversationId ?? `conv_${Date.now()}`;
9663
+ const checkpointKey = conversationId;
9447
9664
  const runId = options.runId ?? generateRunId();
9448
9665
  const turnId = runId;
9449
9666
  const costCollector = new QuickstartRunCostCollector();
@@ -9498,7 +9715,7 @@ async function runAgent(agent, options) {
9498
9715
  };
9499
9716
  await handle.markRunning({ currentNode: "user" });
9500
9717
  try {
9501
- await executor.prime(conversationId, {
9718
+ await executor.prime(checkpointKey, {
9502
9719
  conversationId,
9503
9720
  turnId,
9504
9721
  request: {
@@ -9523,7 +9740,7 @@ async function runAgent(agent, options) {
9523
9740
  return void 0;
9524
9741
  }
9525
9742
  });
9526
- const result = await executor.runUntilYield(conversationId);
9743
+ const result = await executor.runUntilYield(checkpointKey);
9527
9744
  runtimeEvents.push(...result.events);
9528
9745
  for (const event of result.events) {
9529
9746
  if (event.type === "final_answer_chunk") continue;