stitchkit 0.116.0 → 0.117.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 (120) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/dist/agent-runtime/run-acquisition.d.ts +9 -2
  3. package/dist/agent-runtime/run-acquisition.d.ts.map +1 -1
  4. package/dist/agent-runtime/run-execution.d.ts +3 -0
  5. package/dist/agent-runtime/run-execution.d.ts.map +1 -1
  6. package/dist/agent-runtime/run-failure.d.ts +4 -1
  7. package/dist/agent-runtime/run-failure.d.ts.map +1 -1
  8. package/dist/agent-runtime/run-store-retry.d.ts +8 -0
  9. package/dist/agent-runtime/run-store-retry.d.ts.map +1 -0
  10. package/dist/agent-runtime/run-terminal.d.ts.map +1 -1
  11. package/dist/agent-runtime/run-unacquired.d.ts +19 -0
  12. package/dist/agent-runtime/run-unacquired.d.ts.map +1 -0
  13. package/dist/agent-runtime/store-conformance.d.ts +8 -0
  14. package/dist/agent-runtime/store-conformance.d.ts.map +1 -1
  15. package/dist/agent-runtime/store-driver-contract.d.ts +5 -0
  16. package/dist/agent-runtime/store-driver-contract.d.ts.map +1 -1
  17. package/dist/agent-runtime/terminal-commit.d.ts +34 -4
  18. package/dist/agent-runtime/terminal-commit.d.ts.map +1 -1
  19. package/dist/entrypoints/agent-runtime/harness.js +2 -2
  20. package/dist/entrypoints/agent-runtime/sqlite/bun.js +3 -3
  21. package/dist/entrypoints/agent-runtime/sqlite/node.js +3 -3
  22. package/dist/entrypoints/agent-runtime/testing.js +22 -4
  23. package/dist/entrypoints/agent-runtime.d.ts +1 -1
  24. package/dist/entrypoints/agent-runtime.d.ts.map +1 -1
  25. package/dist/entrypoints/agent-runtime.js +13 -11
  26. package/dist/entrypoints/application/diagnostic-journal.js +1 -1
  27. package/dist/entrypoints/application/directory-inbox.js +3 -3
  28. package/dist/entrypoints/cli/publish.js +2 -2
  29. package/dist/entrypoints/files.js +2 -2
  30. package/dist/entrypoints/primitives.js +51 -154
  31. package/dist/entrypoints/server.js +6 -6
  32. package/dist/entrypoints/telegram.d.ts +1 -1
  33. package/dist/entrypoints/telegram.d.ts.map +1 -1
  34. package/dist/entrypoints/telegram.js +196 -76
  35. package/dist/entrypoints/tracking/contract.d.ts +11 -0
  36. package/dist/entrypoints/tracking/contract.d.ts.map +1 -0
  37. package/dist/entrypoints/tracking/contract.js +162 -0
  38. package/dist/entrypoints/tracking/performance.d.ts +8 -0
  39. package/dist/entrypoints/tracking/performance.d.ts.map +1 -0
  40. package/dist/entrypoints/tracking/performance.js +181 -0
  41. package/dist/entrypoints/tracking/server.d.ts +1 -0
  42. package/dist/entrypoints/tracking/server.d.ts.map +1 -1
  43. package/dist/entrypoints/tracking/server.js +40 -12
  44. package/dist/entrypoints/tracking.d.ts +4 -3
  45. package/dist/entrypoints/tracking.d.ts.map +1 -1
  46. package/dist/entrypoints/tracking.js +43 -143
  47. package/dist/entrypoints/xlsx.d.ts +4 -0
  48. package/dist/entrypoints/xlsx.d.ts.map +1 -0
  49. package/dist/entrypoints/xlsx.js +406 -0
  50. package/dist/{index-fa435yq2.js → index-073nw9qr.js} +8 -8
  51. package/dist/index-1f40z584.js +7 -0
  52. package/dist/{index-fdk4r4r6.js → index-75ns2ybj.js} +1 -1
  53. package/dist/{index-jq2ky8fw.js → index-cycp3r3e.js} +124 -181
  54. package/dist/{index-4g6qmgdx.js → index-ghtpfz4z.js} +9 -9
  55. package/dist/{index-n3v695sb.js → index-hdjmdwsj.js} +277 -96
  56. package/dist/{index-zqkz4af9.js → index-nqxrm176.js} +1 -1
  57. package/dist/index-qezhmp51.js +242 -0
  58. package/dist/index-vv1sch8a.js +94 -0
  59. package/dist/{index-fggxgbrk.js → index-xx1j310k.js} +165 -102
  60. package/dist/internal/exclusive-lock.d.ts.map +1 -1
  61. package/dist/primitives/decimal.d.ts +10 -0
  62. package/dist/primitives/decimal.d.ts.map +1 -1
  63. package/dist/primitives/index.d.ts +3 -1
  64. package/dist/primitives/index.d.ts.map +1 -1
  65. package/dist/primitives/money.d.ts +20 -0
  66. package/dist/primitives/money.d.ts.map +1 -1
  67. package/dist/primitives/quantity.d.ts.map +1 -1
  68. package/dist/primitives/rounding.d.ts +40 -0
  69. package/dist/primitives/rounding.d.ts.map +1 -0
  70. package/dist/telegram/budget-transformer.d.ts +2 -2
  71. package/dist/telegram/not-dispatched.d.ts +2 -2
  72. package/dist/telegram/not-dispatched.d.ts.map +1 -1
  73. package/dist/telegram/outbound-budget.d.ts +53 -16
  74. package/dist/telegram/outbound-budget.d.ts.map +1 -1
  75. package/dist/telegram/outbound-cost.d.ts +5 -0
  76. package/dist/telegram/outbound-cost.d.ts.map +1 -0
  77. package/dist/telegram/outbound-pauses.d.ts +17 -0
  78. package/dist/telegram/outbound-pauses.d.ts.map +1 -0
  79. package/dist/telegram/outbound-queue.d.ts +17 -0
  80. package/dist/telegram/outbound-queue.d.ts.map +1 -0
  81. package/dist/tracking/attribution.d.ts +1 -1
  82. package/dist/tracking/attribution.d.ts.map +1 -1
  83. package/dist/tracking/client-visit.d.ts +3 -1
  84. package/dist/tracking/client-visit.d.ts.map +1 -1
  85. package/dist/tracking/client.d.ts.map +1 -1
  86. package/dist/tracking/performance/collector.d.ts +61 -0
  87. package/dist/tracking/performance/collector.d.ts.map +1 -0
  88. package/dist/tracking/performance/schema.d.ts +45 -0
  89. package/dist/tracking/performance/schema.d.ts.map +1 -0
  90. package/dist/tracking/performance/summary.d.ts +12 -0
  91. package/dist/tracking/performance/summary.d.ts.map +1 -0
  92. package/dist/tracking/privacy.d.ts +5 -0
  93. package/dist/tracking/privacy.d.ts.map +1 -0
  94. package/dist/tracking/server/telemetry-health.d.ts +31 -0
  95. package/dist/tracking/server/telemetry-health.d.ts.map +1 -0
  96. package/dist/xlsx/cells.d.ts +17 -0
  97. package/dist/xlsx/cells.d.ts.map +1 -0
  98. package/dist/xlsx/render.d.ts +11 -0
  99. package/dist/xlsx/render.d.ts.map +1 -0
  100. package/dist/xlsx/schema.d.ts +119 -0
  101. package/dist/xlsx/schema.d.ts.map +1 -0
  102. package/dist/xlsx/zip.d.ts +13 -0
  103. package/dist/xlsx/zip.d.ts.map +1 -0
  104. package/llms/agent-runtime.2.txt +40 -16
  105. package/llms/agent-runtime.3.txt +17 -0
  106. package/llms/agent-runtime.txt +4 -1
  107. package/llms/primitives.txt +21 -0
  108. package/llms/stitchkit.txt +9 -6
  109. package/llms/telegram.txt +32 -12
  110. package/llms/tracking-contract.txt +32 -0
  111. package/llms/tracking-performance.txt +21 -0
  112. package/llms/tracking-server.txt +1 -0
  113. package/llms/tracking.txt +75 -12
  114. package/llms/{upgrading-0.105.0-0.116.0.txt → upgrading-0.105.0-0.117.0.txt} +50 -3
  115. package/llms/upgrading.txt +1 -1
  116. package/llms/xlsx.txt +107 -0
  117. package/llms-full.txt +355 -31
  118. package/llms.txt +11 -7
  119. package/package.json +27 -9
  120. package/dist/{index-z3d6smer.js → index-tdpmfks8.js} +5 -5
