@qvac/harness 0.7.1 → 1.0.0-rc.1

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 (201) hide show
  1. package/README.md +224 -0
  2. package/dist-lib/index.d.ts +55 -3
  3. package/dist-lib/index.js +721 -236
  4. package/dist-lib/lib/capabilities/completion-engine/abort-polyfill.d.ts +1 -0
  5. package/dist-lib/lib/capabilities/completion-engine/abort-polyfill.js +10 -0
  6. package/dist-lib/lib/capabilities/completion-engine/actors/answering.d.ts +3 -0
  7. package/dist-lib/lib/capabilities/completion-engine/actors/answering.js +17 -0
  8. package/dist-lib/lib/capabilities/completion-engine/actors/approval.d.ts +4 -0
  9. package/dist-lib/lib/capabilities/completion-engine/actors/approval.js +29 -0
  10. package/dist-lib/lib/capabilities/completion-engine/actors/direct-search.d.ts +4 -0
  11. package/dist-lib/lib/capabilities/completion-engine/actors/direct-search.js +73 -0
  12. package/dist-lib/lib/capabilities/completion-engine/actors/execute.d.ts +41 -0
  13. package/dist-lib/lib/capabilities/completion-engine/actors/execute.js +49 -0
  14. package/dist-lib/lib/capabilities/completion-engine/actors/executing.d.ts +3 -0
  15. package/dist-lib/lib/capabilities/completion-engine/actors/executing.js +102 -0
  16. package/dist-lib/lib/capabilities/completion-engine/actors/execution-plan.d.ts +47 -0
  17. package/dist-lib/lib/capabilities/completion-engine/actors/execution-plan.js +87 -0
  18. package/dist-lib/lib/capabilities/completion-engine/actors/finishing.d.ts +2 -0
  19. package/dist-lib/lib/capabilities/completion-engine/actors/finishing.js +32 -0
  20. package/dist-lib/lib/capabilities/completion-engine/actors/inspect-preload.d.ts +3 -0
  21. package/dist-lib/lib/capabilities/completion-engine/actors/inspect-preload.js +75 -0
  22. package/dist-lib/lib/capabilities/completion-engine/actors/inspecting.d.ts +3 -0
  23. package/dist-lib/lib/capabilities/completion-engine/actors/inspecting.js +152 -0
  24. package/dist-lib/lib/capabilities/completion-engine/actors/loading-skill.d.ts +3 -0
  25. package/dist-lib/lib/capabilities/completion-engine/actors/loading-skill.js +94 -0
  26. package/dist-lib/lib/capabilities/completion-engine/actors/preload-failure.d.ts +9 -0
  27. package/dist-lib/lib/capabilities/completion-engine/actors/preload-failure.js +11 -0
  28. package/dist-lib/lib/capabilities/completion-engine/actors/preloading.d.ts +3 -0
  29. package/dist-lib/lib/capabilities/completion-engine/actors/preloading.js +114 -0
  30. package/dist-lib/lib/capabilities/completion-engine/actors/preparing.d.ts +3 -0
  31. package/dist-lib/lib/capabilities/completion-engine/actors/preparing.js +198 -0
  32. package/dist-lib/lib/capabilities/completion-engine/actors/rejecting.d.ts +3 -0
  33. package/dist-lib/lib/capabilities/completion-engine/actors/rejecting.js +71 -0
  34. package/dist-lib/lib/capabilities/completion-engine/actors/rejection.d.ts +18 -0
  35. package/dist-lib/lib/capabilities/completion-engine/actors/rejection.js +70 -0
  36. package/dist-lib/lib/capabilities/completion-engine/actors/resolving.d.ts +3 -0
  37. package/dist-lib/lib/capabilities/completion-engine/actors/resolving.js +60 -0
  38. package/dist-lib/lib/capabilities/completion-engine/actors/stream.d.ts +21 -0
  39. package/dist-lib/lib/capabilities/completion-engine/actors/stream.js +48 -0
  40. package/dist-lib/lib/capabilities/completion-engine/actors/streaming.d.ts +3 -0
  41. package/dist-lib/lib/capabilities/completion-engine/actors/streaming.js +156 -0
  42. package/dist-lib/lib/capabilities/completion-engine/actors/wrap-up.d.ts +7 -0
  43. package/dist-lib/lib/capabilities/completion-engine/actors/wrap-up.js +61 -0
  44. package/dist-lib/lib/capabilities/completion-engine/driver.d.ts +25 -0
  45. package/dist-lib/lib/capabilities/completion-engine/driver.js +553 -0
  46. package/dist-lib/lib/capabilities/completion-engine/durable.d.ts +61 -0
  47. package/dist-lib/lib/capabilities/completion-engine/durable.js +150 -0
  48. package/dist-lib/lib/capabilities/completion-engine/operations.d.ts +6 -0
  49. package/dist-lib/lib/capabilities/completion-engine/operations.js +239 -0
  50. package/dist-lib/lib/capabilities/completion-engine/ports.d.ts +3 -0
  51. package/dist-lib/lib/capabilities/completion-engine/ports.js +267 -0
  52. package/dist-lib/lib/capabilities/completion-engine/session.d.ts +76 -0
  53. package/dist-lib/lib/capabilities/completion-engine/session.js +70 -0
  54. package/dist-lib/lib/capabilities/completion-loop/index.d.ts +80 -0
  55. package/dist-lib/lib/capabilities/completion-loop/index.js +158 -0
  56. package/dist-lib/lib/capabilities/completion-loop/metrics.d.ts +5 -0
  57. package/dist-lib/lib/capabilities/completion-loop/metrics.js +29 -0
  58. package/dist-lib/lib/capabilities/completion-loop/round.d.ts +33 -0
  59. package/dist-lib/lib/capabilities/completion-loop/round.js +353 -0
  60. package/dist-lib/lib/capabilities/completion-loop/tool-execution.d.ts +60 -0
  61. package/dist-lib/lib/capabilities/completion-loop/tool-execution.js +270 -0
  62. package/dist-lib/lib/capabilities/completion-loop/turns.d.ts +23 -0
  63. package/dist-lib/lib/capabilities/completion-loop/turns.js +112 -0
  64. package/dist-lib/lib/capabilities/completion-runtime.d.ts +46 -0
  65. package/dist-lib/lib/capabilities/completion-runtime.js +74 -0
  66. package/dist-lib/lib/capabilities/completion.d.ts +18 -335
  67. package/dist-lib/lib/capabilities/completion.js +20 -1301
  68. package/dist-lib/lib/capabilities/download.d.ts +1 -1
  69. package/dist-lib/lib/capabilities/download.js +7 -2
  70. package/dist-lib/lib/capabilities/invoke.js +5 -3
  71. package/dist-lib/lib/capabilities/tool-plan.d.ts +35 -0
  72. package/dist-lib/lib/capabilities/tool-plan.js +66 -0
  73. package/dist-lib/lib/capabilities/tool-turns.d.ts +11 -2
  74. package/dist-lib/lib/capabilities/tool-turns.js +30 -2
  75. package/dist-lib/lib/capabilities/types.d.ts +287 -0
  76. package/dist-lib/lib/capabilities/types.js +1 -0
  77. package/dist-lib/lib/completion-lifecycle.d.ts +14 -0
  78. package/dist-lib/lib/completion-lifecycle.js +126 -0
  79. package/dist-lib/lib/connect.d.ts +10 -3
  80. package/dist-lib/lib/connect.js +329 -23
  81. package/dist-lib/lib/contract-types.d.ts +19 -2
  82. package/dist-lib/lib/harness-lifecycle.d.ts +66 -0
  83. package/dist-lib/lib/harness-lifecycle.js +129 -0
  84. package/dist-lib/lib/helpers/detach-json.d.ts +1 -0
  85. package/dist-lib/lib/helpers/detach-json.js +146 -0
  86. package/dist-lib/lib/helpers/markup-scanner.d.ts +26 -0
  87. package/dist-lib/lib/helpers/markup-scanner.js +156 -0
  88. package/dist-lib/lib/helpers/markup-stream-filter.js +138 -35
  89. package/dist-lib/lib/helpers/race-abort.d.ts +9 -4
  90. package/dist-lib/lib/helpers/race-abort.js +2 -7
  91. package/dist-lib/lib/helpers/recovery-required.d.ts +1 -0
  92. package/dist-lib/lib/helpers/recovery-required.js +1 -0
  93. package/dist-lib/lib/helpers/run-outcome.d.ts +10 -2
  94. package/dist-lib/lib/helpers/run-outcome.js +8 -5
  95. package/dist-lib/lib/helpers/tool-call-markup.d.ts +2 -0
  96. package/dist-lib/lib/helpers/tool-call-markup.js +197 -82
  97. package/dist-lib/lib/hooks/built-in/arg-repair.d.ts +1 -0
  98. package/dist-lib/lib/hooks/built-in/arg-repair.js +1 -0
  99. package/dist-lib/lib/hooks/built-in/egress.d.ts +1 -0
  100. package/dist-lib/lib/hooks/built-in/egress.js +2 -1
  101. package/dist-lib/lib/hooks/built-in/sandbox.d.ts +1 -0
  102. package/dist-lib/lib/hooks/built-in/sandbox.js +6 -1
  103. package/dist-lib/lib/hooks/built-in/skill-catalog.d.ts +1 -0
  104. package/dist-lib/lib/hooks/built-in/skill-catalog.js +2 -1
  105. package/dist-lib/lib/hooks/pipeline.d.ts +4 -1
  106. package/dist-lib/lib/hooks/pipeline.js +24 -2
  107. package/dist-lib/lib/hooks/run.d.ts +2 -1
  108. package/dist-lib/lib/hooks/run.js +19 -7
  109. package/dist-lib/lib/hooks/types.d.ts +17 -6
  110. package/dist-lib/lib/machine/completion/actions/approval.d.ts +3 -0
  111. package/dist-lib/lib/machine/completion/actions/approval.js +16 -0
  112. package/dist-lib/lib/machine/completion/actions/completion.d.ts +23 -0
  113. package/dist-lib/lib/machine/completion/actions/completion.js +142 -0
  114. package/dist-lib/lib/machine/completion/actions/skills.d.ts +9 -0
  115. package/dist-lib/lib/machine/completion/actions/skills.js +83 -0
  116. package/dist-lib/lib/machine/completion/actions/tools.d.ts +16 -0
  117. package/dist-lib/lib/machine/completion/actions/tools.js +173 -0
  118. package/dist-lib/lib/machine/completion/context.d.ts +9 -0
  119. package/dist-lib/lib/machine/completion/context.js +44 -0
  120. package/dist-lib/lib/machine/completion/contract.d.ts +6 -0
  121. package/dist-lib/lib/machine/completion/contract.js +1 -0
  122. package/dist-lib/lib/machine/completion/guards/retry.d.ts +9 -0
  123. package/dist-lib/lib/machine/completion/guards/retry.js +25 -0
  124. package/dist-lib/lib/machine/completion/implementations.d.ts +81 -0
  125. package/dist-lib/lib/machine/completion/implementations.js +152 -0
  126. package/dist-lib/lib/machine/completion/machine.d.ts +375 -0
  127. package/dist-lib/lib/machine/completion/machine.js +511 -0
  128. package/dist-lib/lib/machine/completion/ports.d.ts +65 -0
  129. package/dist-lib/lib/machine/completion/ports.js +224 -0
  130. package/dist-lib/lib/machine/completion/rules.d.ts +39 -0
  131. package/dist-lib/lib/machine/completion/rules.js +115 -0
  132. package/dist-lib/lib/machine/completion/types.d.ts +493 -0
  133. package/dist-lib/lib/machine/completion/types.js +1 -0
  134. package/dist-lib/lib/machine/engine.d.ts +93 -0
  135. package/dist-lib/lib/machine/engine.js +483 -0
  136. package/dist-lib/lib/machine/errors.d.ts +44 -0
  137. package/dist-lib/lib/machine/errors.js +373 -0
  138. package/dist-lib/lib/machine/guards.d.ts +2 -0
  139. package/dist-lib/lib/machine/guards.js +6 -0
  140. package/dist-lib/lib/machine/index.d.ts +20 -0
  141. package/dist-lib/lib/machine/index.js +11 -0
  142. package/dist-lib/lib/machine/replay-output.d.ts +24 -0
  143. package/dist-lib/lib/machine/replay-output.js +50 -0
  144. package/dist-lib/lib/machine/stable-stringify.d.ts +1 -0
  145. package/dist-lib/lib/machine/stable-stringify.js +11 -0
  146. package/dist-lib/lib/models/model-pool.d.ts +14 -6
  147. package/dist-lib/lib/models/model-pool.js +95 -30
  148. package/dist-lib/lib/run-log/history-codec.d.ts +23 -0
  149. package/dist-lib/lib/run-log/history-codec.js +973 -0
  150. package/dist-lib/lib/run-log/patch.d.ts +6 -0
  151. package/dist-lib/lib/run-log/patch.js +93 -0
  152. package/dist-lib/lib/run-log/persisted-actor.d.ts +18 -0
  153. package/dist-lib/lib/run-log/persisted-actor.js +218 -0
  154. package/dist-lib/lib/run-log/protocol-types.d.ts +153 -0
  155. package/dist-lib/lib/run-log/protocol-types.js +1 -0
  156. package/dist-lib/lib/run-log/protocol.d.ts +27 -0
  157. package/dist-lib/lib/run-log/protocol.js +1056 -0
  158. package/dist-lib/lib/run-log/replay.d.ts +25 -0
  159. package/dist-lib/lib/run-log/replay.js +129 -0
  160. package/dist-lib/lib/run-log/run-journal.d.ts +125 -0
  161. package/dist-lib/lib/run-log/run-journal.js +783 -0
  162. package/dist-lib/lib/run-log-inspect.d.ts +25 -0
  163. package/dist-lib/lib/run-log-inspect.js +627 -0
  164. package/dist-lib/lib/run-log-protocol.d.ts +2 -0
  165. package/dist-lib/lib/run-log-protocol.js +1 -0
  166. package/dist-lib/lib/run-log-redact.d.ts +27 -0
  167. package/dist-lib/lib/run-log-redact.js +1107 -0
  168. package/dist-lib/lib/serve.js +307 -11
  169. package/dist-lib/lib/spawn.js +3 -2
  170. package/dist-lib/lib/tool-call-display.d.ts +1 -21
  171. package/dist-lib/lib/tools/exec/adapters/python/wheels.js +2 -1
  172. package/dist-lib/lib/tools/exec.d.ts +2 -1
  173. package/dist-lib/lib/tools/exec.js +57 -2
  174. package/dist-lib/lib/tools/generate-image.js +1 -1
  175. package/dist-lib/lib/tools/generate-music.js +1 -1
  176. package/dist-lib/lib/tools/http-request.d.ts +2 -1
  177. package/dist-lib/lib/tools/http-request.js +2 -1
  178. package/dist-lib/lib/tools/mcp-call.js +8 -1
  179. package/dist-lib/lib/tools/operations/builders.d.ts +1 -0
  180. package/dist-lib/lib/tools/operations/builders.js +1 -0
  181. package/dist-lib/lib/tools/operations/compile.js +11 -1
  182. package/dist-lib/lib/tools/operations/manifest.js +1 -0
  183. package/dist-lib/lib/tools/outbound-guard.d.ts +8 -6
  184. package/dist-lib/lib/tools/outbound-guard.js +25 -8
  185. package/dist-lib/lib/tools/skills/catalog.d.ts +1 -0
  186. package/dist-lib/lib/tools/skills/catalog.js +35 -0
  187. package/dist-lib/lib/tools/skills/cli-schema-types.d.ts +1 -0
  188. package/dist-lib/lib/tools/skills/cli-schema.js +25 -0
  189. package/dist-lib/lib/wire.d.ts +5 -0
  190. package/dist-lib/lib/wire.js +128 -5
  191. package/dist-lib/schema/harness.js +20 -5
  192. package/dist-lib/spec/hrpc/messages.js +95 -15
  193. package/dist-lib/spec/hyperschema/index.js +95 -15
  194. package/dist-lib/spec/hyperschema/schema.json +69 -1
  195. package/dist-lib/spec/hyperschema/types.d.ts +10 -3
  196. package/package.json +20 -2
  197. package/patches/@qvac%2Finference@0.20.0.patch +67 -0
  198. package/patches/bare-stow@0.1.5.patch +68 -0
  199. package/patches/hypercore-blob-server@1.15.0.patch +15 -0
  200. package/patches/localwatch@1.4.3.patch +13 -0
  201. package/patches/pyodide@314.0.2.patch +144 -0
