@nodetool-ai/reliability-harness 0.8.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.
- package/README.md +34 -0
- package/dist/.nodetool-build-stamp +1 -0
- package/dist/cli.d.ts +73 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +201 -0
- package/dist/cli.js.map +1 -0
- package/dist/compare.d.ts +98 -0
- package/dist/compare.d.ts.map +1 -0
- package/dist/compare.js +267 -0
- package/dist/compare.js.map +1 -0
- package/dist/core/diff.d.ts +39 -0
- package/dist/core/diff.d.ts.map +1 -0
- package/dist/core/diff.js +114 -0
- package/dist/core/diff.js.map +1 -0
- package/dist/core/golden.d.ts +50 -0
- package/dist/core/golden.d.ts.map +1 -0
- package/dist/core/golden.js +150 -0
- package/dist/core/golden.js.map +1 -0
- package/dist/core/invariants/index.d.ts +32 -0
- package/dist/core/invariants/index.d.ts.map +1 -0
- package/dist/core/invariants/index.js +44 -0
- package/dist/core/invariants/index.js.map +1 -0
- package/dist/core/invariants/leaks.d.ts +22 -0
- package/dist/core/invariants/leaks.d.ts.map +1 -0
- package/dist/core/invariants/leaks.js +55 -0
- package/dist/core/invariants/leaks.js.map +1 -0
- package/dist/core/invariants/lifecycle.d.ts +19 -0
- package/dist/core/invariants/lifecycle.d.ts.map +1 -0
- package/dist/core/invariants/lifecycle.js +95 -0
- package/dist/core/invariants/lifecycle.js.map +1 -0
- package/dist/core/invariants/protocol-validity.d.ts +4 -0
- package/dist/core/invariants/protocol-validity.d.ts.map +1 -0
- package/dist/core/invariants/protocol-validity.js +131 -0
- package/dist/core/invariants/protocol-validity.js.map +1 -0
- package/dist/core/invariants/state-machine.d.ts +29 -0
- package/dist/core/invariants/state-machine.d.ts.map +1 -0
- package/dist/core/invariants/state-machine.js +79 -0
- package/dist/core/invariants/state-machine.js.map +1 -0
- package/dist/core/invariants/status-sets.d.ts +27 -0
- package/dist/core/invariants/status-sets.d.ts.map +1 -0
- package/dist/core/invariants/status-sets.js +51 -0
- package/dist/core/invariants/status-sets.js.map +1 -0
- package/dist/core/invariants/terminal-uniqueness.d.ts +23 -0
- package/dist/core/invariants/terminal-uniqueness.d.ts.map +1 -0
- package/dist/core/invariants/terminal-uniqueness.js +99 -0
- package/dist/core/invariants/terminal-uniqueness.js.map +1 -0
- package/dist/core/invariants/types.d.ts +25 -0
- package/dist/core/invariants/types.d.ts.map +1 -0
- package/dist/core/invariants/types.js +2 -0
- package/dist/core/invariants/types.js.map +1 -0
- package/dist/core/journey.d.ts +121 -0
- package/dist/core/journey.d.ts.map +1 -0
- package/dist/core/journey.js +166 -0
- package/dist/core/journey.js.map +1 -0
- package/dist/core/normalize.d.ts +86 -0
- package/dist/core/normalize.d.ts.map +1 -0
- package/dist/core/normalize.js +182 -0
- package/dist/core/normalize.js.map +1 -0
- package/dist/core/record.d.ts +160 -0
- package/dist/core/record.d.ts.map +1 -0
- package/dist/core/record.js +74 -0
- package/dist/core/record.js.map +1 -0
- package/dist/core/stable-json.d.ts +13 -0
- package/dist/core/stable-json.d.ts.map +1 -0
- package/dist/core/stable-json.js +28 -0
- package/dist/core/stable-json.js.map +1 -0
- package/dist/drivers/anchors.d.ts +29 -0
- package/dist/drivers/anchors.d.ts.map +1 -0
- package/dist/drivers/anchors.js +48 -0
- package/dist/drivers/anchors.js.map +1 -0
- package/dist/drivers/app-headless.d.ts +39 -0
- package/dist/drivers/app-headless.d.ts.map +1 -0
- package/dist/drivers/app-headless.js +123 -0
- package/dist/drivers/app-headless.js.map +1 -0
- package/dist/drivers/browser.d.ts +34 -0
- package/dist/drivers/browser.d.ts.map +1 -0
- package/dist/drivers/browser.js +176 -0
- package/dist/drivers/browser.js.map +1 -0
- package/dist/drivers/cli.d.ts +13 -0
- package/dist/drivers/cli.d.ts.map +1 -0
- package/dist/drivers/cli.js +82 -0
- package/dist/drivers/cli.js.map +1 -0
- package/dist/drivers/fixture-nodes.d.ts +124 -0
- package/dist/drivers/fixture-nodes.d.ts.map +1 -0
- package/dist/drivers/fixture-nodes.js +189 -0
- package/dist/drivers/fixture-nodes.js.map +1 -0
- package/dist/drivers/index.d.ts +18 -0
- package/dist/drivers/index.d.ts.map +1 -0
- package/dist/drivers/index.js +12 -0
- package/dist/drivers/index.js.map +1 -0
- package/dist/drivers/kernel.d.ts +8 -0
- package/dist/drivers/kernel.d.ts.map +1 -0
- package/dist/drivers/kernel.js +247 -0
- package/dist/drivers/kernel.js.map +1 -0
- package/dist/drivers/packaged.d.ts +28 -0
- package/dist/drivers/packaged.d.ts.map +1 -0
- package/dist/drivers/packaged.js +303 -0
- package/dist/drivers/packaged.js.map +1 -0
- package/dist/drivers/python-bridge.d.ts +22 -0
- package/dist/drivers/python-bridge.d.ts.map +1 -0
- package/dist/drivers/python-bridge.js +48 -0
- package/dist/drivers/python-bridge.js.map +1 -0
- package/dist/drivers/registry.d.ts +11 -0
- package/dist/drivers/registry.d.ts.map +1 -0
- package/dist/drivers/registry.js +18 -0
- package/dist/drivers/registry.js.map +1 -0
- package/dist/drivers/relay-fields.d.ts +70 -0
- package/dist/drivers/relay-fields.d.ts.map +1 -0
- package/dist/drivers/relay-fields.js +104 -0
- package/dist/drivers/relay-fields.js.map +1 -0
- package/dist/drivers/repo-root.d.ts +9 -0
- package/dist/drivers/repo-root.d.ts.map +1 -0
- package/dist/drivers/repo-root.js +39 -0
- package/dist/drivers/repo-root.js.map +1 -0
- package/dist/drivers/spawn-cli.d.ts +8 -0
- package/dist/drivers/spawn-cli.d.ts.map +1 -0
- package/dist/drivers/spawn-cli.js +41 -0
- package/dist/drivers/spawn-cli.js.map +1 -0
- package/dist/drivers/types.d.ts +18 -0
- package/dist/drivers/types.d.ts.map +1 -0
- package/dist/drivers/types.js +2 -0
- package/dist/drivers/types.js.map +1 -0
- package/dist/drivers/ws-server.d.ts +8 -0
- package/dist/drivers/ws-server.d.ts.map +1 -0
- package/dist/drivers/ws-server.js +382 -0
- package/dist/drivers/ws-server.js.map +1 -0
- package/dist/faults/bridge-faults.d.ts +7 -0
- package/dist/faults/bridge-faults.d.ts.map +1 -0
- package/dist/faults/bridge-faults.js +90 -0
- package/dist/faults/bridge-faults.js.map +1 -0
- package/dist/faults/host-faults.d.ts +40 -0
- package/dist/faults/host-faults.d.ts.map +1 -0
- package/dist/faults/host-faults.js +70 -0
- package/dist/faults/host-faults.js.map +1 -0
- package/dist/faults/index.d.ts +21 -0
- package/dist/faults/index.d.ts.map +1 -0
- package/dist/faults/index.js +29 -0
- package/dist/faults/index.js.map +1 -0
- package/dist/faults/net-proxy.d.ts +75 -0
- package/dist/faults/net-proxy.d.ts.map +1 -0
- package/dist/faults/net-proxy.js +305 -0
- package/dist/faults/net-proxy.js.map +1 -0
- package/dist/faults/provider-faults.d.ts +12 -0
- package/dist/faults/provider-faults.d.ts.map +1 -0
- package/dist/faults/provider-faults.js +110 -0
- package/dist/faults/provider-faults.js.map +1 -0
- package/dist/faults/registry.d.ts +17 -0
- package/dist/faults/registry.d.ts.map +1 -0
- package/dist/faults/registry.js +15 -0
- package/dist/faults/registry.js.map +1 -0
- package/dist/faults/types.d.ts +42 -0
- package/dist/faults/types.d.ts.map +1 -0
- package/dist/faults/types.js +2 -0
- package/dist/faults/types.js.map +1 -0
- package/dist/faults/ws-faults.d.ts +6 -0
- package/dist/faults/ws-faults.d.ts.map +1 -0
- package/dist/faults/ws-faults.js +48 -0
- package/dist/faults/ws-faults.js.map +1 -0
- package/dist/faults/ws-proxy.d.ts +36 -0
- package/dist/faults/ws-proxy.d.ts.map +1 -0
- package/dist/faults/ws-proxy.js +40 -0
- package/dist/faults/ws-proxy.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/package.json +75 -0
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Hermetic fixture nodes for journeys the real node registry has no node
|
|
9
|
+
* for: a controllable long-running actor (mid-run cancellation while a node
|
|
10
|
+
* is `running`) and an externally-fed streaming input (mid-run cancellation
|
|
11
|
+
* while a node is mid-stream). Every other C2 journey uses real registered
|
|
12
|
+
* `nodetool.*` node classes from `@nodetool-ai/base-nodes` (§5: "prefer core
|
|
13
|
+
* nodes... so the kernel driver can run them too") — these three fill the
|
|
14
|
+
* one gap: no shipped node exposes a controllable busy-loop or a
|
|
15
|
+
* `pushInput`-fed external stream.
|
|
16
|
+
*
|
|
17
|
+
* Registered identically into both drivers' registries (`registry.ts` for
|
|
18
|
+
* the kernel driver, `configureRegistry` for the ws-server driver) so their
|
|
19
|
+
* behavior is byte-identical on both surfaces — modeled on the equivalent
|
|
20
|
+
* fixtures in `packages/execution/tests/fixtures.ts`.
|
|
21
|
+
*/
|
|
22
|
+
import { BaseNode, prop } from "@nodetool-ai/node-sdk";
|
|
23
|
+
/**
|
|
24
|
+
* External input node whose output is structurally streaming (the trivial
|
|
25
|
+
* `genProcess` override flips `hasStreamingOutput()`), so the kernel keeps
|
|
26
|
+
* its downstream inbox open for `pushInput`/`finishInputStream` (and the
|
|
27
|
+
* ws-server's `stream_input`/`end_input_stream` commands) instead of
|
|
28
|
+
* dispatching a one-shot default. The generator itself is never invoked when
|
|
29
|
+
* the node has no incoming edges — the kernel dispatches it as an external
|
|
30
|
+
* input, not a spawned actor.
|
|
31
|
+
*
|
|
32
|
+
* The `nodetool.input.` prefix is load-bearing, not cosmetic: the kernel's
|
|
33
|
+
* `_isExternalInputNode`/`_dispatchInputs` (`runner.ts`) recognize external
|
|
34
|
+
* inputs by type-prefix, not by the `genProcess` override alone. A type
|
|
35
|
+
* outside that prefix (e.g. an early `test.reliability.*` draft of this
|
|
36
|
+
* fixture) gets spawned as an ordinary zero-input actor instead — it runs
|
|
37
|
+
* `genProcess` once to completion immediately, which defeats the whole
|
|
38
|
+
* point of a `pushInput`-fed external stream.
|
|
39
|
+
*/
|
|
40
|
+
export class ReliabilityStreamingInputNode extends BaseNode {
|
|
41
|
+
static nodeType = "nodetool.input.ReliabilityStreamingInput";
|
|
42
|
+
static title = "Reliability Streaming Input";
|
|
43
|
+
static description = "Test fixture: external input fed by pushInput/stream_input.";
|
|
44
|
+
async process() {
|
|
45
|
+
return { output: this.value };
|
|
46
|
+
}
|
|
47
|
+
async *genProcess() {
|
|
48
|
+
yield { output: this.value };
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
__decorate([
|
|
52
|
+
prop({ type: "any", default: null })
|
|
53
|
+
], ReliabilityStreamingInputNode.prototype, "value", void 0);
|
|
54
|
+
/** Collects every value streamed on its `value` input into one terminal array. */
|
|
55
|
+
export class ReliabilityStreamSinkNode extends BaseNode {
|
|
56
|
+
static nodeType = "test.reliability.StreamSink";
|
|
57
|
+
static title = "Reliability Stream Sink";
|
|
58
|
+
static description = "Test fixture: collects streamed values.";
|
|
59
|
+
static isStreamingInput = true;
|
|
60
|
+
/** Never invoked directly — the kernel dispatches streaming-input nodes
|
|
61
|
+
* through `run()`. Required only to satisfy `BaseNode`'s abstract member. */
|
|
62
|
+
async process() {
|
|
63
|
+
return { output: [] };
|
|
64
|
+
}
|
|
65
|
+
async run(inputs, outputs) {
|
|
66
|
+
const collected = [];
|
|
67
|
+
for await (const value of inputs.stream("value")) {
|
|
68
|
+
collected.push(value);
|
|
69
|
+
}
|
|
70
|
+
// A cancellation is exactly what closes the loop above without a
|
|
71
|
+
// natural EOS. Skipping the final emit in that case is deliberate, not
|
|
72
|
+
// just tidy: `WorkflowRunner._sendMessages` (the code path an
|
|
73
|
+
// `outputs.emit()` call after the loop would reach) gates on
|
|
74
|
+
// `this._cancelled` and no-ops once it's set — but the kernel driver's
|
|
75
|
+
// in-process `cancel()` and the ws-server driver's networked
|
|
76
|
+
// `cancel_job` command reach that flag at genuinely different wall-clock
|
|
77
|
+
// offsets from this actor's own scheduling, so whether the runner's own
|
|
78
|
+
// gate has already flipped by the time this line would run is a race
|
|
79
|
+
// between the two surfaces, not just within one. Checking the signal
|
|
80
|
+
// here makes the "no output_update after a cancellation" outcome this
|
|
81
|
+
// fixture's own deterministic behavior instead of an incidental timing
|
|
82
|
+
// race the recorded stream would otherwise expose.
|
|
83
|
+
if (inputs.signal.aborted)
|
|
84
|
+
return;
|
|
85
|
+
await outputs.emit("output", collected);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* A busy node with no incoming edges: parked on the run's own
|
|
90
|
+
* `AbortSignal` — busy from the graph's perspective, distinct from journey
|
|
91
|
+
* 6b's `nodetool.input.*`-fed streaming node — until the run is cancelled.
|
|
92
|
+
*
|
|
93
|
+
* Two earlier designs both raced:
|
|
94
|
+
* - Polling `inputs.signal.aborted` in a `setTimeout`-paced loop raced the
|
|
95
|
+
* runner's own cancel bookkeeping — whether this actor's `run()`
|
|
96
|
+
* returned before or after `WorkflowRunner` finished processing
|
|
97
|
+
* `cancel()` depended on `setTimeout` scheduling granularity, so the
|
|
98
|
+
* exact frame sequence differed from run to run *on the same driver*,
|
|
99
|
+
* not just across drivers (§6: "two runs ... produce identical
|
|
100
|
+
* normalized streams").
|
|
101
|
+
* - Blocking on `inputs.stream()` for a handle no edge ever targets
|
|
102
|
+
* doesn't block at all: the inbox has zero registered writers for it
|
|
103
|
+
* from the start, so `stream()` resolves as an immediate EOS and the
|
|
104
|
+
* actor "completes" before any cancel command can possibly land.
|
|
105
|
+
*
|
|
106
|
+
* Listening for the signal's `abort` event is neither: it makes no progress
|
|
107
|
+
* of its own to race, and resolves only once, however long that takes.
|
|
108
|
+
*/
|
|
109
|
+
export class ReliabilityCancelProbeNode extends BaseNode {
|
|
110
|
+
static nodeType = "test.reliability.CancelProbe";
|
|
111
|
+
static title = "Reliability Cancel Probe";
|
|
112
|
+
static description = "Test fixture: blocks until cancelled.";
|
|
113
|
+
static isStreamingInput = true;
|
|
114
|
+
/** Never invoked directly — see {@link ReliabilityStreamSinkNode.process}. */
|
|
115
|
+
async process() {
|
|
116
|
+
return {};
|
|
117
|
+
}
|
|
118
|
+
async run(inputs) {
|
|
119
|
+
if (inputs.signal.aborted)
|
|
120
|
+
return;
|
|
121
|
+
await new Promise((resolve) => {
|
|
122
|
+
inputs.signal.addEventListener("abort", () => resolve(), { once: true });
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Writes bytes through `context.storage` — the one write op every real
|
|
128
|
+
* asset-producing node eventually calls. Exists purely as a deterministic,
|
|
129
|
+
* hermetic target for task D3's `host-disk-full` fault: no shipped node
|
|
130
|
+
* writes an asset without also touching media-ref plumbing this fixture
|
|
131
|
+
* doesn't need to exercise. A missing `context.storage` (the normal
|
|
132
|
+
* fault-free hermetic default — `ExecutionSession`'s own minimal context
|
|
133
|
+
* wires none) is a configuration error for a journey using this node, not a
|
|
134
|
+
* silent no-op, so it throws rather than skipping the write.
|
|
135
|
+
*/
|
|
136
|
+
export class ReliabilityStorageWriteNode extends BaseNode {
|
|
137
|
+
static nodeType = "test.reliability.StorageWrite";
|
|
138
|
+
static title = "Reliability Storage Write";
|
|
139
|
+
static description = "Test fixture: writes bytes through context.storage (task D3's host-disk-full fault).";
|
|
140
|
+
async process(context) {
|
|
141
|
+
if (!context?.storage) {
|
|
142
|
+
throw new Error("ReliabilityStorageWriteNode requires a ProcessingContext with storage wired");
|
|
143
|
+
}
|
|
144
|
+
const uri = await context.storage.store(`${this.key}.bin`, new Uint8Array([1, 2, 3]), "application/octet-stream");
|
|
145
|
+
return { output: uri };
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
__decorate([
|
|
149
|
+
prop({ type: "str", default: "reliability-fixture" })
|
|
150
|
+
], ReliabilityStorageWriteNode.prototype, "key", void 0);
|
|
151
|
+
/**
|
|
152
|
+
* Joins a `list[str]` property — the shared-list-handle multi-edge fan-in
|
|
153
|
+
* target for the `fan-in-shared-list-handle` journey (A5,
|
|
154
|
+
* docs/RELIABILITY_TASKS.md Track A). Unlike `fan-out-fan-in-dag`'s `join`
|
|
155
|
+
* node (two edges into two *distinct* handles, a workaround for the
|
|
156
|
+
* hydration gap where a hydration path without `propertyTypes` couldn't
|
|
157
|
+
* distinguish a genuine list fan-in from an invalid one), this node takes
|
|
158
|
+
* two edges into the SAME `items` handle — the case that gap used to reject
|
|
159
|
+
* outright on any surface hydrating without a metadata resolver.
|
|
160
|
+
*/
|
|
161
|
+
export class ReliabilityListJoinNode extends BaseNode {
|
|
162
|
+
static nodeType = "test.reliability.ListJoin";
|
|
163
|
+
static title = "Reliability List Join";
|
|
164
|
+
static description = "Test fixture: joins a list[str] input fed by a shared multi-edge handle.";
|
|
165
|
+
async process() {
|
|
166
|
+
const list = Array.isArray(this.items) ? this.items : [this.items];
|
|
167
|
+
return { output: [...list].map((v) => String(v ?? "")).sort().join(",") };
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
__decorate([
|
|
171
|
+
prop({ type: "list[str]", default: [] })
|
|
172
|
+
], ReliabilityListJoinNode.prototype, "items", void 0);
|
|
173
|
+
export const RELIABILITY_FIXTURE_NODES = [
|
|
174
|
+
ReliabilityStreamingInputNode,
|
|
175
|
+
ReliabilityStreamSinkNode,
|
|
176
|
+
ReliabilityCancelProbeNode,
|
|
177
|
+
ReliabilityStorageWriteNode,
|
|
178
|
+
ReliabilityListJoinNode
|
|
179
|
+
];
|
|
180
|
+
/** Registers the harness's own fixture nodes into a live registry. Idempotent
|
|
181
|
+
* (last-write-wins, matching `NodeRegistry.register`), so it's safe to call
|
|
182
|
+
* on both a fresh kernel-driver registry and a shared ws-server registry via
|
|
183
|
+
* `configureRegistry`. */
|
|
184
|
+
export function registerFixtureNodes(registry) {
|
|
185
|
+
for (const nodeClass of RELIABILITY_FIXTURE_NODES) {
|
|
186
|
+
registry.register(nodeClass);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
//# sourceMappingURL=fixture-nodes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fixture-nodes.js","sourceRoot":"","sources":["../../src/drivers/fixture-nodes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Driver entry point (C2/C4, docs/RELIABILITY_TASKS.md Track C). Now also
|
|
3
|
+
* re-exported from `../index.ts` (C4 item 7 lifts the "kept out of the main
|
|
4
|
+
* barrel" constraint C2/C3 deliberately left in place).
|
|
5
|
+
*/
|
|
6
|
+
export type { RunDriver } from "./types.js";
|
|
7
|
+
export { matchesAnchor, AnchorWaiter, type AnchoredMessage } from "./anchors.js";
|
|
8
|
+
export { RELIABILITY_FIXTURE_NODES, registerFixtureNodes, ReliabilityStreamingInputNode, ReliabilityStreamSinkNode, ReliabilityCancelProbeNode } from "./fixture-nodes.js";
|
|
9
|
+
export { buildJourneyRegistry } from "./registry.js";
|
|
10
|
+
export { KernelDriver } from "./kernel.js";
|
|
11
|
+
export { WsServerDriver } from "./ws-server.js";
|
|
12
|
+
export { findRepoRoot, resolveTsxBin } from "./repo-root.js";
|
|
13
|
+
export { spawnNodetoolCli, type CliRunResult } from "./spawn-cli.js";
|
|
14
|
+
export { CliDriver, cliDriverSupports } from "./cli.js";
|
|
15
|
+
export { AppHeadlessDriver, journeyHasAppDoc, runRecordFromAppDebugReport, type AppDebugReportLike } from "./app-headless.js";
|
|
16
|
+
export { BrowserDriver, runRecordFromBrowserRecord, type BrowserRunRecordLike } from "./browser.js";
|
|
17
|
+
export { PackagedDriver, stageBackendBundle, type PackagedDriverOptions } from "./packaged.js";
|
|
18
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/drivers/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AACjF,OAAO,EACL,yBAAyB,EACzB,oBAAoB,EACpB,6BAA6B,EAC7B,yBAAyB,EACzB,0BAA0B,EAC3B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACrE,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AACxD,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,2BAA2B,EAC3B,KAAK,kBAAkB,EACxB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,aAAa,EACb,0BAA0B,EAC1B,KAAK,oBAAoB,EAC1B,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,KAAK,qBAAqB,EAC3B,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { matchesAnchor, AnchorWaiter } from "./anchors.js";
|
|
2
|
+
export { RELIABILITY_FIXTURE_NODES, registerFixtureNodes, ReliabilityStreamingInputNode, ReliabilityStreamSinkNode, ReliabilityCancelProbeNode } from "./fixture-nodes.js";
|
|
3
|
+
export { buildJourneyRegistry } from "./registry.js";
|
|
4
|
+
export { KernelDriver } from "./kernel.js";
|
|
5
|
+
export { WsServerDriver } from "./ws-server.js";
|
|
6
|
+
export { findRepoRoot, resolveTsxBin } from "./repo-root.js";
|
|
7
|
+
export { spawnNodetoolCli } from "./spawn-cli.js";
|
|
8
|
+
export { CliDriver, cliDriverSupports } from "./cli.js";
|
|
9
|
+
export { AppHeadlessDriver, journeyHasAppDoc, runRecordFromAppDebugReport } from "./app-headless.js";
|
|
10
|
+
export { BrowserDriver, runRecordFromBrowserRecord } from "./browser.js";
|
|
11
|
+
export { PackagedDriver, stageBackendBundle } from "./packaged.js";
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/drivers/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,aAAa,EAAE,YAAY,EAAwB,MAAM,cAAc,CAAC;AACjF,OAAO,EACL,yBAAyB,EACzB,oBAAoB,EACpB,6BAA6B,EAC7B,yBAAyB,EACzB,0BAA0B,EAC3B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAqB,MAAM,gBAAgB,CAAC;AACrE,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AACxD,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,2BAA2B,EAE5B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,aAAa,EACb,0BAA0B,EAE3B,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,cAAc,EACd,kBAAkB,EAEnB,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Journey } from "../core/journey.js";
|
|
2
|
+
import { type RunRecord } from "../core/record.js";
|
|
3
|
+
import type { RunDriver } from "./types.js";
|
|
4
|
+
export declare class KernelDriver implements RunDriver {
|
|
5
|
+
readonly name = "kernel";
|
|
6
|
+
run(journey: Journey): Promise<RunRecord>;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=kernel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kernel.d.ts","sourceRoot":"","sources":["../../src/drivers/kernel.ts"],"names":[],"mappings":"AAkCA,OAAO,KAAK,EAAE,OAAO,EAAsB,MAAM,oBAAoB,CAAC;AACtE,OAAO,EAIL,KAAK,SAAS,EACf,MAAM,mBAAmB,CAAC;AAM3B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAqB5C,qBAAa,YAAa,YAAW,SAAS;IAC5C,QAAQ,CAAC,IAAI,YAAY;IAEnB,GAAG,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC,CAwO9C;CACF"}
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Kernel driver (§12) — the ONLY driver allowed to touch `ExecutionSession`;
|
|
3
|
+
* its recorded stream is the oracle every other surface's driver diffs
|
|
4
|
+
* against (§7, §12).
|
|
5
|
+
*
|
|
6
|
+
* Runs a journey's scripted `interactions` against a real `ExecutionSession`
|
|
7
|
+
* over a fresh, fully-hermetic registry (`registry.ts`: real base nodes +
|
|
8
|
+
* the harness's own fixture nodes). The bridge factory is
|
|
9
|
+
* `journeyPythonBridgeFactory` (`python-bridge.ts`, task D3) — a real Python
|
|
10
|
+
* worker is never spawned; a graph with an unresolved node type (journey 7,
|
|
11
|
+
* `python-node-workflow`) gets E2's faithful stdio fake instead, everything
|
|
12
|
+
* else gets no bridge at all (`connectPythonBridgeForGraph` only spawns when
|
|
13
|
+
* the graph actually needs one), so this driver stays hermetic either way.
|
|
14
|
+
* Every emitted
|
|
15
|
+
* `ProcessingMessage` is recorded as a `server_to_client` frame. The kernel
|
|
16
|
+
* has no wire, so `pushInput`/`cancel` are in-process method calls, not real
|
|
17
|
+
* frames — but this driver still records a synthetic `client_to_server`
|
|
18
|
+
* envelope (same `{command, data}` shape the ws-server/packaged drivers send
|
|
19
|
+
* over the wire) for each one, purely so surface-agnostic invariant checks
|
|
20
|
+
* that key off command intent (e.g. `terminal-uniqueness`'s
|
|
21
|
+
* `hasCancelRequest`, which looks for a `cancel_job` command frame) see the
|
|
22
|
+
* same evidence on every surface. `compareJourney`'s cross-surface diff
|
|
23
|
+
* ignores this direction entirely (`onlyServerToClient` in `compare.ts`), so
|
|
24
|
+
* these synthetic frames can never cause a false divergence.
|
|
25
|
+
*/
|
|
26
|
+
import { randomUUID } from "node:crypto";
|
|
27
|
+
import { ExecutionSession } from "@nodetool-ai/execution";
|
|
28
|
+
import { createGraphNodeTypeResolver } from "@nodetool-ai/node-sdk";
|
|
29
|
+
import { ProcessingContext, listRegisteredProviderIds } from "@nodetool-ai/runtime";
|
|
30
|
+
import { InMemoryStorageAdapter } from "@nodetool-ai/storage";
|
|
31
|
+
import { makeFrame } from "../core/record.js";
|
|
32
|
+
import { AnchorWaiter } from "./anchors.js";
|
|
33
|
+
import { buildJourneyRegistry } from "./registry.js";
|
|
34
|
+
import { journeyPythonBridgeFactory } from "./python-bridge.js";
|
|
35
|
+
import { getInjectedHostStorage } from "../faults/host-faults.js";
|
|
36
|
+
import { RELIABILITY_FAULT_PROVIDER_ID } from "../faults/provider-faults.js";
|
|
37
|
+
async function pumpMessages(session, frames, waiter, nextSeq) {
|
|
38
|
+
for await (const message of session.messages) {
|
|
39
|
+
frames.push(makeFrame(nextSeq(), "kernel", "server_to_client", message));
|
|
40
|
+
waiter.notify(message);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export class KernelDriver {
|
|
44
|
+
name = "kernel";
|
|
45
|
+
async run(journey) {
|
|
46
|
+
const registry = buildJourneyRegistry();
|
|
47
|
+
const frames = [];
|
|
48
|
+
let seq = 0;
|
|
49
|
+
const waiter = new AnchorWaiter();
|
|
50
|
+
let session = null;
|
|
51
|
+
let pump = null;
|
|
52
|
+
const interactions = journey.interactions.length > 0 ? journey.interactions : [{ action: "run" }];
|
|
53
|
+
for (const interaction of interactions) {
|
|
54
|
+
if (interaction.at) {
|
|
55
|
+
// Registering the waiter here — synchronously, with no `await`
|
|
56
|
+
// between a prior "run"'s `pump = pumpMessages(...)` call and this
|
|
57
|
+
// line — is what keeps this race-free (see anchors.ts's doc comment).
|
|
58
|
+
await waiter.wait(interaction.at);
|
|
59
|
+
}
|
|
60
|
+
switch (interaction.action) {
|
|
61
|
+
case "run": {
|
|
62
|
+
// A5 hydration-gap fix (docs/RELIABILITY_TASKS.md Track A):
|
|
63
|
+
// connect the bridge here (not inside `ExecutionSession.create`)
|
|
64
|
+
// so its discovered metadata can back a `resolveNodeType` fallback
|
|
65
|
+
// — the same shape `websocket-client-session.ts`'s ws-server driver
|
|
66
|
+
// gets via `createTestUiServer`'s `resolveUnknownNodeType`. Without
|
|
67
|
+
// `propertyTypes`/`outputs` resolved, the oracle surface can't tell
|
|
68
|
+
// a genuine multi-edge list-typed fan-in from an invalid non-list
|
|
69
|
+
// one (correlation analysis rejects both identically when
|
|
70
|
+
// `propertyTypes` is absent) — a real cross-surface divergence this
|
|
71
|
+
// journey manifest used to work around with distinct handles
|
|
72
|
+
// instead of a shared list handle. `ExecutionSession` still owns
|
|
73
|
+
// closing this bridge (its `bridgeFactory` just hands back the
|
|
74
|
+
// instance already connected here, never reconnecting).
|
|
75
|
+
const workflowNodes = (journey.workflow
|
|
76
|
+
.nodes ?? []);
|
|
77
|
+
const bridge = await journeyPythonBridgeFactory(workflowNodes, (t) => registry.has(t));
|
|
78
|
+
const baseResolver = createGraphNodeTypeResolver(registry);
|
|
79
|
+
const resolveNodeType = async (nodeType) => {
|
|
80
|
+
const resolved = await baseResolver.resolveNodeType(nodeType);
|
|
81
|
+
if (resolved)
|
|
82
|
+
return resolved;
|
|
83
|
+
// Mirrors the ws-server driver's `resolveUnknownNodeType`
|
|
84
|
+
// exactly: real bridge metadata when the bridge knows the type,
|
|
85
|
+
// else a permissive generic descriptor — never `null`. Returning
|
|
86
|
+
// `null` here would make `Graph.loadFromDict` silently DROP the
|
|
87
|
+
// node (its default `skipErrors: true`) instead of letting it
|
|
88
|
+
// reach `resolveExecutor`/execution, where an unresolvable or
|
|
89
|
+
// fault-injected bridge node is actually supposed to fail.
|
|
90
|
+
const meta = bridge?.hasNodeType(nodeType)
|
|
91
|
+
? bridge.getNodeMetadata().find((m) => m.node_type === nodeType)
|
|
92
|
+
: undefined;
|
|
93
|
+
if (meta) {
|
|
94
|
+
return {
|
|
95
|
+
nodeType,
|
|
96
|
+
propertyTypes: Object.fromEntries(meta.properties.map((p) => [p.name, p.type.type])),
|
|
97
|
+
outputs: Object.fromEntries(meta.outputs.map((o) => [o.name, o.type.type])),
|
|
98
|
+
supportsDynamicInputs: false,
|
|
99
|
+
descriptorDefaults: {}
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
nodeType,
|
|
104
|
+
propertyTypes: { value: "any" },
|
|
105
|
+
outputs: { out: "any" },
|
|
106
|
+
supportsDynamicInputs: true,
|
|
107
|
+
descriptorDefaults: {}
|
|
108
|
+
};
|
|
109
|
+
};
|
|
110
|
+
const sessionOptions = {
|
|
111
|
+
graph: journey.workflow,
|
|
112
|
+
registry,
|
|
113
|
+
bridgeFactory: async () => bridge,
|
|
114
|
+
workflowId: journey.manifest.name,
|
|
115
|
+
params: journey.manifest.params,
|
|
116
|
+
resolveNodeType,
|
|
117
|
+
// §12: "strict mode is a kernel flag... the harness always sets
|
|
118
|
+
// it" — the kernel driver is the oracle surface, so its advisory
|
|
119
|
+
// checks (pending inbox work, pending control responses) are
|
|
120
|
+
// always thrown violations, not log warnings.
|
|
121
|
+
strict: true,
|
|
122
|
+
// This driver is a custom-provider host: journeys wire an LLM
|
|
123
|
+
// node to `reliability-fault-llm`, which `provider-faults.ts`
|
|
124
|
+
// registers process-wide only while a provider fault is active.
|
|
125
|
+
// The run preflight would otherwise refuse every journey that
|
|
126
|
+
// names it with no fault applied — which is how the
|
|
127
|
+
// unregistered-fault-name case reports, so the harness could no
|
|
128
|
+
// longer report it. Declaring the catalog keeps a typo'd provider
|
|
129
|
+
// an error while letting the fault id through; model ids are
|
|
130
|
+
// fixtures with no offline catalog, so they stay unchecked.
|
|
131
|
+
catalogs: {
|
|
132
|
+
listProviderIds: () => [
|
|
133
|
+
...listRegisteredProviderIds(),
|
|
134
|
+
RELIABILITY_FAULT_PROVIDER_ID
|
|
135
|
+
],
|
|
136
|
+
listModelIds: () => undefined
|
|
137
|
+
},
|
|
138
|
+
// Journeys are hermetic: the fault provider needs no credential,
|
|
139
|
+
// and no journey may depend on a real key being present.
|
|
140
|
+
providerConfiguration: () => [],
|
|
141
|
+
// This driver records the message stream frame by frame
|
|
142
|
+
// (`pumpMessages` below), so it's one of the few callers that
|
|
143
|
+
// actually drains `session.messages` — capture is opt-in exactly
|
|
144
|
+
// so hosts that only await `result` don't queue messages unread.
|
|
145
|
+
captureMessages: true
|
|
146
|
+
};
|
|
147
|
+
// Every kernel run gets a working (in-memory, hermetic) storage
|
|
148
|
+
// adapter — `ExecutionSession`'s own default context wires none at
|
|
149
|
+
// all, but a journey like `host-disk-full-write` (task D3) needs
|
|
150
|
+
// one to write through on its happy-path run before the fault
|
|
151
|
+
// matrix below swaps it for an ENOSPC-throwing one
|
|
152
|
+
// (`faults/host-faults.ts`'s `host-disk-full`,
|
|
153
|
+
// {@link getInjectedHostStorage}). No shipped journey before this
|
|
154
|
+
// one wrote an asset, so giving every run a real (if unused)
|
|
155
|
+
// adapter instead of `null` changes nothing else.
|
|
156
|
+
const jobId = randomUUID();
|
|
157
|
+
sessionOptions.jobId = jobId;
|
|
158
|
+
sessionOptions.context = new ProcessingContext({
|
|
159
|
+
jobId,
|
|
160
|
+
workflowId: journey.manifest.name,
|
|
161
|
+
userId: "1",
|
|
162
|
+
storage: getInjectedHostStorage() ?? new InMemoryStorageAdapter()
|
|
163
|
+
});
|
|
164
|
+
session = await ExecutionSession.create(sessionOptions);
|
|
165
|
+
pump = pumpMessages(session, frames, waiter, () => seq++);
|
|
166
|
+
break;
|
|
167
|
+
}
|
|
168
|
+
case "cancel": {
|
|
169
|
+
if (!session) {
|
|
170
|
+
throw new Error(`journey "${journey.manifest.name}": "cancel" interaction before "run"`);
|
|
171
|
+
}
|
|
172
|
+
const reason = typeof interaction.value === "string" ? interaction.value : "journey-cancel";
|
|
173
|
+
frames.push(makeFrame(seq++, "kernel", "client_to_server", {
|
|
174
|
+
command: "cancel_job",
|
|
175
|
+
data: { job_id: session.jobId, reason }
|
|
176
|
+
}));
|
|
177
|
+
session.cancel(reason);
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
case "stream_input": {
|
|
181
|
+
if (!session) {
|
|
182
|
+
throw new Error(`journey "${journey.manifest.name}": "stream_input" interaction before "run"`);
|
|
183
|
+
}
|
|
184
|
+
if (!interaction.nodeId) {
|
|
185
|
+
throw new Error(`journey "${journey.manifest.name}": "stream_input" interaction needs nodeId`);
|
|
186
|
+
}
|
|
187
|
+
frames.push(makeFrame(seq++, "kernel", "client_to_server", {
|
|
188
|
+
command: "stream_input",
|
|
189
|
+
data: { job_id: session.jobId, input: interaction.nodeId, value: interaction.value }
|
|
190
|
+
}));
|
|
191
|
+
await session.pushInput(interaction.nodeId, interaction.value);
|
|
192
|
+
break;
|
|
193
|
+
}
|
|
194
|
+
case "end_input_stream": {
|
|
195
|
+
if (!session) {
|
|
196
|
+
throw new Error(`journey "${journey.manifest.name}": "end_input_stream" interaction before "run"`);
|
|
197
|
+
}
|
|
198
|
+
if (!interaction.nodeId) {
|
|
199
|
+
throw new Error(`journey "${journey.manifest.name}": "end_input_stream" interaction needs nodeId`);
|
|
200
|
+
}
|
|
201
|
+
frames.push(makeFrame(seq++, "kernel", "client_to_server", {
|
|
202
|
+
command: "end_input_stream",
|
|
203
|
+
data: { job_id: session.jobId, input: interaction.nodeId }
|
|
204
|
+
}));
|
|
205
|
+
session.finishInputStream(interaction.nodeId);
|
|
206
|
+
break;
|
|
207
|
+
}
|
|
208
|
+
case "reconnect":
|
|
209
|
+
// The kernel has no transport to drop/reconnect — this surface has
|
|
210
|
+
// nothing to exercise for a reconnect interaction.
|
|
211
|
+
throw new Error(`journey "${journey.manifest.name}": kernel driver does not support ` +
|
|
212
|
+
`the "reconnect" interaction (no transport)`);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
if (!session) {
|
|
216
|
+
throw new Error(`journey "${journey.manifest.name}" has no "run" interaction`);
|
|
217
|
+
}
|
|
218
|
+
const result = await session.result;
|
|
219
|
+
if (pump)
|
|
220
|
+
await pump;
|
|
221
|
+
// §6 "Cleanup and leaks": measured from the session itself
|
|
222
|
+
// (`ExecutionSession.resourceCounters`), not inferred. The kernel driver
|
|
223
|
+
// owns no WS slots, so those two are structurally zero here — the
|
|
224
|
+
// ws-server driver is where they carry information.
|
|
225
|
+
const counters = {
|
|
226
|
+
at: "after",
|
|
227
|
+
...session.resourceCounters(),
|
|
228
|
+
activeJobs: 0,
|
|
229
|
+
startingJobs: 0
|
|
230
|
+
};
|
|
231
|
+
return {
|
|
232
|
+
journeyId: journey.manifest.name,
|
|
233
|
+
surface: this.name,
|
|
234
|
+
jobId: session.jobId,
|
|
235
|
+
workflowId: session.workflowId,
|
|
236
|
+
startedAt: frames.length > 0 ? frames[0].ts : null,
|
|
237
|
+
finishedAt: frames.length > 0 ? frames[frames.length - 1].ts : null,
|
|
238
|
+
durationMs: null,
|
|
239
|
+
status: result.status,
|
|
240
|
+
error: result.error ?? null,
|
|
241
|
+
params: journey.manifest.params,
|
|
242
|
+
frames,
|
|
243
|
+
resourceCounters: [counters]
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
//# sourceMappingURL=kernel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kernel.js","sourceRoot":"","sources":["../../src/drivers/kernel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EACL,gBAAgB,EAGjB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AACpF,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAE9D,OAAO,EACL,SAAS,EAIV,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAChE,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,6BAA6B,EAAE,MAAM,8BAA8B,CAAC;AAG7E,KAAK,UAAU,YAAY,CACzB,OAAyB,EACzB,MAAkB,EAClB,MAAoB,EACpB,OAAqB;IAErB,IAAI,KAAK,EAAE,MAAM,OAAO,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QAC7C,MAAM,CAAC,IAAI,CACT,SAAS,CACP,OAAO,EAAE,EACT,QAAQ,EACR,kBAAkB,EAClB,OAA6C,CAC9C,CACF,CAAC;QACF,MAAM,CAAC,MAAM,CAAC,OAA6C,CAAC,CAAC;IAC/D,CAAC;AACH,CAAC;AAED,MAAM,OAAO,YAAY;IACd,IAAI,GAAG,QAAQ,CAAC;IAEzB,KAAK,CAAC,GAAG,CAAC,OAAgB;QACxB,MAAM,QAAQ,GAAG,oBAAoB,EAAE,CAAC;QACxC,MAAM,MAAM,GAAe,EAAE,CAAC;QAC9B,IAAI,GAAG,GAAG,CAAC,CAAC;QACZ,MAAM,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;QAClC,IAAI,OAAO,GAA4B,IAAI,CAAC;QAC5C,IAAI,IAAI,GAAyB,IAAI,CAAC;QAEtC,MAAM,YAAY,GAChB,OAAO,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;QAE/E,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE,CAAC;YACvC,IAAI,WAAW,CAAC,EAAE,EAAE,CAAC;gBACnB,+DAA+D;gBAC/D,mEAAmE;gBACnE,sEAAsE;gBACtE,MAAM,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;YACpC,CAAC;YAED,QAAQ,WAAW,CAAC,MAAM,EAAE,CAAC;gBAC3B,KAAK,KAAK,EAAE,CAAC;oBACX,4DAA4D;oBAC5D,iEAAiE;oBACjE,mEAAmE;oBACnE,oEAAoE;oBACpE,oEAAoE;oBACpE,oEAAoE;oBACpE,kEAAkE;oBAClE,0DAA0D;oBAC1D,oEAAoE;oBACpE,6DAA6D;oBAC7D,iEAAiE;oBACjE,+DAA+D;oBAC/D,wDAAwD;oBACxD,MAAM,aAAa,GAAG,CAAE,OAAO,CAAC,QAAgC;yBAC7D,KAAK,IAAI,EAAE,CAAsC,CAAC;oBACrD,MAAM,MAAM,GAAG,MAAM,0BAA0B,CAAC,aAAa,EAAE,CAAC,CAAC,EAAE,EAAE,CACnE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAChB,CAAC;oBACF,MAAM,YAAY,GAAG,2BAA2B,CAAC,QAAQ,CAAC,CAAC;oBAC3D,MAAM,eAAe,GAAG,KAAK,EAAE,QAAgB,EAAE,EAAE;wBACjD,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;wBAC9D,IAAI,QAAQ;4BAAE,OAAO,QAAQ,CAAC;wBAC9B,0DAA0D;wBAC1D,gEAAgE;wBAChE,iEAAiE;wBACjE,gEAAgE;wBAChE,8DAA8D;wBAC9D,8DAA8D;wBAC9D,2DAA2D;wBAC3D,MAAM,IAAI,GAAG,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC;4BACxC,CAAC,CAAC,MAAM,CAAC,eAAe,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,QAAQ,CAAC;4BAChE,CAAC,CAAC,SAAS,CAAC;wBACd,IAAI,IAAI,EAAE,CAAC;4BACT,OAAO;gCACL,QAAQ;gCACR,aAAa,EAAE,MAAM,CAAC,WAAW,CAC/B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAClD;gCACD,OAAO,EAAE,MAAM,CAAC,WAAW,CACzB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAC/C;gCACD,qBAAqB,EAAE,KAAK;gCAC5B,kBAAkB,EAAE,EAAE;6BACvB,CAAC;wBACJ,CAAC;wBACD,OAAO;4BACL,QAAQ;4BACR,aAAa,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE;4BAC/B,OAAO,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE;4BACvB,qBAAqB,EAAE,IAAI;4BAC3B,kBAAkB,EAAE,EAAE;yBACvB,CAAC;oBACJ,CAAC,CAAC;oBAEF,MAAM,cAAc,GAA4B;wBAC9C,KAAK,EAAE,OAAO,CAAC,QAAoC;wBACnD,QAAQ;wBACR,aAAa,EAAE,KAAK,IAAI,EAAE,CAAC,MAAM;wBACjC,UAAU,EAAE,OAAO,CAAC,QAAQ,CAAC,IAAI;wBACjC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,MAAM;wBAC/B,eAAe;wBACf,gEAAgE;wBAChE,iEAAiE;wBACjE,6DAA6D;wBAC7D,8CAA8C;wBAC9C,MAAM,EAAE,IAAI;wBACZ,8DAA8D;wBAC9D,8DAA8D;wBAC9D,gEAAgE;wBAChE,8DAA8D;wBAC9D,oDAAoD;wBACpD,gEAAgE;wBAChE,kEAAkE;wBAClE,6DAA6D;wBAC7D,4DAA4D;wBAC5D,QAAQ,EAAE;4BACR,eAAe,EAAE,GAAG,EAAE,CAAC;gCACrB,GAAG,yBAAyB,EAAE;gCAC9B,6BAA6B;6BAC9B;4BACD,YAAY,EAAE,GAAG,EAAE,CAAC,SAAS;yBAC9B;wBACD,iEAAiE;wBACjE,yDAAyD;wBACzD,qBAAqB,EAAE,GAAG,EAAE,CAAC,EAAE;wBAC/B,wDAAwD;wBACxD,8DAA8D;wBAC9D,iEAAiE;wBACjE,iEAAiE;wBACjE,eAAe,EAAE,IAAI;qBACtB,CAAC;oBACF,gEAAgE;oBAChE,mEAAmE;oBACnE,iEAAiE;oBACjE,8DAA8D;oBAC9D,mDAAmD;oBACnD,+CAA+C;oBAC/C,kEAAkE;oBAClE,6DAA6D;oBAC7D,kDAAkD;oBAClD,MAAM,KAAK,GAAG,UAAU,EAAE,CAAC;oBAC3B,cAAc,CAAC,KAAK,GAAG,KAAK,CAAC;oBAC7B,cAAc,CAAC,OAAO,GAAG,IAAI,iBAAiB,CAAC;wBAC7C,KAAK;wBACL,UAAU,EAAE,OAAO,CAAC,QAAQ,CAAC,IAAI;wBACjC,MAAM,EAAE,GAAG;wBACX,OAAO,EAAE,sBAAsB,EAAE,IAAI,IAAI,sBAAsB,EAAE;qBAClE,CAAC,CAAC;oBACH,OAAO,GAAG,MAAM,gBAAgB,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;oBACxD,IAAI,GAAG,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC;oBAC1D,MAAM;gBACR,CAAC;gBACD,KAAK,QAAQ,EAAE,CAAC;oBACd,IAAI,CAAC,OAAO,EAAE,CAAC;wBACb,MAAM,IAAI,KAAK,CACb,YAAY,OAAO,CAAC,QAAQ,CAAC,IAAI,sCAAsC,CACxE,CAAC;oBACJ,CAAC;oBACD,MAAM,MAAM,GACV,OAAO,WAAW,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,gBAAgB,CAAC;oBAC/E,MAAM,CAAC,IAAI,CACT,SAAS,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,kBAAkB,EAAE;wBAC7C,OAAO,EAAE,YAAY;wBACrB,IAAI,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE;qBACxC,CAAC,CACH,CAAC;oBACF,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;oBACvB,MAAM;gBACR,CAAC;gBACD,KAAK,cAAc,EAAE,CAAC;oBACpB,IAAI,CAAC,OAAO,EAAE,CAAC;wBACb,MAAM,IAAI,KAAK,CACb,YAAY,OAAO,CAAC,QAAQ,CAAC,IAAI,4CAA4C,CAC9E,CAAC;oBACJ,CAAC;oBACD,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC;wBACxB,MAAM,IAAI,KAAK,CACb,YAAY,OAAO,CAAC,QAAQ,CAAC,IAAI,4CAA4C,CAC9E,CAAC;oBACJ,CAAC;oBACD,MAAM,CAAC,IAAI,CACT,SAAS,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,kBAAkB,EAAE;wBAC7C,OAAO,EAAE,cAAc;wBACvB,IAAI,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,KAAK,EAAE,WAAW,CAAC,KAAK,EAAE;qBACrF,CAAC,CACH,CAAC;oBACF,MAAM,OAAO,CAAC,SAAS,CAAC,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC;oBAC/D,MAAM;gBACR,CAAC;gBACD,KAAK,kBAAkB,EAAE,CAAC;oBACxB,IAAI,CAAC,OAAO,EAAE,CAAC;wBACb,MAAM,IAAI,KAAK,CACb,YAAY,OAAO,CAAC,QAAQ,CAAC,IAAI,gDAAgD,CAClF,CAAC;oBACJ,CAAC;oBACD,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC;wBACxB,MAAM,IAAI,KAAK,CACb,YAAY,OAAO,CAAC,QAAQ,CAAC,IAAI,gDAAgD,CAClF,CAAC;oBACJ,CAAC;oBACD,MAAM,CAAC,IAAI,CACT,SAAS,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,kBAAkB,EAAE;wBAC7C,OAAO,EAAE,kBAAkB;wBAC3B,IAAI,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE;qBAC3D,CAAC,CACH,CAAC;oBACF,OAAO,CAAC,iBAAiB,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;oBAC9C,MAAM;gBACR,CAAC;gBACD,KAAK,WAAW;oBACd,mEAAmE;oBACnE,mDAAmD;oBACnD,MAAM,IAAI,KAAK,CACb,YAAY,OAAO,CAAC,QAAQ,CAAC,IAAI,oCAAoC;wBACnE,4CAA4C,CAC/C,CAAC;YACN,CAAC;QACH,CAAC;QAED,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,YAAY,OAAO,CAAC,QAAQ,CAAC,IAAI,4BAA4B,CAAC,CAAC;QACjF,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC;QACpC,IAAI,IAAI;YAAE,MAAM,IAAI,CAAC;QAErB,2DAA2D;QAC3D,yEAAyE;QACzE,kEAAkE;QAClE,oDAAoD;QACpD,MAAM,QAAQ,GAA4B;YACxC,EAAE,EAAE,OAAO;YACX,GAAG,OAAO,CAAC,gBAAgB,EAAE;YAC7B,UAAU,EAAE,CAAC;YACb,YAAY,EAAE,CAAC;SAChB,CAAC;QAEF,OAAO;YACL,SAAS,EAAE,OAAO,CAAC,QAAQ,CAAC,IAAI;YAChC,OAAO,EAAE,IAAI,CAAC,IAAI;YAClB,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,SAAS,EAAE,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI;YAClD,UAAU,EAAE,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI;YACnE,UAAU,EAAE,IAAI;YAChB,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,IAAI;YAC3B,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,MAAM;YAC/B,MAAM;YACN,gBAAgB,EAAE,CAAC,QAAQ,CAAC;SAC7B,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Journey } from "../core/journey.js";
|
|
2
|
+
import { type RunRecord } from "../core/record.js";
|
|
3
|
+
import type { RunDriver } from "./types.js";
|
|
4
|
+
/**
|
|
5
|
+
* Stages the backend bundle via the exact entry point `npm run backend:smoke`
|
|
6
|
+
* uses (`npm run prepare-backend --workspace=electron`, i.e.
|
|
7
|
+
* `scripts/bundle-backend.mjs`). Expensive (minutes) — call once per journey
|
|
8
|
+
* session, not per journey.
|
|
9
|
+
*/
|
|
10
|
+
export declare function stageBackendBundle(repoRoot?: string): Promise<string>;
|
|
11
|
+
export interface PackagedDriverOptions {
|
|
12
|
+
/** Staged bundle dir; defaults to `<repoRoot>/electron/backend-bundle`. */
|
|
13
|
+
bundleDir?: string;
|
|
14
|
+
/** Node binary to boot `server.mjs` with; defaults to the bundle's own
|
|
15
|
+
* staged `runtime/node` when present, else the current interpreter. */
|
|
16
|
+
nodeBinary?: string;
|
|
17
|
+
/** How long to wait for `/health` before giving up, ms. */
|
|
18
|
+
healthTimeoutMs?: number;
|
|
19
|
+
}
|
|
20
|
+
export declare class PackagedDriver implements RunDriver {
|
|
21
|
+
private readonly options;
|
|
22
|
+
readonly name = "packaged";
|
|
23
|
+
constructor(options?: PackagedDriverOptions);
|
|
24
|
+
/** True when a bundle is staged at the configured (or default) location. */
|
|
25
|
+
isStaged(): boolean;
|
|
26
|
+
run(journey: Journey): Promise<RunRecord>;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=packaged.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"packaged.d.ts","sourceRoot":"","sources":["../../src/drivers/packaged.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,OAAO,EAAsB,MAAM,oBAAoB,CAAC;AACtE,OAAO,EAA4B,KAAK,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAI7E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAmB5C;;;;;GAKG;AACH,wBAAsB,kBAAkB,CAAC,QAAQ,GAAE,MAAuB,GAAG,OAAO,CAAC,MAAM,CAAC,CAa3F;AAuHD,MAAM,WAAW,qBAAqB;IACpC,2EAA2E;IAC3E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;2EACuE;IACvE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2DAA2D;IAC3D,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,qBAAa,cAAe,YAAW,SAAS;IAGlC,OAAO,CAAC,QAAQ,CAAC,OAAO;IAFpC,QAAQ,CAAC,IAAI,cAAc;IAE3B,YAA6B,OAAO,GAAE,qBAA0B,EAAI;IAEpE,4EAA4E;IAC5E,QAAQ,IAAI,OAAO,CAGlB;IAEK,GAAG,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC,CA0J9C;CACF"}
|