@@ -33,8 +33,9 @@ import {
33
33
  assistantStatus,
34
34
  ProviderJournalMessageSchema,
35
35
  ProviderJournalRequestSchema,
36
- ProviderJournalResponseSchema
37
- } from "./index-fggxgbrk.js";
36
+ ProviderJournalResponseSchema,
37
+ isActiveRunState
38
+ } from "./index-xx1j310k.js";
38
39
  import {
39
40
  messageOf
40
41
  } from "./index-g149e9pk.js";
@@ -52,6 +53,24 @@ import {
52
53
  transportResult
53
54
  } from "./index-9jfdm5tg.js";
54
55
 
56
+ // src/agent-runtime/run-store-retry.ts
57
+ var STORE_RETRY_DELAYS_MS = [25, 100, 400];
58
+ function storeRetryDelay(failures) {
59
+ return STORE_RETRY_DELAYS_MS[failures];
60
+ }
61
+ async function withStoreRetries(work) {
62
+ for (let failures = 0;; failures += 1) {
63
+ try {
64
+ return await work();
65
+ } catch (error) {
66
+ const delay = storeRetryDelay(failures);
67
+ if (delay === undefined)
68
+ throw error;
69
+ await new Promise((resolve) => setTimeout(resolve, delay));
70
+ }
71
+ }
72
+ }
73
+
55
74
  // src/agent-runtime/terminal-commit.ts