@@ -0,0 +1,483 @@
1
+ import { waitFor } from 'xstate';
2
+ import { createCompletionMachine } from './completion/machine.js';
3
+ import { createInvokeTracker } from './completion/ports.js';
4
+ import { isRecord } from '../run-log/patch.js';
5
+ import { replayFinalRound, replaySuccessOutput } from './replay-output.js';
6
+ import { AbortedError, didDrainTimeOut, raceDrain, rehydrateError, tagError } from './errors.js';
7
+ import { createPersistedActor } from '../run-log/persisted-actor.js';
8
+ import { stableStringify } from './stable-stringify.js';
9
+ import { applyEngineStep, captureRunRecord, captureEngineStep, createEngineStep, prepareEngineBoot, transitionName } from '../run-log/protocol.js';
10
+ export { stableStringify } from './stable-stringify.js';
11
+ import { MACHINE_VERSION, XSTATE_VERSION, RUN_LOG_VERSION, ENGINE_BOUNDARY_BOOT, RunJournal, acquireRun, copy } from '../run-log/run-journal.js';
12
+ function nameOf(named) {
13
+ return transitionName(named);
14
+ }
15
+ function stripTransition(transition) {
16
+ const out = { eventType: transition.eventType };
17
+ if (transition.target?.length) {
18
+ out.target = transition.target.map((node) => node.id);
19
+ }
20
+ if (transition.guard) {
21
+ out.guard = nameOf(transition.guard);
22
+ }
23
+ if (transition.actions.length) {
24
+ out.actions = transition.actions.map(nameOf);
25
+ }
26
+ return out;
27
+ }
28
+ let cachedDefinition;
29
+ function machineDefinition() {
30
+ cachedDefinition ??= stripNode(createCompletionMachine().root);
31
+ return cachedDefinition;
32
+ }
33
+ export function completionMachineDefinition() {
34
+ return copy(machineDefinition());
35
+ }
36
+ function stripNode(node) {
37
+ const out = {
38
+ id: node.id,
39
+ type: node.type,
40
+ tags: [...node.tags],
41
+ entry: node.entry.map(nameOf),
42
+ exit: node.exit.map(nameOf),
43
+ invoke: node.invoke.map((invoke) => ({
44
+ id: invoke.id,
45
+ src: typeof invoke.src === 'string' ? invoke.src : nameOf(invoke.src)
46
+ }))
47
+ };
48
+ const initial = node.initial?.target?.[0]?.id;
49
+ if (initial) {
50
+ const prefix = `${node.id}.`;
51
+ out.initial = initial.startsWith(prefix) ? initial.slice(prefix.length) : initial;
52
+ }
53
+ const children = Object.entries(node.states);
54
+ if (children.length) {
55
+ out.states = Object.fromEntries(children.map(([key, child]) => [key, stripNode(child)]));
56
+ }
57
+ if (node.transitions.size) {
58
+ out.on = Object.fromEntries([...node.transitions].map(([event, list]) => [event, list.map(stripTransition)]));
59
+ }
60
+ if (node.always?.length) {
61
+ out.always = node.always.map(stripTransition);
62
+ }
63
+ return out;
64
+ }
65
+ export const HOST_APPEND_TIMEOUT_MS = 5000;
66
+ function readRestoredSnapshot(value) {
67
+ if (!isRecord(value) || Array.isArray(value))
68
+ return undefined;
69
+ const context = isRecord(value.context) && !Array.isArray(value.context) ? value.context : undefined;
70
+ return { status: value.status, output: value.output, context };
71
+ }
72
+ function isActiveIdle(snapshot) {
73
+ const value = snapshot.value;
74
+ return isRecord(value) && value.active === 'idle';
75
+ }
76
+ function isPausedOrAwaitingRecovery(snapshot) {
77
+ return snapshot.hasTag('paused');
78
+ }
79
+ function wasInActiveState(snapshot, name) {
80
+ if (isRecord(snapshot.value) && snapshot.value.active === name) {
81
+ return true;
82
+ }
83
+ const historyValue = Reflect.get(snapshot, 'historyValue');
84
+ if (!isRecord(historyValue)) {
85
+ return false;
86
+ }
87
+ return Object.values(historyValue).some((nodes) => Array.isArray(nodes) &&
88
+ nodes.some((node) => isRecord(node) && node.id === `completion.active.${name}`));
89
+ }
90
+ export async function* runEngine(run, options = {}) {
91
+ const { runId } = run;
92
+ const log = boundaryLog(options, runId);
93
+ const journal = new RunJournal(log, {
94
+ boot: log[ENGINE_BOUNDARY_BOOT](),
95
+ redact: options.redact,
96
+ redactShared: options.redactShared,
97
+ redactOperationResult: options.redactOperationResult,
98
+ redactRecord: options.redactRecord
99
+ });
100
+ const core = journal.core;
101
+ const release = acquireRun(run.lockOwner ?? options.lockOwner ?? core, runId);
102
+ try {
103
+ if (!journal.restored) {
104
+ await journal.restore();
105
+ }
106
+ else if (journal.knownLength !== core.length) {
107
+ throw new Error(`Run ${runId} changed while opening`);
108
+ }
109
+ if (run.resume) {
110
+ if (!journal.metadata) {
111
+ throw new Error(`Run ${runId} does not exist`);
112
+ }
113
+ const requestMatches = run.request === undefined ||
114
+ stableStringify(journal.metadata.request) === stableStringify(run.request);
115
+ if (journal.metadata.runId !== runId ||
116
+ (run.requestDigest !== undefined
117
+ ? journal.metadata.requestDigest !== run.requestDigest
118
+ : !requestMatches)) {
119
+ throw new Error('Resume cannot replace the original model, conversation, or execution configuration');
120
+ }
121
+ }
122
+ else {
123
+ if (run.request === undefined) {
124
+ throw new Error('A new run requires a request identity');
125
+ }
126
+ if (core.length) {
127
+ throw new Error(`Run ${runId} already exists; use resume mode`);
128
+ }
129
+ if (run.recovery?.length) {
130
+ throw new Error('Recovery resolutions require resume mode');
131
+ }
132
+ const metadata = {
133
+ version: RUN_LOG_VERSION,
134
+ type: 'metadata',
135
+ machine: MACHINE_VERSION,
136
+ definition: machineDefinition(),
137
+ xstate: XSTATE_VERSION,
138
+ runId,
139
+ request: run.request,
140
+ requestDigest: run.requestDigest,
141
+ digestRunId: run.requestDigest ? runId : undefined,
142
+ budget: run.budget,
143
+ startedAt: run.now ? run.now() : undefined
144
+ };
145
+ await journal.append(metadata);
146
+ }
147
+ const restored = readRestoredSnapshot(journal.snapshot);
148
+ if (restored && restored.context?.runId !== runId) {
149
+ throw new Error('Run checkpoint identity does not match its metadata');
150
+ }
151
+ await journal.resolve(run.recovery ?? []);
152
+ if (restored?.status === 'done') {
153
+ yield { type: run.resume ? 'run-resumed' : 'run-started', runId };
154
+ const round = restored.context?.round;
155
+ if (run.resume && typeof round === 'number') {
156
+ yield { type: 'round-reset', runId, round, replacedTypes: ['content', 'thinking'] };
157
+ }
158
+ const output = restored.output;
159
+ if (isRecord(output) && output.status === 'failure') {
160
+ const failure = restored.context?.failure;
161
+ const fallback = typeof output.error === 'string' ? output.error : 'Completion failed';
162
+ throw rehydrateError(failure ? tagError(failure) : undefined, fallback);
163
+ }
164
+ yield* replaySuccessOutput({ runId, round, context: restored.context, output });
165
+ return { status: 'replayed' };
166
+ }
167
+ yield { type: run.resume ? 'run-resumed' : 'run-started', runId };
168
+ const invokes = createInvokeTracker();
169
+ const boot = immutableBoot(getCurrentBoot(log, journal));
170
+ const mailbox = createEventMailbox();
171
+ const { ports, context } = await run.start({
172
+ operations: createOperationPort(journal),
173
+ invokes,
174
+ boot
175
+ });
176
+ return yield* drive({
177
+ journal,
178
+ run,
179
+ machine: createCompletionMachine(context, ports.now, {
180
+ ports,
181
+ journal,
182
+ invokes,
183
+ emitContent: (event) => mailbox.emit(event)
184
+ }),
185
+ invokes,
186
+ now: ports.now,
187
+ durable: typeof options.onStep === 'function',
188
+ onDetached: options.onDetached,
189
+ mailbox
190
+ });
191
+ }
192
+ finally {
193
+ if (journal.detachedEffects) {
194
+ journal.sealed = true;
195
+ }
196
+ release();
197
+ }
198
+ }
199
+ async function* drive({ journal, run, machine, invokes, now, durable, onDetached, mailbox }) {
200
+ const { runId, signal } = run;
201
+ const pausedMs = run.resume && journal.snapshotSavedAt !== undefined
202
+ ? Math.max(0, now() - journal.snapshotSavedAt)
203
+ : 0;
204
+ const { queue } = mailbox;
205
+ let detached = false;
206
+ const detach = () => {
207
+ detached = true;
208
+ if (!journal.detachedEffects) {
209
+ journal.detachedEffects = invokes.waitForInvokes();
210
+ onDetached?.(journal.detachedEffects, runId);
211
+ }
212
+ };
213
+ let wake = () => { };
214
+ let wakeVersion = 0;
215
+ const notify = () => {
216
+ wakeVersion++;
217
+ wake();
218
+ };
219
+ mailbox.notify = notify;
220
+ const { actor, persistence } = await createPersistedActor(journal, machine, notify, now);
221
+ actor.on('*', (event) => {
222
+ queue.push(event);
223
+ notify();
224
+ });
225
+ actor.subscribe({ next: notify, error: notify });
226
+ const pause = () => {
227
+ if (actor.getSnapshot().status === 'active') {
228
+ actor.send({ type: 'PAUSE' });
229
+ }
230
+ notify();
231
+ };
232
+ signal?.addEventListener('abort', pause);
233
+ try {
234
+ await persistence.checkpoint();
235
+ const restored = actor.getSnapshot();
236
+ actor.start();
237
+ if (run.resume) {
238
+ if (!actor.getSnapshot().hasTag('paused')) {
239
+ pause();
240
+ }
241
+ const result = await drainResume({ actor, invokes, persistence, durable, detach });
242
+ if (result) {
243
+ return result;
244
+ }
245
+ yield* replayInterruptedGeneration(runId, restored);
246
+ const uncertain = journal.uncertainWrite();
247
+ if (uncertain) {
248
+ actor.send({ type: 'RECOVERY_REQUIRED', operation: uncertain });
249
+ }
250
+ else if (!signal?.aborted) {
251
+ actor.send({ type: 'RESUME', pausedMs });
252
+ }
253
+ }
254
+ if (signal?.aborted) {
255
+ pause();
256
+ }
257
+ else if (isActiveIdle(actor.getSnapshot())) {
258
+ actor.send({ type: 'START' });
259
+ }
260
+ while (true) {
261
+ if (journal.hasPendingFlush()) {
262
+ await persistence.flush();
263
+ }
264
+ yield* drainQueue(queue);
265
+ if (isActiveIdle(actor.getSnapshot()) && !signal?.aborted) {
266
+ actor.send({ type: 'START' });
267
+ }
268
+ const snapshot = actor.getSnapshot();
269
+ if (snapshot.status === 'error') {
270
+ return { status: 'error', snapshot, error: snapshot.error };
271
+ }
272
+ if (snapshot.status === 'done') {
273
+ break;
274
+ }
275
+ const isSettling = settling(snapshot);
276
+ const settlingResult = isSettling
277
+ ? await drainSettling({ actor, persistence, durable, detach })
278
+ : undefined;
279
+ if (settlingResult) {
280
+ yield* drainQueue(queue);
281
+ return settlingResult;
282
+ }
283
+ if (isSettling) {
284
+ continue;
285
+ }
286
+ if (isPausedOrAwaitingRecovery(snapshot)) {
287
+ return yield* finishPaused({
288
+ actor,
289
+ invokes,
290
+ persistence,
291
+ durable,
292
+ detach,
293
+ journal,
294
+ queue,
295
+ runId
296
+ });
297
+ }
298
+ const observedWakeVersion = wakeVersion;
299
+ if (queue.length) {
300
+ continue;
301
+ }
302
+ await new Promise((resolve) => {
303
+ wake = resolve;
304
+ if (wakeVersion !== observedWakeVersion) {
305
+ resolve();
306
+ }
307
+ });
308
+ }
309
+ await persistence.flush();
310
+ yield* drainQueue(queue);
311
+ return { status: 'done', snapshot: actor.getSnapshot() };
312
+ }
313
+ finally {
314
+ signal?.removeEventListener('abort', pause);
315
+ try {
316
+ if (actor.getSnapshot().status === 'active') {
317
+ pause();
318
+ }
319
+ if (!detached && (await invokes.drainTimedOut())) {
320
+ detach();
321
+ }
322
+ if (await shouldDetachWhileClosing({ detached, journal, actor })) {
323
+ detach();
324
+ }
325
+ await persistence.checkpoint();
326
+ await persistence.flush();
327
+ run.settled?.(actor.getSnapshot());
328
+ }
329
+ finally {
330
+ await persistence.dispose();
331
+ }
332
+ }
333
+ }
334
+ async function drainResume({ actor, invokes, persistence, durable, detach }) {
335
+ if (await invokes.drainTimedOut()) {
336
+ return interruptedResult({ actor, persistence, durable, detach });
337
+ }
338
+ if (!settling(actor.getSnapshot())) {
339
+ return undefined;
340
+ }
341
+ const timedOut = didDrainTimeOut(await raceDrain(waitFor(actor, (state) => !settling(state))));
342
+ return timedOut ? interruptedResult({ actor, persistence, durable, detach }) : undefined;
343
+ }
344
+ async function drainSettling(options) {
345
+ const { actor, persistence, durable, detach } = options;
346
+ const timedOut = didDrainTimeOut(await raceDrain(waitFor(actor, (state) => !settling(state))));
347
+ return timedOut ? interruptedResult({ actor, persistence, durable, detach }) : undefined;
348
+ }
349
+ async function interruptedResult({ actor, persistence, durable, detach }) {
350
+ detach();
351
+ await persistence.flush();
352
+ const snapshot = actor.getSnapshot();
353
+ return durable
354
+ ? { status: 'paused', snapshot }
355
+ : { status: 'error', snapshot, error: tagError(new AbortedError()) };
356
+ }
357
+ async function detachIfDrained(invokes, detach) {
358
+ if (await invokes.drainTimedOut()) {
359
+ detach();
360
+ }
361
+ }
362
+ function pendingRecovery(snapshot, journal) {
363
+ const recovery = snapshot.context.recovery;
364
+ return recovery && journal.getReceipt(recovery.id)?.status !== 'result' ? recovery : undefined;
365
+ }
366
+ async function* finishPaused({ actor, invokes, persistence, durable, detach, journal, queue, runId }) {
367
+ await detachIfDrained(invokes, detach);
368
+ await persistence.flush();
369
+ const snapshot = actor.getSnapshot();
370
+ const recovery = pendingRecovery(snapshot, journal);
371
+ if (recovery) {
372
+ const event = { type: 'recovery-required', runId, operation: copy(recovery) };
373
+ yield event;
374
+ }
375
+ yield* drainQueue(queue);
376
+ return durable
377
+ ? { status: 'paused', snapshot }
378
+ : { status: 'error', snapshot, error: tagError(new AbortedError()) };
379
+ }
380
+ async function shouldDetachWhileClosing({ detached, journal, actor }) {
381
+ if (detached || journal.failure || !settling(actor.getSnapshot())) {
382
+ return false;
383
+ }
384
+ return didDrainTimeOut(await raceDrain(waitFor(actor, (snapshot) => !settling(snapshot))));
385
+ }
386
+ function* replayInterruptedGeneration(runId, snapshot) {
387
+ const { round, lastRound } = snapshot.context;
388
+ const finishingRound = lastRound &&
389
+ (wasInActiveState(snapshot, 'answering') ||
390
+ wasInActiveState(snapshot, 'finishing') ||
391
+ (wasInActiveState(snapshot, 'resolving') && !lastRound.toolCalls.length));
392
+ const shouldReplay = wasInActiveState(snapshot, 'generating') ||
393
+ wasInActiveState(snapshot, 'wrapping') ||
394
+ finishingRound;
395
+ if (!shouldReplay) {
396
+ return;
397
+ }
398
+ yield { type: 'round-reset', runId, round };
399
+ if (finishingRound && lastRound) {
400
+ yield* replayFinalRound({ runId, round, last: lastRound, response: snapshot.context.response });
401
+ }
402
+ }
403
+ function settling(snapshot) {
404
+ const value = snapshot.value;
405
+ return value === 'pausing';
406
+ }
407
+ function* drainQueue(queue) {
408
+ while (queue.length) {
409
+ const event = queue.shift();
410
+ if (event) {
411
+ yield event;
412
+ }
413
+ }
414
+ }
415
+ function createEventMailbox() {
416
+ const mailbox = {
417
+ queue: [],
418
+ notify() { },
419
+ emit(event) {
420
+ mailbox.queue.push(event);
421
+ mailbox.notify();
422
+ }
423
+ };
424
+ return mailbox;
425
+ }
426
+ function boundaryLog(options, runId) {
427
+ let boot = prepareEngineBoot(options.boot);
428
+ const log = {
429
+ [ENGINE_BOUNDARY_BOOT]: () => boot,
430
+ get length() {
431
+ return boot.length;
432
+ },
433
+ ready: async () => { },
434
+ get: async () => {
435
+ return null;
436
+ },
437
+ async append(value) {
438
+ const step = createEngineStep(boot.nextSeq, boot.length, [captureRunRecord(value)]);
439
+ const prepared = options.redactStep ? captureEngineStep(options.redactStep(step)) : step;
440
+ const next = applyEngineStep(boot, prepared);
441
+ const append = options.onStep?.(prepared);
442
+ if (append) {
443
+ const configured = options.hostAppendTimeoutMs;
444
+ const timeoutMs = typeof configured === 'number' && Number.isFinite(configured) && configured > 0
445
+ ? Math.min(configured, 2 ** 31 - 1)
446
+ : HOST_APPEND_TIMEOUT_MS;
447
+ const acknowledged = await raceDrain(append, timeoutMs);
448
+ if (didDrainTimeOut(acknowledged)) {
449
+ try {
450
+ options.onDetached?.(append, runId);
451
+ }
452
+ catch {
453
+ }
454
+ throw new Error(`Host run-log append did not acknowledge within ${timeoutMs}ms`);
455
+ }
456
+ }
457
+ boot = next;
458
+ return boot;
459
+ }
460
+ };
461
+ return log;
462
+ }
463
+ function getCurrentBoot(log, journal) {
464
+ const readBoot = Reflect.get(log, ENGINE_BOUNDARY_BOOT);
465
+ return typeof readBoot === 'function' ? readBoot.call(log) : journal.exportBoot();
466
+ }
467
+ function createOperationPort(journal) {
468
+ return Object.freeze({
469
+ flush: () => journal.flush(),
470
+ operation: operationPort(journal),
471
+ getReceipt: (id) => journal.getReceipt(id),
472
+ commitResultFacts: (id, facts) => journal.commitResultFacts(id, facts),
473
+ uncertainWrite: () => journal.uncertainWrite(),
474
+ settledCall: (receiptId) => journal.settledCall(receiptId),
475
+ pendingArgumentsWereRedacted: (snapshot) => journal.pendingArgumentsWereRedacted(snapshot)
476
+ });
477
+ }
478
+ function operationPort(journal) {
479
+ return journal.operation.bind(journal);
480
+ }
481
+ function immutableBoot(boot) {
482
+ return prepareEngineBoot(boot);
483
+ }
@@ -0,0 +1,44 @@
1
+ import type { Operation } from '../run-log/protocol-types.ts';
2
+ export type { Operation } from '../run-log/protocol-types.ts';
3
+ export declare class RecoveryRequired extends Error {
4
+ readonly operation: Operation;
5
+ constructor(operation: Operation);
6
+ }
7
+ export declare class AbortedError extends Error {
8
+ constructor();
9
+ }
10
+ export declare class ToolPolicyChanged extends Error {
11
+ constructor(tool: string);
12
+ }
13
+ export declare const EFFECT_DRAIN_TIMEOUT_MS = 5000;
14
+ declare const TIMED_OUT: unique symbol;
15
+ export declare function raceDrain<T>(promise: Promise<T>, timeoutMs?: number): Promise<T | typeof TIMED_OUT>;
16
+ export declare function didDrainTimeOut(value: unknown): value is typeof TIMED_OUT;
17
+ export interface ErrorCause {
18
+ message: string;
19
+ name: string;
20
+ code?: string;
21
+ stack?: string;
22
+ cause?: ErrorCause;
23
+ }
24
+ export type EngineError = {
25
+ tag: 'recovery';
26
+ message: string;
27
+ name: string;
28
+ operation: Operation;
29
+ stack?: string;
30
+ } | {
31
+ tag: 'aborted';
32
+ message: string;
33
+ name: string;
34
+ stack?: string;
35
+ } | {
36
+ tag: 'failed';
37
+ message: string;
38
+ name: string;
39
+ code?: string;
40
+ stack?: string;
41
+ cause?: ErrorCause;
42
+ };
43
+ export declare function tagError(error: unknown): EngineError;
44
+ export declare function rehydrateError(value: EngineError | ErrorCause | null | undefined, fallbackMessage?: string): Error;