@glubean/runner 0.5.0 → 0.8.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.
- package/dist/engine-bridge.d.ts +55 -0
- package/dist/engine-bridge.d.ts.map +1 -0
- package/dist/engine-bridge.js +219 -0
- package/dist/engine-bridge.js.map +1 -0
- package/dist/executor.d.ts +70 -2
- package/dist/executor.d.ts.map +1 -1
- package/dist/executor.js +21 -226
- package/dist/executor.js.map +1 -1
- package/dist/generate_summary.d.ts +15 -0
- package/dist/generate_summary.d.ts.map +1 -1
- package/dist/generate_summary.js +52 -1
- package/dist/generate_summary.js.map +1 -1
- package/dist/harness.js +257 -21
- package/dist/harness.js.map +1 -1
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -1
- package/dist/load/continuation-pool.d.ts +82 -0
- package/dist/load/continuation-pool.d.ts.map +1 -0
- package/dist/load/continuation-pool.js +154 -0
- package/dist/load/continuation-pool.js.map +1 -0
- package/dist/load/execute-iteration.d.ts +126 -0
- package/dist/load/execute-iteration.d.ts.map +1 -0
- package/dist/load/execute-iteration.js +367 -0
- package/dist/load/execute-iteration.js.map +1 -0
- package/dist/load/histogram.d.ts +63 -0
- package/dist/load/histogram.d.ts.map +1 -0
- package/dist/load/histogram.js +149 -0
- package/dist/load/histogram.js.map +1 -0
- package/dist/load/orchestrator.d.ts +55 -0
- package/dist/load/orchestrator.d.ts.map +1 -0
- package/dist/load/orchestrator.js +571 -0
- package/dist/load/orchestrator.js.map +1 -0
- package/dist/load/reducer.d.ts +109 -0
- package/dist/load/reducer.d.ts.map +1 -0
- package/dist/load/reducer.js +718 -0
- package/dist/load/reducer.js.map +1 -0
- package/dist/load/route-key.d.ts +38 -0
- package/dist/load/route-key.d.ts.map +1 -0
- package/dist/load/route-key.js +107 -0
- package/dist/load/route-key.js.map +1 -0
- package/dist/load/samples.d.ts +83 -0
- package/dist/load/samples.d.ts.map +1 -0
- package/dist/load/samples.js +269 -0
- package/dist/load/samples.js.map +1 -0
- package/dist/load/sink.d.ts +127 -0
- package/dist/load/sink.d.ts.map +1 -0
- package/dist/load/sink.js +351 -0
- package/dist/load/sink.js.map +1 -0
- package/dist/load/subprocess.d.ts +83 -0
- package/dist/load/subprocess.d.ts.map +1 -0
- package/dist/load/subprocess.js +229 -0
- package/dist/load/subprocess.js.map +1 -0
- package/dist/load/threshold.d.ts +44 -0
- package/dist/load/threshold.d.ts.map +1 -0
- package/dist/load/threshold.js +197 -0
- package/dist/load/threshold.js.map +1 -0
- package/dist/load/timeline.d.ts +36 -0
- package/dist/load/timeline.d.ts.map +1 -0
- package/dist/load/timeline.js +158 -0
- package/dist/load/timeline.js.map +1 -0
- package/dist/load-harness.d.ts +2 -0
- package/dist/load-harness.d.ts.map +1 -0
- package/dist/load-harness.js +105 -0
- package/dist/load-harness.js.map +1 -0
- package/dist/resolve.d.ts +10 -11
- package/dist/resolve.d.ts.map +1 -1
- package/dist/resolve.js +28 -9
- package/dist/resolve.js.map +1 -1
- package/dist/runner-resolve.d.ts +53 -0
- package/dist/runner-resolve.d.ts.map +1 -0
- package/dist/runner-resolve.js +264 -0
- package/dist/runner-resolve.js.map +1 -0
- package/dist/workflow/event-timeline.d.ts +3 -0
- package/dist/workflow/event-timeline.d.ts.map +1 -0
- package/dist/workflow/event-timeline.js +72 -0
- package/dist/workflow/event-timeline.js.map +1 -0
- package/dist/workflow/execute.d.ts +267 -0
- package/dist/workflow/execute.d.ts.map +1 -0
- package/dist/workflow/execute.js +1475 -0
- package/dist/workflow/execute.js.map +1 -0
- package/package.json +8 -4
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Streaming over-time series for the load reducer.
|
|
3
|
+
*
|
|
4
|
+
* Buckets the run into fixed-width windows (from run start) so a consumer can draw the
|
|
5
|
+
* classic load curves: RPS, error-rate, latency percentiles, and concurrency vs time.
|
|
6
|
+
* Memory is bounded: windows start at `baseWindowMs` and, once they would exceed
|
|
7
|
+
* `maxWindows`, the width is DOUBLED and adjacent windows merged pairwise — so an
|
|
8
|
+
* arbitrarily long run keeps at most `maxWindows` windows. Each window keeps a bounded
|
|
9
|
+
* `LoadHistogram` for its latency percentiles (mergeable, so coarsening folds cleanly).
|
|
10
|
+
*/
|
|
11
|
+
import { LoadHistogram } from "./histogram.js";
|
|
12
|
+
const ZERO_PCT = { p50: 0, p90: 0, p95: 0, p99: 0, max: 0 };
|
|
13
|
+
function newWindow() {
|
|
14
|
+
return { requests: 0, errors: 0, latency: new LoadHistogram(), starts: 0, iterations: 0, peakSample: 0 };
|
|
15
|
+
}
|
|
16
|
+
export class LoadTimeline {
|
|
17
|
+
baseWindowMs;
|
|
18
|
+
maxWindows;
|
|
19
|
+
windowMs;
|
|
20
|
+
// Sparse: only windows with activity exist; finalize() fills the gaps with zeros so the
|
|
21
|
+
// emitted series is dense (a contiguous x-axis).
|
|
22
|
+
windows = new Map();
|
|
23
|
+
/** @param baseWindowMs initial window width (ms). @param maxWindows coarsening cap. */
|
|
24
|
+
constructor(baseWindowMs = 250, maxWindows = 600) {
|
|
25
|
+
this.baseWindowMs = baseWindowMs;
|
|
26
|
+
this.maxWindows = maxWindows;
|
|
27
|
+
this.windowMs = baseWindowMs;
|
|
28
|
+
}
|
|
29
|
+
/** The window index covering `offsetMs` (ms from run start), coarsening first if the
|
|
30
|
+
* index would exceed the cap (so the series stays ≤ maxWindows). */
|
|
31
|
+
indexFor(offsetMs) {
|
|
32
|
+
let idx = Math.floor(Math.max(0, offsetMs) / this.windowMs);
|
|
33
|
+
while (idx >= this.maxWindows) {
|
|
34
|
+
this.coarsen();
|
|
35
|
+
idx = Math.floor(Math.max(0, offsetMs) / this.windowMs);
|
|
36
|
+
}
|
|
37
|
+
return idx;
|
|
38
|
+
}
|
|
39
|
+
/** The LAST window covered by a run of length `runEndMs` (the run spans [0, runEndMs)), or
|
|
40
|
+
* -1 for a non-positive length. A run ending exactly on a boundary (runEndMs = k·windowMs)
|
|
41
|
+
* covers windows 0..k-1, NOT a window that starts at the run end (codex). Coarsens so the
|
|
42
|
+
* index fits the cap. */
|
|
43
|
+
runEndIndex(runEndMs) {
|
|
44
|
+
if (runEndMs <= 0)
|
|
45
|
+
return -1;
|
|
46
|
+
while (Math.ceil(runEndMs / this.windowMs) - 1 >= this.maxWindows)
|
|
47
|
+
this.coarsen();
|
|
48
|
+
return Math.ceil(runEndMs / this.windowMs) - 1;
|
|
49
|
+
}
|
|
50
|
+
/** The window covering `offsetMs`, creating it if absent. */
|
|
51
|
+
windowFor(offsetMs) {
|
|
52
|
+
const idx = this.indexFor(offsetMs);
|
|
53
|
+
let w = this.windows.get(idx);
|
|
54
|
+
if (w === undefined) {
|
|
55
|
+
w = newWindow();
|
|
56
|
+
this.windows.set(idx, w);
|
|
57
|
+
}
|
|
58
|
+
return w;
|
|
59
|
+
}
|
|
60
|
+
/** Double the window width and merge each adjacent pair (2k, 2k+1 → k). All folds are
|
|
61
|
+
* commutative (sum / max / histogram merge), so Map iteration order is irrelevant. */
|
|
62
|
+
coarsen() {
|
|
63
|
+
const next = new Map();
|
|
64
|
+
for (const [i, w] of this.windows) {
|
|
65
|
+
const ni = Math.floor(i / 2);
|
|
66
|
+
const existing = next.get(ni);
|
|
67
|
+
if (existing === undefined) {
|
|
68
|
+
next.set(ni, w);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
existing.requests += w.requests;
|
|
72
|
+
existing.errors += w.errors;
|
|
73
|
+
existing.starts += w.starts;
|
|
74
|
+
existing.iterations += w.iterations;
|
|
75
|
+
if (w.peakSample > existing.peakSample)
|
|
76
|
+
existing.peakSample = w.peakSample;
|
|
77
|
+
existing.latency.merge(w.latency);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
this.windows = next;
|
|
81
|
+
this.windowMs *= 2;
|
|
82
|
+
}
|
|
83
|
+
/** Record one request observation at `offsetMs`. `inFlight` is the live iteration count
|
|
84
|
+
* at that moment — sampled so a window busy with requests (e.g. a poll) shows concurrency. */
|
|
85
|
+
recordRequest(offsetMs, durationMs, ok, inFlight) {
|
|
86
|
+
const w = this.windowFor(offsetMs);
|
|
87
|
+
w.requests += 1;
|
|
88
|
+
if (!ok)
|
|
89
|
+
w.errors += 1;
|
|
90
|
+
w.latency.record(durationMs);
|
|
91
|
+
if (inFlight > w.peakSample)
|
|
92
|
+
w.peakSample = inFlight;
|
|
93
|
+
}
|
|
94
|
+
/** Record one started iteration at `offsetMs`. `inFlight` is the live count just after the
|
|
95
|
+
* start (its local peak), sampled so even a same-window start+end shows its concurrency. */
|
|
96
|
+
recordIterationStart(offsetMs, inFlight) {
|
|
97
|
+
const w = this.windowFor(offsetMs);
|
|
98
|
+
w.starts += 1;
|
|
99
|
+
if (inFlight > w.peakSample)
|
|
100
|
+
w.peakSample = inFlight;
|
|
101
|
+
}
|
|
102
|
+
/** Record one completed iteration (iteration:end) at `offsetMs`. */
|
|
103
|
+
recordIterationEnd(offsetMs) {
|
|
104
|
+
this.windowFor(offsetMs).iterations += 1;
|
|
105
|
+
}
|
|
106
|
+
/** Emit the dense series: every window from 0..last, idle windows zero-filled. `runEndMs`
|
|
107
|
+
* (the run's `load:end` offset) extends the series to the actual run end, so a trailing
|
|
108
|
+
* idle / sustained-in-flight period after the last recorded event (an abort, drain timeout,
|
|
109
|
+
* or hung iteration) is still present instead of being truncated (codex). */
|
|
110
|
+
finalize(runEndMs = 0) {
|
|
111
|
+
if (this.windows.size === 0)
|
|
112
|
+
return { windowMs: this.windowMs, windows: [] };
|
|
113
|
+
// Extend to the last window the run actually covered (may coarsen existing windows).
|
|
114
|
+
let maxIdx = this.runEndIndex(runEndMs);
|
|
115
|
+
for (const i of this.windows.keys())
|
|
116
|
+
if (i > maxIdx)
|
|
117
|
+
maxIdx = i;
|
|
118
|
+
const windowSec = this.windowMs / 1000;
|
|
119
|
+
const windows = [];
|
|
120
|
+
// `carriedIn` = in-flight iterations ENTERING each window = Σ(starts − ends) through the
|
|
121
|
+
// PREVIOUS windows. The window's reported concurrency is max(its sampled peak, carriedIn):
|
|
122
|
+
// - the sampled peak catches intra-window concurrency the net would cancel (a short
|
|
123
|
+
// iteration that starts and ends in one window — even after coarsening);
|
|
124
|
+
// - carriedIn catches a long iteration spanning quiet/idle windows (sustained, not zero).
|
|
125
|
+
let carriedIn = 0;
|
|
126
|
+
for (let i = 0; i <= maxIdx; i++) {
|
|
127
|
+
const w = this.windows.get(i);
|
|
128
|
+
const peakInFlight = Math.max(0, w?.peakSample ?? 0, carriedIn);
|
|
129
|
+
if (w === undefined) {
|
|
130
|
+
windows.push({
|
|
131
|
+
offsetMs: i * this.windowMs,
|
|
132
|
+
requests: 0,
|
|
133
|
+
errors: 0,
|
|
134
|
+
errorRate: 0,
|
|
135
|
+
throughputPerSec: 0,
|
|
136
|
+
latency: ZERO_PCT,
|
|
137
|
+
iterations: 0,
|
|
138
|
+
peakInFlight,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
windows.push({
|
|
143
|
+
offsetMs: i * this.windowMs,
|
|
144
|
+
requests: w.requests,
|
|
145
|
+
errors: w.errors,
|
|
146
|
+
errorRate: w.requests > 0 ? w.errors / w.requests : 0,
|
|
147
|
+
throughputPerSec: windowSec > 0 ? w.requests / windowSec : 0,
|
|
148
|
+
latency: w.latency.count > 0 ? w.latency.percentiles() : ZERO_PCT,
|
|
149
|
+
iterations: w.iterations,
|
|
150
|
+
peakInFlight,
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
carriedIn += (w?.starts ?? 0) - (w?.iterations ?? 0);
|
|
154
|
+
}
|
|
155
|
+
return { windowMs: this.windowMs, windows };
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=timeline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timeline.js","sourceRoot":"","sources":["../../src/load/timeline.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load-harness.d.ts","sourceRoot":"","sources":["../src/load-harness.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Load harness — runs INSIDE the Node.js subprocess (spawned via tsx by
|
|
3
|
+
* `runLoadFileInSubprocess`). The load-execution counterpart to `harness.ts`.
|
|
4
|
+
*
|
|
5
|
+
* Because this harness and the user `.load.ts` file are loaded in the SAME
|
|
6
|
+
* process — and resolved through the SAME project-local runner — both halves
|
|
7
|
+
* co-resolve one `@glubean/sdk`, so `runLoad`'s engine carrier and the scenario's
|
|
8
|
+
* runtime carrier are identical (no split-brain).
|
|
9
|
+
*
|
|
10
|
+
* Protocol:
|
|
11
|
+
* stdin ← JSON `{ vars, secrets }` (raw; env fallback applied here)
|
|
12
|
+
* argv ← `--file=<absolute path to the .load.ts>`
|
|
13
|
+
* stdout → `WIRE_PREFIX`-tagged NDJSON `LoadHarnessMessage` lines: one
|
|
14
|
+
* `artifact` per completed plan, one `error` per import / plan-run
|
|
15
|
+
* failure, a terminal `done`. The prefix lets the parent tell protocol
|
|
16
|
+
* from ordinary user `console.log` (forwarded as-is); writes go through
|
|
17
|
+
* `writeSync(1, …)` so they flush before exit. A crash (no `done`) is
|
|
18
|
+
* surfaced by the parent from stderr.
|
|
19
|
+
*/
|
|
20
|
+
import { parseArgs } from "node:util";
|
|
21
|
+
import { writeSync } from "node:fs";
|
|
22
|
+
import { pathToFileURL } from "node:url";
|
|
23
|
+
import { bootstrap } from "./bootstrap.js";
|
|
24
|
+
import { runLoad } from "./load/orchestrator.js";
|
|
25
|
+
import { collectLoadPlans, withProcessEnvFallback, WIRE_PREFIX, } from "./load/subprocess.js";
|
|
26
|
+
/** Write one protocol message synchronously to stdout (fd 1, flush-safe). The
|
|
27
|
+
* LEADING newline guarantees the prefix begins a fresh line even when user /
|
|
28
|
+
* plugin code wrote to stdout WITHOUT a trailing newline (otherwise the message
|
|
29
|
+
* would be appended to that line and no longer start with the prefix). */
|
|
30
|
+
function emit(msg) {
|
|
31
|
+
writeSync(1, "\n" + WIRE_PREFIX + JSON.stringify(msg) + "\n");
|
|
32
|
+
}
|
|
33
|
+
/** Mark the harness done (terminal sentinel) and exit cleanly. */
|
|
34
|
+
function finishClean() {
|
|
35
|
+
emit({ type: "done" });
|
|
36
|
+
process.exit(0);
|
|
37
|
+
}
|
|
38
|
+
// A crash (uncaught error) is reported to stderr and exits nonzero WITHOUT a
|
|
39
|
+
// `done` sentinel — the parent detects the missing sentinel and surfaces the
|
|
40
|
+
// stderr text as a "did not complete" error, so nothing is silently lost.
|
|
41
|
+
function crash(message) {
|
|
42
|
+
process.stderr.write(message + "\n");
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
process.on("uncaughtException", (error) => {
|
|
46
|
+
crash(`load harness crashed: ${error?.stack ?? error?.message ?? String(error)}`);
|
|
47
|
+
});
|
|
48
|
+
process.on("unhandledRejection", (reason) => {
|
|
49
|
+
crash(`load harness crashed: ${reason instanceof Error ? (reason.stack ?? reason.message) : String(reason)}`);
|
|
50
|
+
});
|
|
51
|
+
const { values: args } = parseArgs({
|
|
52
|
+
args: process.argv.slice(2),
|
|
53
|
+
options: { file: { type: "string" } },
|
|
54
|
+
strict: false,
|
|
55
|
+
});
|
|
56
|
+
const file = args.file;
|
|
57
|
+
if (!file)
|
|
58
|
+
crash("load harness: missing required --file argument");
|
|
59
|
+
/** Read the full stdin payload (the `{ vars, secrets }` JSON). */
|
|
60
|
+
async function readStdin() {
|
|
61
|
+
const chunks = [];
|
|
62
|
+
for await (const chunk of process.stdin)
|
|
63
|
+
chunks.push(chunk);
|
|
64
|
+
return Buffer.concat(chunks).toString("utf-8");
|
|
65
|
+
}
|
|
66
|
+
const stdinRaw = await readStdin();
|
|
67
|
+
const { vars = {}, secrets = {} } = stdinRaw
|
|
68
|
+
? JSON.parse(stdinRaw)
|
|
69
|
+
: {};
|
|
70
|
+
// Register project plugins (matchers / protocol adapters) before importing the
|
|
71
|
+
// load file, which may use them — same as the test/contract paths.
|
|
72
|
+
await bootstrap(process.cwd());
|
|
73
|
+
let ns;
|
|
74
|
+
try {
|
|
75
|
+
// tsx (the spawning runtime) transforms full TypeScript; Node resolves the
|
|
76
|
+
// file's bare imports (`@glubean/sdk/load`) relative to the file's location.
|
|
77
|
+
ns = (await import(pathToFileURL(file).href));
|
|
78
|
+
}
|
|
79
|
+
catch (e) {
|
|
80
|
+
// A handled per-file failure (not a crash): emit the error + the done sentinel.
|
|
81
|
+
emit({
|
|
82
|
+
type: "error",
|
|
83
|
+
message: `failed to import load file ${file}: ${e instanceof Error ? e.message : String(e)} (ensure @glubean/sdk is resolvable from the file)`,
|
|
84
|
+
});
|
|
85
|
+
finishClean();
|
|
86
|
+
}
|
|
87
|
+
const envVars = withProcessEnvFallback(vars);
|
|
88
|
+
const envSecrets = withProcessEnvFallback(secrets);
|
|
89
|
+
for (const plan of collectLoadPlans(ns)) {
|
|
90
|
+
try {
|
|
91
|
+
// runLoad can throw for an invalid plan (traffic-mix, no termination bound,
|
|
92
|
+
// bad bounds) — report it per-plan and keep going so other plans' completed
|
|
93
|
+
// artifacts still emit.
|
|
94
|
+
const artifact = await runLoad(plan, { vars: envVars, secrets: envSecrets });
|
|
95
|
+
emit({ type: "artifact", runnerId: plan.id, artifact });
|
|
96
|
+
}
|
|
97
|
+
catch (e) {
|
|
98
|
+
emit({
|
|
99
|
+
type: "error",
|
|
100
|
+
message: `load plan "${plan.id}" (${file}) failed: ${e instanceof Error ? e.message : String(e)}`,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
finishClean();
|
|
105
|
+
//# sourceMappingURL=load-harness.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load-harness.js","sourceRoot":"","sources":["../src/load-harness.ts"],"names":[],"mappings":"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"}
|
package/dist/resolve.d.ts
CHANGED
|
@@ -54,23 +54,22 @@ export declare function isEachBuilder(obj: unknown): obj is {
|
|
|
54
54
|
build(): Test<unknown>[];
|
|
55
55
|
};
|
|
56
56
|
/**
|
|
57
|
-
* Type guard — check if a value is an un-built `
|
|
58
|
-
* (from `
|
|
57
|
+
* Type guard — check if a value is an un-built vNext `WorkflowBuilder`
|
|
58
|
+
* (from `workflow(id)...`).
|
|
59
59
|
*
|
|
60
|
-
* The builder carries `__glubean_type === "
|
|
61
|
-
* method that returns a `
|
|
60
|
+
* The builder carries `__glubean_type === "workflow-builder"` and a `build()`
|
|
61
|
+
* method that returns a `BuiltWorkflow` (a one-element `Test[]` that also
|
|
62
|
+
* carries the workflow IR fields).
|
|
62
63
|
*/
|
|
63
|
-
export declare function
|
|
64
|
-
__glubean_type: "
|
|
65
|
-
build(): Test<unknown>[]
|
|
66
|
-
_flow?: unknown;
|
|
67
|
-
};
|
|
64
|
+
export declare function isWorkflowBuilder(obj: unknown): obj is {
|
|
65
|
+
__glubean_type: "workflow-builder";
|
|
66
|
+
build(): Test<unknown>[];
|
|
68
67
|
};
|
|
69
68
|
/**
|
|
70
69
|
* If the value is a `TestBuilder`, call `.build()` to get a `Test`.
|
|
71
70
|
* If the value is an `EachBuilder`, call `.build()` to get a `Test[]`.
|
|
72
|
-
* If the value is a `
|
|
73
|
-
* (array-extending Test[]
|
|
71
|
+
* If the value is a vNext `WorkflowBuilder`, call `.build()` to get a
|
|
72
|
+
* `BuiltWorkflow` (array-extending Test[] carrying the workflow IR).
|
|
74
73
|
* Otherwise return as-is.
|
|
75
74
|
*/
|
|
76
75
|
export declare function autoResolve(value: unknown): unknown;
|
package/dist/resolve.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAMzC;;;;;;;;GAQG;AACH,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC;IACzB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAMD;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,CASzD;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,OAAO,GACX,GAAG,IAAI;IAAE,cAAc,EAAE,SAAS,CAAC;IAAC,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC,CAAA;CAAE,CAO9D;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,OAAO,GACX,GAAG,IAAI;IAAE,cAAc,EAAE,cAAc,CAAC;IAAC,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC,EAAE,CAAA;CAAE,CAOrE;AAED
|
|
1
|
+
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAMzC;;;;;;;;GAQG;AACH,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC;IACzB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAMD;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,CASzD;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,OAAO,GACX,GAAG,IAAI;IAAE,cAAc,EAAE,SAAS,CAAC;IAAC,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC,CAAA;CAAE,CAO9D;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,OAAO,GACX,GAAG,IAAI;IAAE,cAAc,EAAE,cAAc,CAAC;IAAC,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC,EAAE,CAAA;CAAE,CAOrE;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,OAAO,GACX,GAAG,IAAI;IACR,cAAc,EAAE,kBAAkB,CAAC;IACnC,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;CAC1B,CAOA;AAMD;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAKnD;AA2BD;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,YAAY,EAAE,CAQhB;AAuDD;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAC1B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,MAAM,EAAE,MAAM,GACb,IAAI,CAAC,OAAO,CAAC,GAAG,SAAS,CA2B3B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,IAAI,EAAE,MAAM,GACX,IAAI,CAAC,OAAO,CAAC,GAAG,SAAS,CA0B3B"}
|
package/dist/resolve.js
CHANGED
|
@@ -49,16 +49,17 @@ export function isEachBuilder(obj) {
|
|
|
49
49
|
typeof obj.build === "function");
|
|
50
50
|
}
|
|
51
51
|
/**
|
|
52
|
-
* Type guard — check if a value is an un-built `
|
|
53
|
-
* (from `
|
|
52
|
+
* Type guard — check if a value is an un-built vNext `WorkflowBuilder`
|
|
53
|
+
* (from `workflow(id)...`).
|
|
54
54
|
*
|
|
55
|
-
* The builder carries `__glubean_type === "
|
|
56
|
-
* method that returns a `
|
|
55
|
+
* The builder carries `__glubean_type === "workflow-builder"` and a `build()`
|
|
56
|
+
* method that returns a `BuiltWorkflow` (a one-element `Test[]` that also
|
|
57
|
+
* carries the workflow IR fields).
|
|
57
58
|
*/
|
|
58
|
-
export function
|
|
59
|
+
export function isWorkflowBuilder(obj) {
|
|
59
60
|
return (typeof obj === "object" &&
|
|
60
61
|
obj !== null &&
|
|
61
|
-
obj.__glubean_type === "
|
|
62
|
+
obj.__glubean_type === "workflow-builder" &&
|
|
62
63
|
typeof obj.build === "function");
|
|
63
64
|
}
|
|
64
65
|
// ---------------------------------------------------------------------------
|
|
@@ -67,8 +68,8 @@ export function isFlowBuilder(obj) {
|
|
|
67
68
|
/**
|
|
68
69
|
* If the value is a `TestBuilder`, call `.build()` to get a `Test`.
|
|
69
70
|
* If the value is an `EachBuilder`, call `.build()` to get a `Test[]`.
|
|
70
|
-
* If the value is a `
|
|
71
|
-
* (array-extending Test[]
|
|
71
|
+
* If the value is a vNext `WorkflowBuilder`, call `.build()` to get a
|
|
72
|
+
* `BuiltWorkflow` (array-extending Test[] carrying the workflow IR).
|
|
72
73
|
* Otherwise return as-is.
|
|
73
74
|
*/
|
|
74
75
|
export function autoResolve(value) {
|
|
@@ -76,7 +77,7 @@ export function autoResolve(value) {
|
|
|
76
77
|
return value.build();
|
|
77
78
|
if (isEachBuilder(value))
|
|
78
79
|
return value.build();
|
|
79
|
-
if (
|
|
80
|
+
if (isWorkflowBuilder(value))
|
|
80
81
|
return value.build();
|
|
81
82
|
return value;
|
|
82
83
|
}
|
|
@@ -135,6 +136,14 @@ function collectTests(exportName, value, out) {
|
|
|
135
136
|
if (isTest(resolvedItem)) {
|
|
136
137
|
out.push(toResolvedTest(exportName, resolvedItem));
|
|
137
138
|
}
|
|
139
|
+
else if (Array.isArray(resolvedItem)) {
|
|
140
|
+
// One nesting level: workflow.each() returns BuiltWorkflow[] where
|
|
141
|
+
// each member is itself a one-element Test[] (the dual array handle).
|
|
142
|
+
for (const inner of resolvedItem) {
|
|
143
|
+
if (isTest(inner))
|
|
144
|
+
out.push(toResolvedTest(exportName, inner));
|
|
145
|
+
}
|
|
146
|
+
}
|
|
138
147
|
}
|
|
139
148
|
}
|
|
140
149
|
}
|
|
@@ -219,6 +228,16 @@ export function findTestByExport(userModule, name) {
|
|
|
219
228
|
if (isTest(item)) {
|
|
220
229
|
return item;
|
|
221
230
|
}
|
|
231
|
+
// One nesting level: workflow.each()/pick() exports BuiltWorkflow[]
|
|
232
|
+
// whose members are themselves one-element Test[] handles. The
|
|
233
|
+
// export-name fallback exists exactly for pick's run-to-run randomness —
|
|
234
|
+
// it must see nested members too (codex S2.12 R1 P1).
|
|
235
|
+
if (Array.isArray(item)) {
|
|
236
|
+
for (const inner of item) {
|
|
237
|
+
if (isTest(inner))
|
|
238
|
+
return inner;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
222
241
|
}
|
|
223
242
|
}
|
|
224
243
|
return undefined;
|
package/dist/resolve.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA2BH,8EAA8E;AAC9E,cAAc;AACd,8EAA8E;AAE9E;;;;GAIG;AACH,MAAM,UAAU,MAAM,CAAC,GAAY;IACjC,OAAO,CACL,OAAO,GAAG,KAAK,QAAQ;QACvB,GAAG,KAAK,IAAI;QACZ,MAAM,IAAI,GAAG;QACb,MAAM,IAAI,GAAG;QACb,CAAE,GAAqB,CAAC,IAAI,KAAK,QAAQ;YACtC,GAAqB,CAAC,IAAI,KAAK,OAAO,CAAC,CAC3C,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAC3B,GAAY;IAEZ,OAAO,CACL,OAAO,GAAG,KAAK,QAAQ;QACvB,GAAG,KAAK,IAAI;QACX,GAA+B,CAAC,cAAc,KAAK,SAAS;QAC7D,OAAQ,GAA+B,CAAC,KAAK,KAAK,UAAU,CAC7D,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAC3B,GAAY;IAEZ,OAAO,CACL,OAAO,GAAG,KAAK,QAAQ;QACvB,GAAG,KAAK,IAAI;QACX,GAA+B,CAAC,cAAc,KAAK,cAAc;QAClE,OAAQ,GAA+B,CAAC,KAAK,KAAK,UAAU,CAC7D,CAAC;AACJ,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/** Diagnostic warning emitted by the executor's runner resolver. */
|
|
2
|
+
export interface RunnerWarning {
|
|
3
|
+
/** Human-readable message. */
|
|
4
|
+
message: string;
|
|
5
|
+
/** Stable code for filtering / consumer dedupe. */
|
|
6
|
+
code: "runner_fallback_no_project" | "runner_fallback_no_dist" | "runner_protocol_old" | "runner_pkg_root_not_found";
|
|
7
|
+
}
|
|
8
|
+
export interface ResolvedRunner {
|
|
9
|
+
distDir: string;
|
|
10
|
+
pkgRoot: string;
|
|
11
|
+
source: "project" | "bundled";
|
|
12
|
+
resolvedFrom?: string;
|
|
13
|
+
version?: string;
|
|
14
|
+
pendingWarnings: RunnerWarning[];
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Resolve the runner dist/ directory + package root.
|
|
18
|
+
*
|
|
19
|
+
* Preference: project-local `@glubean/runner` (found from `projectCwd`'s
|
|
20
|
+
* `node_modules` chain). Fallback: bundled (the consumer's own runner copy).
|
|
21
|
+
*
|
|
22
|
+
* Returns warnings to be yielded as `{ type: "warning", ... }` events at
|
|
23
|
+
* the start of every `run()` call. Always emits a warning when falling
|
|
24
|
+
* back to bundled (so users see why "configure() values..." errors may
|
|
25
|
+
* appear in a misconfigured project).
|
|
26
|
+
*/
|
|
27
|
+
export declare function resolveRunnerRoot(projectCwd: string, bundledDistDir: string, bundledPkgRoot: string): ResolvedRunner;
|
|
28
|
+
/** Resolve the tsx CLI entry used to transform the user's TypeScript in the
|
|
29
|
+
* spawned harness subprocess. Cached after the first lookup. */
|
|
30
|
+
export declare function resolveTsxPath(): string;
|
|
31
|
+
/** A computed zero-project plan: extra tsx `--import` args, env redirects, and a
|
|
32
|
+
* cleanup that undoes any temp package.json. */
|
|
33
|
+
export interface ZeroProjectSetup {
|
|
34
|
+
/** tsx args to prepend (`--import <zero-project-register.mjs>`), or `[]`. */
|
|
35
|
+
tsxArgs: string[];
|
|
36
|
+
/** Env additions (`GLUBEAN_VENDORED_ROOT`), or `{}`. */
|
|
37
|
+
env: Record<string, string>;
|
|
38
|
+
/** Restore the working dir's package.json to its original state. Idempotent. */
|
|
39
|
+
cleanup(): void;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Set up zero-project (scratch) mode for a spawn rooted at `cwd`: when the cwd
|
|
43
|
+
* has no `@glubean/sdk` in node_modules, redirect the user file's `@glubean/*`
|
|
44
|
+
* imports to the resolved runner's vendored copy (via the register hook +
|
|
45
|
+
* `GLUBEAN_VENDORED_ROOT`) and ensure a `"type":"module"` package.json so the
|
|
46
|
+
* `.ts` file loads as ESM. When the cwd already has `@glubean/sdk`, this is a
|
|
47
|
+
* no-op (empty args/env, no-op cleanup).
|
|
48
|
+
*
|
|
49
|
+
* Pure w.r.t. instance state — both `TestExecutor` and the load spawn call it
|
|
50
|
+
* and own the returned `tsxArgs`/`env`/`cleanup`.
|
|
51
|
+
*/
|
|
52
|
+
export declare function prepareZeroProject(cwd: string, runnerDistDir: string, runnerPkgRoot: string): ZeroProjectSetup;
|
|
53
|
+
//# sourceMappingURL=runner-resolve.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner-resolve.d.ts","sourceRoot":"","sources":["../src/runner-resolve.ts"],"names":[],"mappings":"AAqEA,oEAAoE;AACpE,MAAM,WAAW,aAAa;IAC5B,8BAA8B;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,mDAAmD;IACnD,IAAI,EAAE,4BAA4B,GAAG,yBAAyB,GAAG,qBAAqB,GAAG,2BAA2B,CAAC;CACtH;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,SAAS,GAAG,SAAS,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,aAAa,EAAE,CAAC;CAClC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,EAClB,cAAc,EAAE,MAAM,EACtB,cAAc,EAAE,MAAM,GACrB,cAAc,CAuGhB;AAQD;iEACiE;AACjE,wBAAgB,cAAc,IAAI,MAAM,CAKvC;AAID;iDACiD;AACjD,MAAM,WAAW,gBAAgB;IAC/B,6EAA6E;IAC7E,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,wDAAwD;IACxD,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,gFAAgF;IAChF,OAAO,IAAI,IAAI,CAAC;CACjB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,MAAM,EACX,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,MAAM,GACpB,gBAAgB,CA2DlB"}
|