56
75
  class AgentRuntimeConflictError2 extends Error {
57
76
  constructor(operation) {
@@ -59,6 +78,18 @@ class AgentRuntimeConflictError2 extends Error {
59
78
  this.name = "AgentRuntimeConflictError";
60
79
  }
61
80
  }
81
+
82
+ class AgentRunUnsettledError2 extends Error {
83
+ run;
84
+ ownerId;
85
+ constructor(run, ownerId, cause) {
86
+ const reason = cause instanceof Error ? cause.message : String(cause);
87
+ super(`Agent run ${run.id} is still ${run.state} with no executor: ${reason}`, { cause });
88
+ this.name = "AgentRunUnsettledError";
89
+ this.run = run;
90
+ this.ownerId = ownerId;
91
+ }
92
+ }
62
93
  function appliedSnapshot(result, operation) {
63
94
  if (result.outcome === "applied" || result.outcome === "duplicate")
64
95
  return result.snapshot;
@@ -74,6 +105,12 @@ function viewOfSnapshot(snapshot, runId, retainedAssistant) {
74
105
  ...assistant && { assistant }
75
106
  };
76
107
  }
108
+ function terminalOfSnapshot(snapshot, runId) {
109
+ return canonicalTerminal(viewOfSnapshot(snapshot, runId));
110
+ }
111
+ function terminalOfRunView(view, conversationId) {
112
+ return canonicalTerminal(viewOfRun(view, conversationId));
113
+ }
77
114
  function viewOfRun(view, conversationId) {
78
115
  return {
79
116
  snapshotVersion: view.snapshotVersion,
@@ -122,55 +159,92 @@ function canRetryTerminal(current, previous, runtimeEpoch) {
122
159
  return (current.state === "running" || current.state === "interrupt_requested") && current.ownerId === runtimeEpoch && current.fencingToken === previous.fencingToken;
123
160
  }
124
161
  var TERMINAL_COMMIT_ATTEMPTS = 32;
162
+ async function attemptTerminalCommit(input, candidate) {
163
+ const committed = await input.store.commitRunTerminal({
164
+ conversationId: candidate.run.conversationId,
165
+ runId: candidate.run.id,
166
+ expectedRevision: candidate.run.revision,
167
+ ownerId: input.runtimeEpoch,
168
+ ...candidate.run.fencingToken !== undefined && {
169
+ fencingToken: candidate.run.fencingToken
170
+ },
171
+ assistant: candidate.assistant,
172
+ reason: candidate.reason,
173
+ ...candidate.policyName && { policyName: candidate.policyName },
174
+ ...candidate.usage && { usage: candidate.usage },
175
+ ...candidate.absorb?.length && { absorb: candidate.absorb }
176
+ });
177
+ if (committed.outcome === "applied") {
178
+ const terminal = canonicalTerminal(viewOfSnapshot(committed.snapshot, candidate.run.id));
179
+ if (!terminal)
180
+ throw new AgentRuntimeConflictError2("terminal result projection");
181
+ const absorbed = committed.snapshot.runs.filter((run) => run.absorbedIntoRunId === candidate.run.id);
182
+ return {
183
+ settled: {
184
+ ...terminal,
185
+ committedByCaller: true,
186
+ ...absorbed.length > 0 && { absorbed }
187
+ }
188
+ };
189
+ }
190
+ if (committed.outcome === "duplicate") {
191
+ const terminal = canonicalTerminal(viewOfSnapshot(committed.snapshot, candidate.run.id, committed.assistant));
192
+ if (!terminal)
193
+ throw new AgentRuntimeConflictError2("terminal result projection");
194
+ return { settled: terminal };
195
+ }
196
+ if (committed.outcome !== "conflict") {
197
+ throw new AgentRuntimeConflictError2("terminal commit");
198
+ }
199
+ const latest = await input.store.loadRun({
200
+ conversationId: candidate.run.conversationId,
201
+ runId: candidate.run.id
202
+ });
203
+ const terminal = latest ? canonicalTerminal(viewOfRun(latest, candidate.run.conversationId)) : undefined;
204
+ if (terminal)
205
+ return { settled: terminal };
206
+ const current = latest?.run;
207
+ if (!current || !canRetryTerminal(current, candidate.run, input.runtimeEpoch)) {
208
+ throw new AgentRuntimeConflictError2("terminal commit");
209
+ }
210
+ return {
211
+ candidate: current.state === "interrupt_requested" ? interruptedCandidate(candidate, current, input.now) : { ...candidate, run: current }
212
+ };
213
+ }
214
+ async function absorbedBy(store, candidate) {
215
+ const views = await Promise.all((candidate.absorb ?? []).map(({ runId }) => store.loadRun({ conversationId: candidate.run.conversationId, runId }).catch(() => {
216
+ return;
217
+ })));
218
+ return views.flatMap((view) => view?.run.absorbedIntoRunId === candidate.run.id ? [view.run] : []);
219
+ }
125
220
  async function commitAgentRunTerminal(input) {
126
221
  let candidate = input.candidate;
222
+ let storeFailures = 0;
127
223
  for (let attempt = 0;attempt < TERMINAL_COMMIT_ATTEMPTS; attempt += 1) {
128
- const committed = await input.store.commitRunTerminal({
129
- conversationId: candidate.run.conversationId,
130
- runId: candidate.run.id,
131
- expectedRevision: candidate.run.revision,
132
- ownerId: input.runtimeEpoch,
133
- ...candidate.run.fencingToken !== undefined && {
134
- fencingToken: candidate.run.fencingToken
135
- },
136
- assistant: candidate.assistant,
137
- reason: candidate.reason,
138
- ...candidate.policyName && { policyName: candidate.policyName },
139
- ...candidate.usage && { usage: candidate.usage },
140
- ...candidate.absorb?.length && { absorb: candidate.absorb }
141
- });
142
- if (committed.outcome === "applied") {
143
- const terminal = canonicalTerminal(viewOfSnapshot(committed.snapshot, candidate.run.id));
144
- if (!terminal)
145
- throw new AgentRuntimeConflictError2("terminal result projection");
146
- const absorbed = committed.snapshot.runs.filter((run) => run.absorbedIntoRunId === candidate.run.id);
224
+ try {
225
+ const round = await attemptTerminalCommit(input, candidate);
226
+ if (!round.settled) {
227
+ candidate = round.candidate;
228
+ continue;
229
+ }
230
+ const owned = storeFailures > 0 && round.settled.run.ownerId === input.runtimeEpoch && round.settled.run.fencingToken === candidate.run.fencingToken;
231
+ if (!owned)
232
+ return round.settled;
233
+ const absorbed = await absorbedBy(input.store, candidate);
147
234
  return {
148
- ...terminal,
235
+ ...round.settled,
149
236
  committedByCaller: true,
150
237
  ...absorbed.length > 0 && { absorbed }
151
238
  };
239
+ } catch (error) {
240
+ if (error instanceof AgentRuntimeConflictError2)
241
+ throw error;
242
+ const delay = storeRetryDelay(storeFailures);
243
+ if (delay === undefined)
244
+ throw error;
245
+ storeFailures += 1;
246
+ await new Promise((resolve) => setTimeout(resolve, delay));
152
247
  }
153
- if (committed.outcome === "duplicate") {
154
- const terminal = canonicalTerminal(viewOfSnapshot(committed.snapshot, candidate.run.id, committed.assistant));
155
- if (!terminal)
156
- throw new AgentRuntimeConflictError2("terminal result projection");
157
- return terminal;
158
- }
159
- if (committed.outcome !== "conflict") {
160
- throw new AgentRuntimeConflictError2("terminal commit");
161
- }
162
- const latest = await input.store.loadRun({
163
- conversationId: candidate.run.conversationId,
164
- runId: candidate.run.id
165
- });
166
- const terminal = latest ? canonicalTerminal(viewOfRun(latest, candidate.run.conversationId)) : undefined;
167
- if (terminal)
168
- return terminal;
169
- const current = latest?.run;
170
- if (!current || !canRetryTerminal(current, candidate.run, input.runtimeEpoch)) {
171
- throw new AgentRuntimeConflictError2("terminal commit");
172
- }
173
- candidate = current.state === "interrupt_requested" ? interruptedCandidate(candidate, current, input.now) : { ...candidate, run: current };
174
248
  }
175
249
  throw new AgentRuntimeConflictError2("terminal commit");
176
250
  }
@@ -2545,19 +2619,20 @@ function createAgentRunOperationLifecycle(config) {
2545
2619
 
2546
2620
  // src/agent-runtime/run-acquisition.ts
2547
2621
  async function acquireRun(dependencies, input) {
2548
- const { config, publish, runtimeEpoch, generateId, now, idleTimeoutMs, injection } = dependencies;
2622
+ const { config, runtimeEpoch, now, idleTimeoutMs, injection } = dependencies;
2549
2623
  injection?.withdraw(input.key, input.acceptedRun.id);
2550
- const queued = await config.store.loadRun({
2624
+ const queued = await withStoreRetries(() => config.store.loadRun({
2551
2625
  conversationId: input.acceptedRun.conversationId,
2552
2626
  runId: input.acceptedRun.id
2553
- });
2627
+ }));
2554
2628
  if (!queued)
2555
2629
  throw new AgentRuntimeConflictError2("run lookup");
2556
2630
  if (queued.run.terminalReason === "absorbed") {
2557
- const absorbing = queued.run.absorbedIntoRunId ? await config.store.loadRun({
2631
+ const { absorbedIntoRunId } = queued.run;
2632
+ const absorbing = absorbedIntoRunId ? await withStoreRetries(() => config.store.loadRun({
2558
2633
  conversationId: queued.run.conversationId,
2559
- runId: queued.run.absorbedIntoRunId
2560
- }) : undefined;
2634
+ runId: absorbedIntoRunId
2635
+ })) : undefined;
2561
2636
  if (!absorbing?.assistant || !absorbing.run.terminalReason) {
2562
2637
  throw new AgentRuntimeConflictError2("absorbed run resolution");
2563
2638
  }
@@ -2576,38 +2651,16 @@ async function acquireRun(dependencies, input) {
2576
2651
  };
2577
2652
  }
2578
2653
  const queuedRun = queued.run;
2579
- const acquired = appliedSnapshot(await config.store.acquireRun({
2654
+ const acquired = appliedSnapshot(await withStoreRetries(() => config.store.acquireRun({
2580
2655
  conversationId: queuedRun.conversationId,
2581
2656
  runId: queuedRun.id,
2582
2657
  expectedRevision: queuedRun.revision,
2583
2658
  ownerId: runtimeEpoch
2584
- }), "run acquisition");
2585
- let run = findRun(acquired.runs, input.acceptedRun.id);
2659
+ })), "run acquisition");
2660
+ const run = findRun(acquired.runs, input.acceptedRun.id);
2586
2661
  input.onAcquired?.();
2587
- await publish({
2588
- type: "run-state",
2589
- eventId: agentDurableEventId2("run-state", run.id, acquired.version),
2590
- conversationId: run.conversationId,
2591
- runId: run.id,
2592
- snapshotVersion: acquired.version,
2593
- state: run.state,
2594
- emittedAt: now().toISOString()
2595
- });
2596
2662
  const trace = config.observe?.rootTrace();
2597
2663
  const runStartedAt = performance.now();
2598
- config.observe?.emit({
2599
- schemaVersion: 1,
2600
- eventId: generateId(),
2601
- type: "run-started",
2602
- conversationId: run.conversationId,
2603
- runId: run.id,
2604
- traceId: trace?.traceId ?? generateId(),
2605
- spanId: trace?.spanId ?? generateId(),
2606
- ...trace?.parentSpanId && { parentSpanId: trace.parentSpanId },
2607
- state: run.state,
2608
- queueWaitMs: Math.max(0, now().getTime() - new Date(run.createdAt).getTime()),
2609
- emittedAt: now().toISOString()
2610
- });
2611
2664
  const assistant = AgentMessageSchema2.parse({
2612
2665
  schemaVersion: 1,
2613
2666
  id: run.assistantMessageId,
@@ -2619,19 +2672,10 @@ async function acquireRun(dependencies, input) {
2619
2672
  createdAt: now().toISOString(),
2620
2673
  updatedAt: now().toISOString()
2621
2674
  });
2622
- const snapshot = appliedSnapshot(await config.store.checkpointRunAssistant({
2623
- conversationId: run.conversationId,
2624
- runId: run.id,
2625
- expectedRevision: run.revision,
2626
- ownerId: runtimeEpoch,
2627
- ...run.fencingToken !== undefined && { fencingToken: run.fencingToken },
2628
- assistant
2629
- }), "assistant draft");
2630
- run = findRun(snapshot.runs, run.id);
2631
2675
  const state = {
2632
2676
  run,
2633
- snapshot,
2634
- observedVersion: snapshot.version,
2677
+ snapshot: acquired,
2678
+ observedVersion: acquired.version,
2635
2679
  assistant,
2636
2680
  parts: [],
2637
2681
  absorbed: new Map,
@@ -2660,7 +2704,7 @@ async function acquireRun(dependencies, input) {
2660
2704
  serialize,
2661
2705
  currentRun: () => state.run,
2662
2706
  acceptSnapshot: (next) => adoptSnapshot(state, next),
2663
- publish,
2707
+ publish: dependencies.publish,
2664
2708
  now
2665
2709
  });
2666
2710
  return {
@@ -2678,6 +2722,41 @@ async function acquireRun(dependencies, input) {
2678
2722
  }
2679
2723
  };
2680
2724
  }
2725
+ async function beginRunExecution(execution) {
2726
+ const { config, publish, runtimeEpoch, generateId, now } = execution.dependencies;
2727
+ const { state, trace } = execution;
2728
+ const { run, assistant } = state;
2729
+ await publish({
2730
+ type: "run-state",
2731
+ eventId: agentDurableEventId2("run-state", run.id, state.observedVersion),
2732
+ conversationId: run.conversationId,
2733
+ runId: run.id,
2734
+ snapshotVersion: state.observedVersion,
2735
+ state: run.state,
2736
+ emittedAt: now().toISOString()
2737
+ });
2738
+ config.observe?.emit({
2739
+ schemaVersion: 1,
2740
+ eventId: generateId(),
2741
+ type: "run-started",
2742
+ conversationId: run.conversationId,
2743
+ runId: run.id,
2744
+ traceId: trace?.traceId ?? generateId(),
2745
+ spanId: trace?.spanId ?? generateId(),
2746
+ ...trace?.parentSpanId && { parentSpanId: trace.parentSpanId },
2747
+ state: run.state,
2748
+ queueWaitMs: Math.max(0, now().getTime() - new Date(run.createdAt).getTime()),
2749
+ emittedAt: now().toISOString()
2750
+ });
2751
+ adoptSnapshot(state, appliedSnapshot(await config.store.checkpointRunAssistant({
2752
+ conversationId: run.conversationId,
2753
+ runId: run.id,
2754
+ expectedRevision: run.revision,
2755
+ ownerId: runtimeEpoch,
2756
+ ...run.fencingToken !== undefined && { fencingToken: run.fencingToken },
2757
+ assistant
2758
+ }), "assistant draft"));
2759
+ }
2681
2760
 
2682
2761
  // src/agent-runtime/run-failure.ts
2683
2762
  function failureThisRuntimeOwns(error) {
@@ -2691,16 +2770,24 @@ function failureThisRuntimeOwns(error) {
2691
2770
  return "runtime_failure";
2692
2771
  return;
2693
2772
  }
2773
+ function withLaterFailure(primary, later, what) {
2774
+ return new AggregateError([primary, later], `${primary instanceof Error ? primary.message : String(primary)} (${what} also failed: ${later instanceof Error ? later.message : String(later)})`);
2775
+ }
2694
2776
  async function classifyRunFailure(execution, error) {
2695
2777
  const { config, runtimeEpoch } = execution.dependencies;
2696
2778
  const { state, operationLifecycle, executionSignal } = execution;
2697
2779
  operationLifecycle.failStepCheckpoints(error);
2698
2780
  const cleanupFailure = state.providerStreamCleanupFailure;
2699
- state.internalCause = cleanupFailure === undefined ? error : new AggregateError([error, cleanupFailure], `${error instanceof Error ? error.message : String(error)} (provider stream cleanup also failed: ${cleanupFailure instanceof Error ? cleanupFailure.message : String(cleanupFailure)})`);
2700
- const latest = await config.store.loadRun({
2701
- conversationId: state.run.conversationId,
2702
- runId: state.run.id
2703
- });
2781
+ state.internalCause = cleanupFailure === undefined ? error : withLaterFailure(error, cleanupFailure, "provider stream cleanup");
2782
+ let latest;
2783
+ try {
2784
+ latest = await config.store.loadRun({
2785
+ conversationId: state.run.conversationId,
2786
+ runId: state.run.id
2787
+ });
2788
+ } catch (readFailure) {
2789
+ state.internalCause = withLaterFailure(state.internalCause, readFailure, "the run read");
2790
+ }
2704
2791
  const latestRun = latest?.run;
2705
2792
  const durableInterrupt = latestRun?.ownerId === runtimeEpoch && latestRun.state === "interrupt_requested";
2706
2793
  if (durableInterrupt && latest && latestRun) {
@@ -2709,7 +2796,11 @@ async function classifyRunFailure(execution, error) {
2709
2796
  }
2710
2797
  const staleOwner = isToolExecutionControlError2(error) && error.reason === "stale_run";
2711
2798
  if (!staleOwner) {
2712
- await operationLifecycle.finish(executionSignal.aborted || durableInterrupt ? "cancelled" : "failed");
2799
+ try {
2800
+ await operationLifecycle.finish(executionSignal.aborted || durableInterrupt ? "cancelled" : "failed");
2801
+ } catch (finishFailure) {
2802
+ state.internalCause = withLaterFailure(state.internalCause, finishFailure, "closing the operations");
2803
+ }
2713
2804
  }
2714
2805
  if (isToolExecutionControlError2(error) || executionSignal.aborted || durableInterrupt) {
2715
2806
  state.terminalReason = executionSignal.aborted ? abortTerminalReason(executionSignal) : "interrupted";
@@ -3587,7 +3678,9 @@ async function commitRunTerminal(execution) {
3587
3678
  reason: state.terminalReason,
3588
3679
  usage: spent
3589
3680
  });
3590
- throw error;
3681
+ if (error instanceof AgentRuntimeConflictError2)
3682
+ throw error;
3683
+ throw new AgentRunUnsettledError2(state.run, runtimeEpoch, error);
3591
3684
  }
3592
3685
  state.observedVersion = terminal.snapshotVersion;
3593
3686
  state.run = terminal.run;
@@ -3879,14 +3972,102 @@ async function prepareTurn(execution) {
3879
3972
  return { selectedModel, runtimeContext, prompt, tools, history, projection };
3880
3973
  }
3881
3974
 
3975
+ // src/agent-runtime/run-unacquired.ts
3976
+ async function closeUnacquiredRun(dependencies, input, failure, executing) {
3977
+ const { config, publish, runtimeEpoch, generateId, now } = dependencies;
3978
+ const { conversationId, id: runId } = input.acceptedRun;
3979
+ const view = await withStoreRetries(() => config.store.loadRun({ conversationId, runId })).catch(() => {
3980
+ throw new AgentRunUnsettledError2(input.acceptedRun, runtimeEpoch, failure);
3981
+ });
3982
+ if (!view || !isActiveRunState(view.run.state))
3983
+ throw failure;
3984
+ const { run } = view;
3985
+ if (run.ownerId !== undefined && run.ownerId !== runtimeEpoch)
3986
+ throw failure;
3987
+ if (executing.has(runId))
3988
+ throw failure;
3989
+ const unsettled = new AgentRunUnsettledError2(run, runtimeEpoch, failure);
3990
+ if (failure instanceof AgentRuntimeConflictError2 && run.ownerId === undefined)
3991
+ throw unsettled;
3992
+ const abandoned = await withStoreRetries(() => config.store.recoverRun({
3993
+ conversationId,
3994
+ runId,
3995
+ expectedRevision: run.revision,
3996
+ action: "abandon"
3997
+ })).catch(() => {
3998
+ return;
3999
+ });
4000
+ const terminal = abandoned?.outcome === "applied" ? terminalOfSnapshot(abandoned.snapshot, runId) : await withStoreRetries(() => config.store.loadRun({ conversationId, runId })).then((latest) => latest ? terminalOfRunView(latest, conversationId) : undefined, () => {
4001
+ return;
4002
+ });
4003
+ if (terminal?.reason !== "abandoned")
4004
+ throw unsettled;
4005
+ input.onAcquired?.();
4006
+ const version = terminal.snapshotVersion;
4007
+ const usage = statedUsage(terminal.run.usage);
4008
+ const emittedAt = now().toISOString();
4009
+ await publish({
4010
+ type: "run-state",
4011
+ eventId: agentDurableEventId2("run-state", runId, version),
4012
+ conversationId,
4013
+ runId,
4014
+ snapshotVersion: version,
4015
+ state: terminal.run.state,
4016
+ emittedAt
4017
+ });
4018
+ config.observe?.emit({
4019
+ schemaVersion: 1,
4020
+ eventId: agentDurableEventId2("terminal", runId, version),
4021
+ type: "run-terminal",
4022
+ conversationId,
4023
+ runId,
4024
+ traceId: generateId(),
4025
+ spanId: generateId(),
4026
+ state: terminal.run.state,
4027
+ terminalReason: terminal.reason,
4028
+ durationMs: 0,
4029
+ usage,
4030
+ internalCause: failure,
4031
+ emittedAt
4032
+ });
4033
+ const metrics = { partial: true, durationMs: 0, usage };
4034
+ await publish({
4035
+ type: "terminal",
4036
+ eventId: agentDurableEventId2("terminal", runId, version),
4037
+ conversationId,
4038
+ runId,
4039
+ snapshotVersion: version,
4040
+ reason: terminal.reason,
4041
+ message: terminal.assistant,
4042
+ metrics,
4043
+ emittedAt
4044
+ });
4045
+ return {
4046
+ run: terminal.run,
4047
+ message: terminal.assistant,
4048
+ reason: terminal.reason,
4049
+ snapshotVersion: version,
4050
+ metrics
4051
+ };
4052
+ }
4053
+
3882
4054
  // src/agent-runtime/run-execution.ts
3883
4055
  function createRunExecutor(dependencies) {
4056
+ const executing = new Set;
3884
4057
  return async function executeRun(input) {
3885
- const acquisition = await acquireRun(dependencies, input);
4058
+ let acquisition;
4059
+ try {
4060
+ acquisition = await acquireRun(dependencies, input);
4061
+ } catch (error) {
4062
+ return closeUnacquiredRun(dependencies, input, error, executing);
4063
+ }
3886
4064
  if (acquisition.kind === "absorbed")
3887
4065
  return acquisition.result;
3888
4066
  const { execution } = acquisition;
4067
+ const runId = execution.state.run.id;
4068
+ executing.add(runId);
3889
4069
  try {
4070
+ await beginRunExecution(execution);
3890
4071
  const invocations = dependencies.config.invocations;
3891
4072
  if (invocations) {
3892
4073
  const trace = await invocations.trace({
@@ -3904,7 +4085,7 @@ function createRunExecutor(dependencies) {
3904
4085
  } finally {
3905
4086
  execution.idleDeadline.dispose();
3906
4087
  }
3907
- const result = await commitRunTerminal(execution);
4088
+ const result = await commitRunTerminal(execution).finally(() => executing.delete(runId));
3908
4089
  await execution.invocation?.finish(result.reason === "success" ? "succeeded" : ["interrupted", "cancelled", "timeout", "shutdown"].includes(result.reason) ? "cancelled" : "failed");
3909
4090
  return result;
3910
4091
  };
@@ -4283,4 +4464,4 @@ function createAgentRuntime2(config) {
4283
4464
  };
4284
4465
  }
4285
4466
 
4286
- export { AgentRuntimeConflictError2, normalizeSdkUsage, AgentContextOverflowError2, createAgentSessionCoordinator2, registerDeferredToolRepair, registerDeferredToolCatalog, deferredToolCatalog, repairedSearchCall, projectAgentHistoryDetailed2, projectAgentHistory2, ModelInvocationTraceSchema2, CompletionInvocationInputSchema2, ModelInvocationRecordSchema2, currentModelInvocationAttempt2, createModelInvocationLedger2, createAgentToolFenceLifecycle2, AgentTokenCountSchema2, selectAgentHistory2, composeAgentPrompt2, AgentProviderStreamCutError2, classifyProviderFailure2, isToolResultFailure2, recordAgentRetryDecision2, defineStateSlot2, createAgentStateSlotStore2, renderAgentStateSlots2, agentGoalStateSlot2, agentTodoStateSlot2, createAgentRuntime2 };
4467
+ export { AgentRuntimeConflictError2, AgentRunUnsettledError2, normalizeSdkUsage, AgentContextOverflowError2, createAgentSessionCoordinator2, registerDeferredToolRepair, registerDeferredToolCatalog, deferredToolCatalog, repairedSearchCall, projectAgentHistoryDetailed2, projectAgentHistory2, ModelInvocationTraceSchema2, CompletionInvocationInputSchema2, ModelInvocationRecordSchema2, currentModelInvocationAttempt2, createModelInvocationLedger2, createAgentToolFenceLifecycle2, AgentTokenCountSchema2, selectAgentHistory2, composeAgentPrompt2, AgentProviderStreamCutError2, classifyProviderFailure2, isToolResultFailure2, recordAgentRetryDecision2, defineStateSlot2, createAgentStateSlotStore2, renderAgentStateSlots2, agentGoalStateSlot2, agentTodoStateSlot2, createAgentRuntime2 };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  attemptExclusiveLock
3
- } from "./index-z3d6smer.js";
3
+ } from "./index-tdpmfks8.js";
4
4
  import {
5
5
  sleep
6
6
  } from "./index-eemvahkc.js";