@dungle-scrubs/harness-cli-normalizer 0.1.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/LICENSE +21 -0
- package/README.md +103 -0
- package/dist/execution/channel.d.ts +33 -0
- package/dist/execution/channel.d.ts.map +1 -0
- package/dist/execution/channel.js +86 -0
- package/dist/execution/channel.js.map +1 -0
- package/dist/execution/decode.d.ts +16 -0
- package/dist/execution/decode.d.ts.map +1 -0
- package/dist/execution/decode.js +60 -0
- package/dist/execution/decode.js.map +1 -0
- package/dist/execution/deps.d.ts +53 -0
- package/dist/execution/deps.d.ts.map +1 -0
- package/dist/execution/deps.js +8 -0
- package/dist/execution/deps.js.map +1 -0
- package/dist/execution/events.d.ts +54 -0
- package/dist/execution/events.d.ts.map +1 -0
- package/dist/execution/events.js +2 -0
- package/dist/execution/events.js.map +1 -0
- package/dist/execution/index.d.ts +19 -0
- package/dist/execution/index.d.ts.map +1 -0
- package/dist/execution/index.js +19 -0
- package/dist/execution/index.js.map +1 -0
- package/dist/execution/lines.d.ts +21 -0
- package/dist/execution/lines.d.ts.map +1 -0
- package/dist/execution/lines.js +70 -0
- package/dist/execution/lines.js.map +1 -0
- package/dist/execution/node-deps.d.ts +13 -0
- package/dist/execution/node-deps.d.ts.map +1 -0
- package/dist/execution/node-deps.js +164 -0
- package/dist/execution/node-deps.js.map +1 -0
- package/dist/execution/open-session.d.ts +31 -0
- package/dist/execution/open-session.d.ts.map +1 -0
- package/dist/execution/open-session.js +360 -0
- package/dist/execution/open-session.js.map +1 -0
- package/dist/execution/stream-turn.d.ts +43 -0
- package/dist/execution/stream-turn.d.ts.map +1 -0
- package/dist/execution/stream-turn.js +283 -0
- package/dist/execution/stream-turn.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/interpretation/argv.d.ts +35 -0
- package/dist/interpretation/argv.d.ts.map +1 -0
- package/dist/interpretation/argv.js +147 -0
- package/dist/interpretation/argv.js.map +1 -0
- package/dist/interpretation/capabilities.d.ts +19 -0
- package/dist/interpretation/capabilities.d.ts.map +1 -0
- package/dist/interpretation/capabilities.js +25 -0
- package/dist/interpretation/capabilities.js.map +1 -0
- package/dist/interpretation/content.d.ts +33 -0
- package/dist/interpretation/content.d.ts.map +1 -0
- package/dist/interpretation/content.js +169 -0
- package/dist/interpretation/content.js.map +1 -0
- package/dist/interpretation/context.d.ts +17 -0
- package/dist/interpretation/context.d.ts.map +1 -0
- package/dist/interpretation/context.js +16 -0
- package/dist/interpretation/context.js.map +1 -0
- package/dist/interpretation/dimensions.d.ts +13 -0
- package/dist/interpretation/dimensions.d.ts.map +1 -0
- package/dist/interpretation/dimensions.js +6 -0
- package/dist/interpretation/dimensions.js.map +1 -0
- package/dist/interpretation/identity.d.ts +32 -0
- package/dist/interpretation/identity.d.ts.map +1 -0
- package/dist/interpretation/identity.js +44 -0
- package/dist/interpretation/identity.js.map +1 -0
- package/dist/interpretation/index.d.ts +23 -0
- package/dist/interpretation/index.d.ts.map +1 -0
- package/dist/interpretation/index.js +23 -0
- package/dist/interpretation/index.js.map +1 -0
- package/dist/interpretation/limits.d.ts +20 -0
- package/dist/interpretation/limits.d.ts.map +1 -0
- package/dist/interpretation/limits.js +35 -0
- package/dist/interpretation/limits.js.map +1 -0
- package/dist/interpretation/parse-resume.d.ts +28 -0
- package/dist/interpretation/parse-resume.d.ts.map +1 -0
- package/dist/interpretation/parse-resume.js +91 -0
- package/dist/interpretation/parse-resume.js.map +1 -0
- package/dist/interpretation/presence.d.ts +16 -0
- package/dist/interpretation/presence.d.ts.map +1 -0
- package/dist/interpretation/presence.js +32 -0
- package/dist/interpretation/presence.js.map +1 -0
- package/dist/interpretation/resume-last.d.ts +32 -0
- package/dist/interpretation/resume-last.d.ts.map +1 -0
- package/dist/interpretation/resume-last.js +70 -0
- package/dist/interpretation/resume-last.js.map +1 -0
- package/dist/interpretation/session-id.d.ts +22 -0
- package/dist/interpretation/session-id.d.ts.map +1 -0
- package/dist/interpretation/session-id.js +29 -0
- package/dist/interpretation/session-id.js.map +1 -0
- package/dist/interpretation/session-input.d.ts +13 -0
- package/dist/interpretation/session-input.d.ts.map +1 -0
- package/dist/interpretation/session-input.js +32 -0
- package/dist/interpretation/session-input.js.map +1 -0
- package/dist/interpretation/shape.d.ts +17 -0
- package/dist/interpretation/shape.d.ts.map +1 -0
- package/dist/interpretation/shape.js +54 -0
- package/dist/interpretation/shape.js.map +1 -0
- package/dist/interpretation/store.d.ts +16 -0
- package/dist/interpretation/store.d.ts.map +1 -0
- package/dist/interpretation/store.js +27 -0
- package/dist/interpretation/store.js.map +1 -0
- package/dist/interpretation/versions.d.ts +16 -0
- package/dist/interpretation/versions.d.ts.map +1 -0
- package/dist/interpretation/versions.js +44 -0
- package/dist/interpretation/versions.js.map +1 -0
- package/dist/interpretation/vocabulary.d.ts +29 -0
- package/dist/interpretation/vocabulary.d.ts.map +1 -0
- package/dist/interpretation/vocabulary.js +55 -0
- package/dist/interpretation/vocabulary.js.map +1 -0
- package/dist/knowledge/claude-code.d.ts +8 -0
- package/dist/knowledge/claude-code.d.ts.map +1 -0
- package/dist/knowledge/claude-code.js +132 -0
- package/dist/knowledge/claude-code.js.map +1 -0
- package/dist/knowledge/codex.d.ts +9 -0
- package/dist/knowledge/codex.d.ts.map +1 -0
- package/dist/knowledge/codex.js +106 -0
- package/dist/knowledge/codex.js.map +1 -0
- package/dist/knowledge/descriptor.d.ts +211 -0
- package/dist/knowledge/descriptor.d.ts.map +1 -0
- package/dist/knowledge/descriptor.js +20 -0
- package/dist/knowledge/descriptor.js.map +1 -0
- package/dist/knowledge/index.d.ts +19 -0
- package/dist/knowledge/index.d.ts.map +1 -0
- package/dist/knowledge/index.js +19 -0
- package/dist/knowledge/index.js.map +1 -0
- package/dist/knowledge/matchers.d.ts +10 -0
- package/dist/knowledge/matchers.d.ts.map +1 -0
- package/dist/knowledge/matchers.js +11 -0
- package/dist/knowledge/matchers.js.map +1 -0
- package/dist/knowledge/muse.d.ts +12 -0
- package/dist/knowledge/muse.d.ts.map +1 -0
- package/dist/knowledge/muse.js +94 -0
- package/dist/knowledge/muse.js.map +1 -0
- package/dist/knowledge/overrides.d.ts +11 -0
- package/dist/knowledge/overrides.d.ts.map +1 -0
- package/dist/knowledge/overrides.js +166 -0
- package/dist/knowledge/overrides.js.map +1 -0
- package/dist/knowledge/pi.d.ts +11 -0
- package/dist/knowledge/pi.d.ts.map +1 -0
- package/dist/knowledge/pi.js +97 -0
- package/dist/knowledge/pi.js.map +1 -0
- package/package.json +69 -0
- package/src/execution/channel.ts +86 -0
- package/src/execution/decode.ts +79 -0
- package/src/execution/deps.ts +59 -0
- package/src/execution/events.ts +37 -0
- package/src/execution/index.ts +18 -0
- package/src/execution/lines.ts +71 -0
- package/src/execution/node-deps.ts +179 -0
- package/src/execution/open-session.ts +392 -0
- package/src/execution/stream-turn.ts +310 -0
- package/src/index.ts +7 -0
- package/src/interpretation/argv.ts +188 -0
- package/src/interpretation/capabilities.ts +51 -0
- package/src/interpretation/content.ts +191 -0
- package/src/interpretation/context.ts +28 -0
- package/src/interpretation/dimensions.ts +20 -0
- package/src/interpretation/identity.ts +81 -0
- package/src/interpretation/index.ts +22 -0
- package/src/interpretation/limits.ts +63 -0
- package/src/interpretation/parse-resume.ts +117 -0
- package/src/interpretation/presence.ts +49 -0
- package/src/interpretation/resume-last.ts +93 -0
- package/src/interpretation/session-id.ts +35 -0
- package/src/interpretation/session-input.ts +45 -0
- package/src/interpretation/shape.ts +55 -0
- package/src/interpretation/store.ts +43 -0
- package/src/interpretation/versions.ts +43 -0
- package/src/interpretation/vocabulary.ts +74 -0
- package/src/knowledge/claude-code.ts +132 -0
- package/src/knowledge/codex.ts +106 -0
- package/src/knowledge/descriptor.ts +217 -0
- package/src/knowledge/index.ts +23 -0
- package/src/knowledge/matchers.ts +19 -0
- package/src/knowledge/muse.ts +94 -0
- package/src/knowledge/overrides.ts +182 -0
- package/src/knowledge/pi.ts +97 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Readable } from "node:stream";
|
|
2
|
+
import type { RunnerDeps } from "./deps.js";
|
|
3
|
+
type SpawnOutcome = "spawned" | "failed";
|
|
4
|
+
/** Request terminal disposal without discarding chunks already buffered by
|
|
5
|
+
* the runtime. Once the consumer reaches the first pending read, destruction
|
|
6
|
+
* settles that read with this adapter's unique disposal cause. */
|
|
7
|
+
export declare const disposableOutputStream: (source: Readable, disposalCause: Error, spawnOutcome: Promise<SpawnOutcome>) => {
|
|
8
|
+
readonly stream: AsyncIterable<Uint8Array>;
|
|
9
|
+
dispose(): void;
|
|
10
|
+
};
|
|
11
|
+
export declare const nodeRunnerDeps: (extra?: Partial<RunnerDeps>) => RunnerDeps;
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=node-deps.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-deps.d.ts","sourceRoot":"","sources":["../../src/execution/node-deps.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAS,UAAU,EAAgC,MAAM,WAAW,CAAC;AAMjF,KAAK,YAAY,GAAG,SAAS,GAAG,QAAQ,CAAC;AAwBzC;;kEAEkE;AAClE,eAAO,MAAM,sBAAsB,WACzB,QAAQ,iBACD,KAAK,gBACN,OAAO,CAAC,YAAY,CAAC,KAClC;IAAE,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;IAAC,OAAO,IAAI,IAAI,CAAA;CAyC/D,CAAC;AAmFF,eAAO,MAAM,cAAc,WAAY,OAAO,CAAC,UAAU,CAAC,KAAG,UAO3D,CAAC"}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The real runtime adapter for RunnerDeps: node:child_process spawn (Bun
|
|
3
|
+
* implements the same module, so this is the Node AND Bun adapter), wall
|
|
4
|
+
* clock, and process signalling. This is the ONE module where the injected
|
|
5
|
+
* primitives touch the operating system - everything above it stays pure
|
|
6
|
+
* and fake-driven. Kills go to the exact child handle this adapter
|
|
7
|
+
* spawned, never to a pid pattern.
|
|
8
|
+
*/
|
|
9
|
+
import { spawn as nodeSpawn } from "node:child_process";
|
|
10
|
+
const children = new WeakMap();
|
|
11
|
+
const emptyStream = async function* () { };
|
|
12
|
+
/** Normalize only errors created by this adapter's own terminal operations.
|
|
13
|
+
* Identity comparison keeps an unrelated read failure visible even when it
|
|
14
|
+
* settles after output disposal has started. */
|
|
15
|
+
const normalizeOutputStream = async function* (source, disposalCause, spawnOutcome) {
|
|
16
|
+
try {
|
|
17
|
+
yield* source;
|
|
18
|
+
}
|
|
19
|
+
catch (cause) {
|
|
20
|
+
if (cause === disposalCause)
|
|
21
|
+
return;
|
|
22
|
+
if (cause?.code === "ERR_STREAM_PREMATURE_CLOSE" &&
|
|
23
|
+
(await spawnOutcome) === "failed") {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
throw cause;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
/** Request terminal disposal without discarding chunks already buffered by
|
|
30
|
+
* the runtime. Once the consumer reaches the first pending read, destruction
|
|
31
|
+
* settles that read with this adapter's unique disposal cause. */
|
|
32
|
+
export const disposableOutputStream = (source, disposalCause, spawnOutcome) => {
|
|
33
|
+
let disposalRequested = false;
|
|
34
|
+
let disposalDrainBudget = 0;
|
|
35
|
+
let readPending = false;
|
|
36
|
+
const destroyPendingRead = () => {
|
|
37
|
+
if (disposalRequested && readPending && disposalDrainBudget === 0 && !source.destroyed) {
|
|
38
|
+
source.destroy(disposalCause);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
const drainBeforeDisposal = async function* () {
|
|
42
|
+
const iterator = source[Symbol.asyncIterator]();
|
|
43
|
+
while (true) {
|
|
44
|
+
readPending = true;
|
|
45
|
+
if (disposalRequested && disposalDrainBudget === 0 && !source.destroyed) {
|
|
46
|
+
source.destroy(disposalCause);
|
|
47
|
+
}
|
|
48
|
+
let next;
|
|
49
|
+
try {
|
|
50
|
+
next = await iterator.next();
|
|
51
|
+
}
|
|
52
|
+
finally {
|
|
53
|
+
readPending = false;
|
|
54
|
+
}
|
|
55
|
+
if (next.done)
|
|
56
|
+
return;
|
|
57
|
+
if (disposalRequested) {
|
|
58
|
+
const bytes = next.value;
|
|
59
|
+
disposalDrainBudget = Math.max(0, disposalDrainBudget - (bytes.byteLength ?? 0));
|
|
60
|
+
}
|
|
61
|
+
yield next.value;
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
return {
|
|
65
|
+
stream: normalizeOutputStream(drainBeforeDisposal(), disposalCause, spawnOutcome),
|
|
66
|
+
dispose: () => {
|
|
67
|
+
if (disposalRequested)
|
|
68
|
+
return;
|
|
69
|
+
disposalRequested = true;
|
|
70
|
+
disposalDrainBudget = source.readableLength;
|
|
71
|
+
destroyPendingRead();
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
};
|
|
75
|
+
const realSpawn = (argv, opts) => {
|
|
76
|
+
const [bin, ...args] = argv;
|
|
77
|
+
if (bin === undefined)
|
|
78
|
+
throw new Error("empty argv");
|
|
79
|
+
const child = nodeSpawn(bin, args, {
|
|
80
|
+
...(opts.cwd !== undefined ? { cwd: opts.cwd } : {}),
|
|
81
|
+
stdio: [
|
|
82
|
+
opts.stdin === "pipe" ? "pipe" : opts.stdin === "close" ? "ignore" : "inherit",
|
|
83
|
+
"pipe",
|
|
84
|
+
"pipe",
|
|
85
|
+
],
|
|
86
|
+
});
|
|
87
|
+
let outputDisposed = false;
|
|
88
|
+
const stdoutDisposalCause = new Error("stdout disposed by runner");
|
|
89
|
+
const stderrDisposalCause = new Error("stderr disposed by runner");
|
|
90
|
+
let spawnError = null;
|
|
91
|
+
const spawnOutcome = new Promise((resolve) => {
|
|
92
|
+
child.once("spawn", () => resolve("spawned"));
|
|
93
|
+
child.once("error", () => resolve("failed"));
|
|
94
|
+
});
|
|
95
|
+
const stdoutOutput = child.stdout === null
|
|
96
|
+
? null
|
|
97
|
+
: disposableOutputStream(child.stdout, stdoutDisposalCause, spawnOutcome);
|
|
98
|
+
const stderrOutput = child.stderr === null
|
|
99
|
+
? null
|
|
100
|
+
: disposableOutputStream(child.stderr, stderrDisposalCause, spawnOutcome);
|
|
101
|
+
// exited resolves via 'exit' (process died - fires even while a grandchild
|
|
102
|
+
// holds the pipes open, unlike 'close') or 'error' (ENOENT etc., which
|
|
103
|
+
// node reports async, not as a sync throw -> map to 127 crash). The error
|
|
104
|
+
// handler sets spawnError before it resolves exited.
|
|
105
|
+
const exited = new Promise((resolve) => {
|
|
106
|
+
child.on("error", (err) => {
|
|
107
|
+
spawnError = err;
|
|
108
|
+
resolve(127);
|
|
109
|
+
});
|
|
110
|
+
child.on("exit", (code) => resolve(code));
|
|
111
|
+
});
|
|
112
|
+
// The spawn error rides the stderr stream so the runner's tail (and the
|
|
113
|
+
// crash exit log) carry the explanation, matching the sync-throw path.
|
|
114
|
+
// normalizeOutputStream waits only for the spawn/error outcome when it sees a
|
|
115
|
+
// premature close, so a genuine read failure on a live child propagates
|
|
116
|
+
// immediately while an async ENOENT remains the single spawn-error signal.
|
|
117
|
+
const stderrWithError = async function* () {
|
|
118
|
+
if (stderrOutput !== null)
|
|
119
|
+
yield* stderrOutput.stream;
|
|
120
|
+
await exited;
|
|
121
|
+
if (spawnError !== null)
|
|
122
|
+
yield `spawn failed: ${spawnError.message}\n`;
|
|
123
|
+
};
|
|
124
|
+
const proc = {
|
|
125
|
+
stdout: stdoutOutput === null ? emptyStream() : stdoutOutput.stream,
|
|
126
|
+
stderr: stderrWithError(),
|
|
127
|
+
exited,
|
|
128
|
+
disposeOutput: () => {
|
|
129
|
+
if (outputDisposed)
|
|
130
|
+
return;
|
|
131
|
+
outputDisposed = true;
|
|
132
|
+
stdoutOutput?.dispose();
|
|
133
|
+
stderrOutput?.dispose();
|
|
134
|
+
},
|
|
135
|
+
...(opts.stdin === "pipe" && child.stdin !== null
|
|
136
|
+
? {
|
|
137
|
+
stdin: {
|
|
138
|
+
write: (data) => {
|
|
139
|
+
child.stdin?.write(data);
|
|
140
|
+
},
|
|
141
|
+
end: () => {
|
|
142
|
+
child.stdin?.end();
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
}
|
|
146
|
+
: {}),
|
|
147
|
+
};
|
|
148
|
+
children.set(proc, child);
|
|
149
|
+
return proc;
|
|
150
|
+
};
|
|
151
|
+
const realClock = {
|
|
152
|
+
now: () => Date.now(),
|
|
153
|
+
setTimeout: (fn, ms) => setTimeout(fn, ms),
|
|
154
|
+
clearTimeout: (handle) => clearTimeout(handle),
|
|
155
|
+
};
|
|
156
|
+
export const nodeRunnerDeps = (extra) => ({
|
|
157
|
+
spawn: realSpawn,
|
|
158
|
+
clock: realClock,
|
|
159
|
+
signal: (proc, sig) => {
|
|
160
|
+
children.get(proc)?.kill(sig);
|
|
161
|
+
},
|
|
162
|
+
...extra,
|
|
163
|
+
});
|
|
164
|
+
//# sourceMappingURL=node-deps.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-deps.js","sourceRoot":"","sources":["../../src/execution/node-deps.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { HarnessDescriptor } from "../knowledge/descriptor.js";
|
|
2
|
+
import type { RunnerDeps } from "./deps.js";
|
|
3
|
+
import type { HarnessEvent } from "./events.js";
|
|
4
|
+
/** Grace after stdin EOF before concluding the child will not exit on its
|
|
5
|
+
* own and escalating signals. */
|
|
6
|
+
export declare const CLOSE_GRACE_MS = 5000;
|
|
7
|
+
export interface SessionSendResult {
|
|
8
|
+
readonly disposition: "started" | "queued";
|
|
9
|
+
}
|
|
10
|
+
export interface SessionHandle {
|
|
11
|
+
/** One inner iterable per turn, each ending in a turn-scoped `done`.
|
|
12
|
+
* Breaking out of THIS iterable closes the session; breaking out of a
|
|
13
|
+
* single turn's iterable only stops reading that turn. */
|
|
14
|
+
readonly turns: AsyncIterable<AsyncIterable<HarnessEvent>>;
|
|
15
|
+
send(text: string): SessionSendResult;
|
|
16
|
+
close(): Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
export interface OpenSessionOptions {
|
|
19
|
+
readonly sessionId: string;
|
|
20
|
+
readonly model?: string;
|
|
21
|
+
/** Working directory for the spawned harness. */
|
|
22
|
+
readonly cwd?: string;
|
|
23
|
+
}
|
|
24
|
+
export declare class SessionClosedError extends Error {
|
|
25
|
+
constructor();
|
|
26
|
+
}
|
|
27
|
+
export declare class SessionSpawnError extends Error {
|
|
28
|
+
constructor(harness: string, cause: unknown);
|
|
29
|
+
}
|
|
30
|
+
export declare const openSession: (h: HarnessDescriptor, opts: OpenSessionOptions, deps: RunnerDeps) => SessionHandle;
|
|
31
|
+
//# sourceMappingURL=open-session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"open-session.d.ts","sourceRoot":"","sources":["../../src/execution/open-session.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,iBAAiB,EAAwB,MAAM,4BAA4B,CAAC;AAG1F,OAAO,KAAK,EAAE,UAAU,EAAkB,MAAM,WAAW,CAAC;AAC5D,OAAO,KAAK,EAAa,YAAY,EAAE,MAAM,aAAa,CAAC;AAI3D;iCACiC;AACjC,eAAO,MAAM,cAAc,OAAQ,CAAC;AAIpC,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,WAAW,EAAE,SAAS,GAAG,QAAQ,CAAC;CAC5C;AAED,MAAM,WAAW,aAAa;IAC5B;;8DAE0D;IAC1D,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC;IAC3D,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,CAAC;IACtC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,iDAAiD;IACjD,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,cAGC;CACF;AAED,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,YAAY,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAK1C;CACF;AAED,eAAO,MAAM,WAAW,MACnB,iBAAiB,QACd,kBAAkB,QAClB,UAAU,KACf,aA2TF,CAAC"}
|
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* openSession: the persistent headless session runner - ONE process, many
|
|
3
|
+
* turns (A-001). `send` during idle writes a descriptor-encoded user record to
|
|
4
|
+
* stdin and starts a turn; `send` during a live turn is QUEUED to the next
|
|
5
|
+
* boundary (mid-turn stdin writes would interleave into the model's
|
|
6
|
+
* context unpredictably - the harness itself queues, so we mirror its
|
|
7
|
+
* disposition). `result` lines delimit turns; identity dedupe (D-022)
|
|
8
|
+
* spans the whole session. Lifecycle is bounded end to end: close() ends
|
|
9
|
+
* stdin, escalates SIGTERM->SIGKILL if the child ignores EOF, and pipes
|
|
10
|
+
* held open past exit close out after grace - a session can always be
|
|
11
|
+
* ended. Queued sends that die with the session are surfaced, never
|
|
12
|
+
* silently dropped. Structured lifecycle events (session open/close, turn
|
|
13
|
+
* start/end, send dispositions, drops) are always-on evidence with
|
|
14
|
+
* sessionId + turnId correlation.
|
|
15
|
+
*/
|
|
16
|
+
import { buildSessionArgv } from "../interpretation/argv.js";
|
|
17
|
+
import { detectAuthFailureInLine, detectLimitInLine } from "../interpretation/limits.js";
|
|
18
|
+
import { encodeSessionInput, resolveSessionInput, SessionInputRefusalError, } from "../interpretation/session-input.js";
|
|
19
|
+
import { AsyncChannel } from "./channel.js";
|
|
20
|
+
import { decodeParsed, freshDecodeState } from "./decode.js";
|
|
21
|
+
import { LineBuffer } from "./lines.js";
|
|
22
|
+
import { KILL_GRACE_MS, PIPE_GRACE_MS, redactArgv, StderrTail } from "./stream-turn.js";
|
|
23
|
+
/** Grace after stdin EOF before concluding the child will not exit on its
|
|
24
|
+
* own and escalating signals. */
|
|
25
|
+
export const CLOSE_GRACE_MS = 5_000;
|
|
26
|
+
const PRETURN_MAX = 256;
|
|
27
|
+
export class SessionClosedError extends Error {
|
|
28
|
+
constructor() {
|
|
29
|
+
super("session is closed; sends have nowhere to go");
|
|
30
|
+
this.name = "SessionClosedError";
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export class SessionSpawnError extends Error {
|
|
34
|
+
constructor(harness, cause) {
|
|
35
|
+
super(`could not spawn a ${harness} session: ${cause instanceof Error ? cause.message : String(cause)}`);
|
|
36
|
+
this.name = "SessionSpawnError";
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
export const openSession = (h, opts, deps) => {
|
|
40
|
+
const log = deps.log ?? (() => { });
|
|
41
|
+
const argv = buildSessionArgv(h, {
|
|
42
|
+
sessionId: opts.sessionId,
|
|
43
|
+
...(opts.model !== undefined ? { model: opts.model } : {}),
|
|
44
|
+
});
|
|
45
|
+
let sessionInput;
|
|
46
|
+
try {
|
|
47
|
+
sessionInput = resolveSessionInput(h);
|
|
48
|
+
}
|
|
49
|
+
catch (cause) {
|
|
50
|
+
if (!(cause instanceof SessionInputRefusalError))
|
|
51
|
+
throw cause;
|
|
52
|
+
log({
|
|
53
|
+
event: "session_input_refused",
|
|
54
|
+
harness: h.name,
|
|
55
|
+
issue: cause.issue,
|
|
56
|
+
sessionId: opts.sessionId,
|
|
57
|
+
});
|
|
58
|
+
throw cause;
|
|
59
|
+
}
|
|
60
|
+
let proc;
|
|
61
|
+
try {
|
|
62
|
+
// A session needs a writable stdin regardless of the descriptor's
|
|
63
|
+
// one-shot stdin policy - that policy governs turns, not sessions.
|
|
64
|
+
proc = deps.spawn(argv, {
|
|
65
|
+
stdin: "pipe",
|
|
66
|
+
...(opts.cwd !== undefined ? { cwd: opts.cwd } : {}),
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
catch (cause) {
|
|
70
|
+
log({ event: "session_spawn_failed", sessionId: opts.sessionId, harness: h.name });
|
|
71
|
+
throw new SessionSpawnError(h.name, cause);
|
|
72
|
+
}
|
|
73
|
+
const stdin = proc.stdin;
|
|
74
|
+
if (stdin === undefined) {
|
|
75
|
+
// The child exists but there is no way to ever send to it - end it
|
|
76
|
+
// before throwing, or it runs orphaned forever.
|
|
77
|
+
deps.signal(proc, "SIGTERM");
|
|
78
|
+
log({ event: "session_spawn_failed", sessionId: opts.sessionId, harness: h.name });
|
|
79
|
+
throw new SessionSpawnError(h.name, new Error("spawner opened no stdin pipe"));
|
|
80
|
+
}
|
|
81
|
+
log({
|
|
82
|
+
event: "session_open",
|
|
83
|
+
sessionId: opts.sessionId,
|
|
84
|
+
harness: h.name,
|
|
85
|
+
argv: redactArgv(argv),
|
|
86
|
+
});
|
|
87
|
+
const turnsChannel = new AsyncChannel();
|
|
88
|
+
const state = freshDecodeState(opts.sessionId);
|
|
89
|
+
const stderrTail = new StderrTail();
|
|
90
|
+
let turnCounter = 0;
|
|
91
|
+
let activeTurn = null;
|
|
92
|
+
let activeTurnId = "";
|
|
93
|
+
const pendingSends = [];
|
|
94
|
+
const preTurnEvents = [];
|
|
95
|
+
let dead = false;
|
|
96
|
+
let closing = false;
|
|
97
|
+
let finalized = false;
|
|
98
|
+
let exitCode = null;
|
|
99
|
+
let resultError = false;
|
|
100
|
+
let turnLimitSeen = false;
|
|
101
|
+
let pumpError = null;
|
|
102
|
+
const safeSignal = (sig) => {
|
|
103
|
+
if (!dead)
|
|
104
|
+
deps.signal(proc, sig);
|
|
105
|
+
};
|
|
106
|
+
const escalate = () => {
|
|
107
|
+
safeSignal("SIGTERM");
|
|
108
|
+
deps.clock.setTimeout(() => safeSignal("SIGKILL"), KILL_GRACE_MS);
|
|
109
|
+
};
|
|
110
|
+
const writeUser = (text) => {
|
|
111
|
+
try {
|
|
112
|
+
stdin.write(encodeSessionInput(sessionInput, text));
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
activeTurn?.push({ kind: "error", message: "send failed: session stdin is gone" });
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
const startTurn = () => {
|
|
121
|
+
turnLimitSeen = false;
|
|
122
|
+
activeTurn = new AsyncChannel();
|
|
123
|
+
activeTurnId = `${opts.sessionId}:turn-${++turnCounter}`;
|
|
124
|
+
log({ event: "turn_start", sessionId: opts.sessionId, turnId: activeTurnId });
|
|
125
|
+
for (const held of preTurnEvents.splice(0))
|
|
126
|
+
activeTurn.push(held);
|
|
127
|
+
turnsChannel.push(activeTurn);
|
|
128
|
+
};
|
|
129
|
+
const endTurn = (done) => {
|
|
130
|
+
if (activeTurn === null)
|
|
131
|
+
return;
|
|
132
|
+
activeTurn.push(done);
|
|
133
|
+
activeTurn.close();
|
|
134
|
+
log({
|
|
135
|
+
event: "turn_end",
|
|
136
|
+
sessionId: opts.sessionId,
|
|
137
|
+
turnId: activeTurnId,
|
|
138
|
+
cause: done.cause,
|
|
139
|
+
});
|
|
140
|
+
activeTurn = null;
|
|
141
|
+
resultError = false;
|
|
142
|
+
// The boundary is the only legal delivery point for queued input.
|
|
143
|
+
if (dead || closing)
|
|
144
|
+
return;
|
|
145
|
+
const next = pendingSends.shift();
|
|
146
|
+
if (next !== undefined && writeUser(next))
|
|
147
|
+
startTurn();
|
|
148
|
+
};
|
|
149
|
+
const routeEvent = (event) => {
|
|
150
|
+
if (event.kind === "limit") {
|
|
151
|
+
state.limitSeen = true;
|
|
152
|
+
turnLimitSeen = true;
|
|
153
|
+
}
|
|
154
|
+
if (activeTurn !== null) {
|
|
155
|
+
// Awaited by the pumps: past the channel's high water mark this
|
|
156
|
+
// blocks the pump, so OS pipe backpressure reaches the child.
|
|
157
|
+
return activeTurn.push(event);
|
|
158
|
+
}
|
|
159
|
+
// Between-turn events wait for the next turn, bounded: past the cap
|
|
160
|
+
// droppable events go first, then oldest.
|
|
161
|
+
preTurnEvents.push(event);
|
|
162
|
+
if (preTurnEvents.length > PRETURN_MAX) {
|
|
163
|
+
const droppableAt = preTurnEvents.findIndex((e) => e.kind === "token" || e.kind === "progress" || e.kind === "context");
|
|
164
|
+
preTurnEvents.splice(droppableAt === -1 ? 0 : droppableAt, 1);
|
|
165
|
+
}
|
|
166
|
+
return Promise.resolve();
|
|
167
|
+
};
|
|
168
|
+
const pumpStdout = async () => {
|
|
169
|
+
const lines = new LineBuffer();
|
|
170
|
+
const handleLine = async (line) => {
|
|
171
|
+
let parsed = null;
|
|
172
|
+
try {
|
|
173
|
+
parsed = JSON.parse(line);
|
|
174
|
+
}
|
|
175
|
+
catch {
|
|
176
|
+
const code = detectLimitInLine(h, line);
|
|
177
|
+
if (code !== null) {
|
|
178
|
+
await routeEvent({ kind: "limit", code, message: `limit wall detected (${code})` });
|
|
179
|
+
}
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
// The result line still feeds identity dedupe (claude includes
|
|
183
|
+
// session_id on it - a rotation announced there must not be missed).
|
|
184
|
+
const events = decodeParsed(h, parsed, state, opts.model ?? "");
|
|
185
|
+
if (parsed.type === "result") {
|
|
186
|
+
// decodeParsed already surfaces the is_error case as an error event
|
|
187
|
+
// (content.ts claude reader); routing the events is enough - we only
|
|
188
|
+
// still track resultError here to classify the done cause.
|
|
189
|
+
for (const event of events)
|
|
190
|
+
await routeEvent(event);
|
|
191
|
+
if (parsed.is_error === true)
|
|
192
|
+
resultError = true;
|
|
193
|
+
endTurn({
|
|
194
|
+
kind: "done",
|
|
195
|
+
exitCode: null,
|
|
196
|
+
cause: turnLimitSeen ? "limit" : resultError ? "crash" : "clean",
|
|
197
|
+
});
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
for (const event of events)
|
|
201
|
+
await routeEvent(event);
|
|
202
|
+
};
|
|
203
|
+
for await (const chunk of proc.stdout) {
|
|
204
|
+
for (const line of lines.push(chunk))
|
|
205
|
+
await handleLine(line);
|
|
206
|
+
}
|
|
207
|
+
const rest = lines.flush();
|
|
208
|
+
if (rest !== null)
|
|
209
|
+
await handleLine(rest);
|
|
210
|
+
};
|
|
211
|
+
const pumpStderr = async () => {
|
|
212
|
+
const lines = new LineBuffer();
|
|
213
|
+
for await (const chunk of proc.stderr) {
|
|
214
|
+
for (const line of lines.push(chunk)) {
|
|
215
|
+
const limit = detectLimitInLine(h, line);
|
|
216
|
+
if (limit !== null) {
|
|
217
|
+
await routeEvent({
|
|
218
|
+
kind: "limit",
|
|
219
|
+
code: limit,
|
|
220
|
+
message: `limit wall detected (${limit})`,
|
|
221
|
+
});
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
const auth = detectAuthFailureInLine(h, line);
|
|
225
|
+
if (auth !== null) {
|
|
226
|
+
await routeEvent({ kind: "error", message: `auth wall: ${auth}` });
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
stderrTail.push(line);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
const pumping = Promise.allSettled([pumpStdout(), pumpStderr()]).then((settlements) => {
|
|
234
|
+
pumpError = settlements.find((settlement) => settlement.status === "rejected")?.reason ?? null;
|
|
235
|
+
});
|
|
236
|
+
let shutdownComplete = () => { };
|
|
237
|
+
const shutdown = new Promise((resolve) => {
|
|
238
|
+
shutdownComplete = resolve;
|
|
239
|
+
});
|
|
240
|
+
let pipesOpenAtExit = false;
|
|
241
|
+
const finalize = () => {
|
|
242
|
+
if (finalized)
|
|
243
|
+
return;
|
|
244
|
+
finalized = true;
|
|
245
|
+
const cause = state.limitSeen
|
|
246
|
+
? "limit"
|
|
247
|
+
: exitCode === 0
|
|
248
|
+
? "clean"
|
|
249
|
+
: exitCode === null
|
|
250
|
+
? "killed"
|
|
251
|
+
: "crash";
|
|
252
|
+
if (pumpError !== null) {
|
|
253
|
+
void routeEvent({ kind: "error", message: `session pump failed: ${String(pumpError)}` });
|
|
254
|
+
}
|
|
255
|
+
if (pendingSends.length > 0) {
|
|
256
|
+
// "queued" was an accepted disposition - the loss must be visible to
|
|
257
|
+
// both the log and the consumer, never silent.
|
|
258
|
+
void routeEvent({
|
|
259
|
+
kind: "error",
|
|
260
|
+
message: `${pendingSends.length} queued send(s) died with the session`,
|
|
261
|
+
});
|
|
262
|
+
log({
|
|
263
|
+
event: "sends_dropped",
|
|
264
|
+
sessionId: opts.sessionId,
|
|
265
|
+
count: pendingSends.length,
|
|
266
|
+
lengths: pendingSends.map((s) => s.length),
|
|
267
|
+
});
|
|
268
|
+
pendingSends.length = 0;
|
|
269
|
+
}
|
|
270
|
+
endTurn({ kind: "done", exitCode, cause });
|
|
271
|
+
if (preTurnEvents.some((e) => e.kind !== "token" && e.kind !== "progress")) {
|
|
272
|
+
log({
|
|
273
|
+
event: "preturn_events_dropped",
|
|
274
|
+
sessionId: opts.sessionId,
|
|
275
|
+
kinds: preTurnEvents.map((e) => e.kind),
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
turnsChannel.close();
|
|
279
|
+
log({
|
|
280
|
+
event: "session_close",
|
|
281
|
+
sessionId: opts.sessionId,
|
|
282
|
+
exitCode,
|
|
283
|
+
cause,
|
|
284
|
+
...(pipesOpenAtExit ? { pipesOpenAtExit } : {}),
|
|
285
|
+
...(cause === "crash" || cause === "killed" ? { stderrTail: stderrTail.snapshot() } : {}),
|
|
286
|
+
});
|
|
287
|
+
shutdownComplete();
|
|
288
|
+
};
|
|
289
|
+
void proc.exited.then((code) => {
|
|
290
|
+
dead = true;
|
|
291
|
+
exitCode = code;
|
|
292
|
+
// Pipes held open past exit (a grandchild) must not hang the session.
|
|
293
|
+
const pipeGrace = deps.clock.setTimeout(() => {
|
|
294
|
+
pipesOpenAtExit = true;
|
|
295
|
+
activeTurn?.releaseBackpressure();
|
|
296
|
+
proc.disposeOutput();
|
|
297
|
+
void pumping.then(() => finalize());
|
|
298
|
+
}, PIPE_GRACE_MS);
|
|
299
|
+
void pumping.then(() => {
|
|
300
|
+
deps.clock.clearTimeout(pipeGrace);
|
|
301
|
+
finalize();
|
|
302
|
+
});
|
|
303
|
+
});
|
|
304
|
+
const close = async () => {
|
|
305
|
+
if (closing)
|
|
306
|
+
return shutdown;
|
|
307
|
+
closing = true;
|
|
308
|
+
try {
|
|
309
|
+
stdin.end();
|
|
310
|
+
}
|
|
311
|
+
catch {
|
|
312
|
+
// stdin may already be gone - escalation below still bounds close.
|
|
313
|
+
}
|
|
314
|
+
// A child that does not exit on stdin EOF gets signalled after grace.
|
|
315
|
+
const closeGrace = deps.clock.setTimeout(() => escalate(), CLOSE_GRACE_MS);
|
|
316
|
+
await shutdown;
|
|
317
|
+
deps.clock.clearTimeout(closeGrace);
|
|
318
|
+
};
|
|
319
|
+
return {
|
|
320
|
+
// Breaking out of the turns iterable is abandonment - treat it as
|
|
321
|
+
// close() so the child is never left running undrained (the streamTurn
|
|
322
|
+
// C1 scar, adapted to a handle-shaped API).
|
|
323
|
+
turns: (async function* () {
|
|
324
|
+
try {
|
|
325
|
+
for await (const turn of turnsChannel)
|
|
326
|
+
yield turn;
|
|
327
|
+
}
|
|
328
|
+
finally {
|
|
329
|
+
if (!closing && !dead)
|
|
330
|
+
void close();
|
|
331
|
+
}
|
|
332
|
+
})(),
|
|
333
|
+
send(text) {
|
|
334
|
+
if (dead || closing)
|
|
335
|
+
throw new SessionClosedError();
|
|
336
|
+
if (activeTurn !== null) {
|
|
337
|
+
pendingSends.push(text);
|
|
338
|
+
log({
|
|
339
|
+
event: "send",
|
|
340
|
+
sessionId: opts.sessionId,
|
|
341
|
+
turnId: activeTurnId,
|
|
342
|
+
disposition: "queued",
|
|
343
|
+
});
|
|
344
|
+
return { disposition: "queued" };
|
|
345
|
+
}
|
|
346
|
+
if (!writeUser(text))
|
|
347
|
+
throw new SessionClosedError();
|
|
348
|
+
startTurn();
|
|
349
|
+
log({
|
|
350
|
+
event: "send",
|
|
351
|
+
sessionId: opts.sessionId,
|
|
352
|
+
turnId: activeTurnId,
|
|
353
|
+
disposition: "started",
|
|
354
|
+
});
|
|
355
|
+
return { disposition: "started" };
|
|
356
|
+
},
|
|
357
|
+
close,
|
|
358
|
+
};
|
|
359
|
+
};
|
|
360
|
+
//# sourceMappingURL=open-session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"open-session.js","sourceRoot":"","sources":["../../src/execution/open-session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AACzF,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,wBAAwB,GACzB,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAG7D,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAExF;iCACiC;AACjC,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,CAAC;AAEpC,MAAM,WAAW,GAAG,GAAG,CAAC;AAsBxB,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAC3C;QACE,KAAK,CAAC,6CAA6C,CAAC,CAAC;QACrD,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AAED,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IAC1C,YAAY,OAAe,EAAE,KAAc;QACzC,KAAK,CACH,qBAAqB,OAAO,aAAa,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAClG,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;IAClC,CAAC;CACF;AAED,MAAM,CAAC,MAAM,WAAW,GAAG,CACzB,CAAoB,EACpB,IAAwB,EACxB,IAAgB,EACD,EAAE;IACjB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACnC,MAAM,IAAI,GAAG,gBAAgB,CAAC,CAAC,EAAE;QAC/B,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,GAAG,CAAC,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC3D,CAAC,CAAC;IACH,IAAI,YAAkC,CAAC;IACvC,IAAI,CAAC;QACH,YAAY,GAAG,mBAAmB,CAAC,CAAC,CAAC,CAAC;IACxC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,CAAC,KAAK,YAAY,wBAAwB,CAAC;YAAE,MAAM,KAAK,CAAC;QAC9D,GAAG,CAAC;YACF,KAAK,EAAE,uBAAuB;YAC9B,OAAO,EAAE,CAAC,CAAC,IAAI;YACf,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,SAAS,EAAE,IAAI,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,MAAM,KAAK,CAAC;IACd,CAAC;IAED,IAAI,IAAoB,CAAC;IACzB,IAAI,CAAC;QACH,kEAAkE;QAClE,mEAAmE;QACnE,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE;YACtB,KAAK,EAAE,MAAM;YACb,GAAG,CAAC,IAAI,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACrD,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,GAAG,CAAC,EAAE,KAAK,EAAE,sBAAsB,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QACnF,MAAM,IAAI,iBAAiB,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC7C,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;IACzB,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,mEAAmE;QACnE,gDAAgD;QAChD,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QAC7B,GAAG,CAAC,EAAE,KAAK,EAAE,sBAAsB,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QACnF,MAAM,IAAI,iBAAiB,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC,CAAC;IACjF,CAAC;IAED,GAAG,CAAC;QACF,KAAK,EAAE,cAAc;QACrB,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,OAAO,EAAE,CAAC,CAAC,IAAI;QACf,IAAI,EAAE,UAAU,CAAC,IAAI,CAAC;KACvB,CAAC,CAAC;IAEH,MAAM,YAAY,GAAG,IAAI,YAAY,EAA+B,CAAC;IACrE,MAAM,KAAK,GAAG,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC/C,MAAM,UAAU,GAAG,IAAI,UAAU,EAAE,CAAC;IACpC,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,IAAI,UAAU,GAAsC,IAAI,CAAC;IACzD,IAAI,YAAY,GAAG,EAAE,CAAC;IACtB,MAAM,YAAY,GAAa,EAAE,CAAC;IAClC,MAAM,aAAa,GAAmB,EAAE,CAAC;IACzC,IAAI,IAAI,GAAG,KAAK,CAAC;IACjB,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,IAAI,SAAS,GAAG,KAAK,CAAC;IACtB,IAAI,QAAQ,GAAkB,IAAI,CAAC;IACnC,IAAI,WAAW,GAAG,KAAK,CAAC;IACxB,IAAI,aAAa,GAAG,KAAK,CAAC;IAC1B,IAAI,SAAS,GAAY,IAAI,CAAC;IAE9B,MAAM,UAAU,GAAG,CAAC,GAA0B,EAAQ,EAAE;QACtD,IAAI,CAAC,IAAI;YAAE,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACpC,CAAC,CAAC;IACF,MAAM,QAAQ,GAAG,GAAS,EAAE;QAC1B,UAAU,CAAC,SAAS,CAAC,CAAC;QACtB,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,aAAa,CAAC,CAAC;IACpE,CAAC,CAAC;IAEF,MAAM,SAAS,GAAG,CAAC,IAAY,EAAW,EAAE;QAC1C,IAAI,CAAC;YACH,KAAK,CAAC,KAAK,CAAC,kBAAkB,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC,CAAC;YACpD,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,UAAU,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,oCAAoC,EAAE,CAAC,CAAC;YACnF,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,SAAS,GAAG,GAAS,EAAE;QAC3B,aAAa,GAAG,KAAK,CAAC;QACtB,UAAU,GAAG,IAAI,YAAY,EAAgB,CAAC;QAC9C,YAAY,GAAG,GAAG,IAAI,CAAC,SAAS,SAAS,EAAE,WAAW,EAAE,CAAC;QACzD,GAAG,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,CAAC;QAC9E,KAAK,MAAM,IAAI,IAAI,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC;YAAE,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClE,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAChC,CAAC,CAAC;IAEF,MAAM,OAAO,GAAG,CAAC,IAAqC,EAAQ,EAAE;QAC9D,IAAI,UAAU,KAAK,IAAI;YAAE,OAAO;QAChC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtB,UAAU,CAAC,KAAK,EAAE,CAAC;QACnB,GAAG,CAAC;YACF,KAAK,EAAE,UAAU;YACjB,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,MAAM,EAAE,YAAY;YACpB,KAAK,EAAE,IAAI,CAAC,KAAK;SAClB,CAAC,CAAC;QACH,UAAU,GAAG,IAAI,CAAC;QAClB,WAAW,GAAG,KAAK,CAAC;QACpB,kEAAkE;QAClE,IAAI,IAAI,IAAI,OAAO;YAAE,OAAO;QAC5B,MAAM,IAAI,GAAG,YAAY,CAAC,KAAK,EAAE,CAAC;QAClC,IAAI,IAAI,KAAK,SAAS,IAAI,SAAS,CAAC,IAAI,CAAC;YAAE,SAAS,EAAE,CAAC;IACzD,CAAC,CAAC;IAEF,MAAM,UAAU,GAAG,CAAC,KAAmB,EAAiB,EAAE;QACxD,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAC3B,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC;YACvB,aAAa,GAAG,IAAI,CAAC;QACvB,CAAC;QACD,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;YACxB,gEAAgE;YAChE,8DAA8D;YAC9D,OAAO,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC;QACD,oEAAoE;QACpE,0CAA0C;QAC1C,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1B,IAAI,aAAa,CAAC,MAAM,GAAG,WAAW,EAAE,CAAC;YACvC,MAAM,WAAW,GAAG,aAAa,CAAC,SAAS,CACzC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS,CAC3E,CAAC;YACF,aAAa,CAAC,MAAM,CAAC,WAAW,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;QAChE,CAAC;QACD,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC,CAAC;IAEF,MAAM,UAAU,GAAG,KAAK,IAAmB,EAAE;QAC3C,MAAM,KAAK,GAAG,IAAI,UAAU,EAAE,CAAC;QAC/B,MAAM,UAAU,GAAG,KAAK,EAAE,IAAY,EAAiB,EAAE;YACvD,IAAI,MAAM,GAAmC,IAAI,CAAC;YAClD,IAAI,CAAC;gBACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAA4B,CAAC;YACvD,CAAC;YAAC,MAAM,CAAC;gBACP,MAAM,IAAI,GAAG,iBAAiB,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;gBACxC,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;oBAClB,MAAM,UAAU,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,wBAAwB,IAAI,GAAG,EAAE,CAAC,CAAC;gBACtF,CAAC;gBACD,OAAO;YACT,CAAC;YACD,+DAA+D;YAC/D,qEAAqE;YACrE,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;YAChE,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC7B,oEAAoE;gBACpE,qEAAqE;gBACrE,2DAA2D;gBAC3D,KAAK,MAAM,KAAK,IAAI,MAAM;oBAAE,MAAM,UAAU,CAAC,KAAK,CAAC,CAAC;gBACpD,IAAI,MAAM,CAAC,QAAQ,KAAK,IAAI;oBAAE,WAAW,GAAG,IAAI,CAAC;gBACjD,OAAO,CAAC;oBACN,IAAI,EAAE,MAAM;oBACZ,QAAQ,EAAE,IAAI;oBACd,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO;iBACjE,CAAC,CAAC;gBACH,OAAO;YACT,CAAC;YACD,KAAK,MAAM,KAAK,IAAI,MAAM;gBAAE,MAAM,UAAU,CAAC,KAAK,CAAC,CAAC;QACtD,CAAC,CAAC;QACF,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YACtC,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;gBAAE,MAAM,UAAU,CAAC,IAAI,CAAC,CAAC;QAC/D,CAAC;QACD,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC;QAC3B,IAAI,IAAI,KAAK,IAAI;YAAE,MAAM,UAAU,CAAC,IAAI,CAAC,CAAC;IAC5C,CAAC,CAAC;IAEF,MAAM,UAAU,GAAG,KAAK,IAAmB,EAAE;QAC3C,MAAM,KAAK,GAAG,IAAI,UAAU,EAAE,CAAC;QAC/B,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YACtC,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;gBACrC,MAAM,KAAK,GAAG,iBAAiB,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;gBACzC,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;oBACnB,MAAM,UAAU,CAAC;wBACf,IAAI,EAAE,OAAO;wBACb,IAAI,EAAE,KAAK;wBACX,OAAO,EAAE,wBAAwB,KAAK,GAAG;qBAC1C,CAAC,CAAC;oBACH,SAAS;gBACX,CAAC;gBACD,MAAM,IAAI,GAAG,uBAAuB,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;gBAC9C,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;oBAClB,MAAM,UAAU,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,cAAc,IAAI,EAAE,EAAE,CAAC,CAAC;oBACnE,SAAS;gBACX,CAAC;gBACD,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACxB,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,UAAU,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,EAAE;QACpF,SAAS,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,MAAM,KAAK,UAAU,CAAC,EAAE,MAAM,IAAI,IAAI,CAAC;IACjG,CAAC,CAAC,CAAC;IAEH,IAAI,gBAAgB,GAAe,GAAG,EAAE,GAAE,CAAC,CAAC;IAC5C,MAAM,QAAQ,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QAC7C,gBAAgB,GAAG,OAAO,CAAC;IAC7B,CAAC,CAAC,CAAC;IAEH,IAAI,eAAe,GAAG,KAAK,CAAC;IAC5B,MAAM,QAAQ,GAAG,GAAS,EAAE;QAC1B,IAAI,SAAS;YAAE,OAAO;QACtB,SAAS,GAAG,IAAI,CAAC;QACjB,MAAM,KAAK,GAAc,KAAK,CAAC,SAAS;YACtC,CAAC,CAAC,OAAO;YACT,CAAC,CAAC,QAAQ,KAAK,CAAC;gBACd,CAAC,CAAC,OAAO;gBACT,CAAC,CAAC,QAAQ,KAAK,IAAI;oBACjB,CAAC,CAAC,QAAQ;oBACV,CAAC,CAAC,OAAO,CAAC;QAChB,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;YACvB,KAAK,UAAU,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,wBAAwB,MAAM,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC,CAAC;QAC3F,CAAC;QACD,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5B,qEAAqE;YACrE,+CAA+C;YAC/C,KAAK,UAAU,CAAC;gBACd,IAAI,EAAE,OAAO;gBACb,OAAO,EAAE,GAAG,YAAY,CAAC,MAAM,uCAAuC;aACvE,CAAC,CAAC;YACH,GAAG,CAAC;gBACF,KAAK,EAAE,eAAe;gBACtB,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,KAAK,EAAE,YAAY,CAAC,MAAM;gBAC1B,OAAO,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;aAC3C,CAAC,CAAC;YACH,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC;QAC1B,CAAC;QACD,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;QAC3C,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,EAAE,CAAC;YAC3E,GAAG,CAAC;gBACF,KAAK,EAAE,wBAAwB;gBAC/B,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,KAAK,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;aACxC,CAAC,CAAC;QACL,CAAC;QACD,YAAY,CAAC,KAAK,EAAE,CAAC;QACrB,GAAG,CAAC;YACF,KAAK,EAAE,eAAe;YACtB,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,QAAQ;YACR,KAAK;YACL,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/C,GAAG,CAAC,KAAK,KAAK,OAAO,IAAI,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,UAAU,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC1F,CAAC,CAAC;QACH,gBAAgB,EAAE,CAAC;IACrB,CAAC,CAAC;IAEF,KAAK,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;QAC7B,IAAI,GAAG,IAAI,CAAC;QACZ,QAAQ,GAAG,IAAI,CAAC;QAChB,sEAAsE;QACtE,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,EAAE;YAC3C,eAAe,GAAG,IAAI,CAAC;YACvB,UAAU,EAAE,mBAAmB,EAAE,CAAC;YAClC,IAAI,CAAC,aAAa,EAAE,CAAC;YACrB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC;QACtC,CAAC,EAAE,aAAa,CAAC,CAAC;QAClB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE;YACrB,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;YACnC,QAAQ,EAAE,CAAC;QACb,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,KAAK,IAAmB,EAAE;QACtC,IAAI,OAAO;YAAE,OAAO,QAAQ,CAAC;QAC7B,OAAO,GAAG,IAAI,CAAC;QACf,IAAI,CAAC;YACH,KAAK,CAAC,GAAG,EAAE,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,mEAAmE;QACrE,CAAC;QACD,sEAAsE;QACtE,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,EAAE,cAAc,CAAC,CAAC;QAC3E,MAAM,QAAQ,CAAC;QACf,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;IACtC,CAAC,CAAC;IAEF,OAAO;QACL,kEAAkE;QAClE,uEAAuE;QACvE,4CAA4C;QAC5C,KAAK,EAAE,CAAC,KAAK,SAAS,CAAC;YACrB,IAAI,CAAC;gBACH,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,YAAY;oBAAE,MAAM,IAAI,CAAC;YACpD,CAAC;oBAAS,CAAC;gBACT,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI;oBAAE,KAAK,KAAK,EAAE,CAAC;YACtC,CAAC;QACH,CAAC,CAAC,EAAE;QACJ,IAAI,CAAC,IAAY;YACf,IAAI,IAAI,IAAI,OAAO;gBAAE,MAAM,IAAI,kBAAkB,EAAE,CAAC;YACpD,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;gBACxB,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACxB,GAAG,CAAC;oBACF,KAAK,EAAE,MAAM;oBACb,SAAS,EAAE,IAAI,CAAC,SAAS;oBACzB,MAAM,EAAE,YAAY;oBACpB,WAAW,EAAE,QAAQ;iBACtB,CAAC,CAAC;gBACH,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC;YACnC,CAAC;YACD,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;gBAAE,MAAM,IAAI,kBAAkB,EAAE,CAAC;YACrD,SAAS,EAAE,CAAC;YACZ,GAAG,CAAC;gBACF,KAAK,EAAE,MAAM;gBACb,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,MAAM,EAAE,YAAY;gBACpB,WAAW,EAAE,SAAS;aACvB,CAAC,CAAC;YACH,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC;QACpC,CAAC;QACD,KAAK;KACN,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* streamTurn: the spawn-per-turn headless runner. Spawn, drain both stdio
|
|
3
|
+
* streams concurrently, decode typed HarnessEvents, watchdog stalls (only
|
|
4
|
+
* for none-granularity invocations - a structured stream proves its own
|
|
5
|
+
* liveness), classify the exit, always end with `done` (spawn failures
|
|
6
|
+
* included). Runtime primitives are injected (D-005); structured boundary
|
|
7
|
+
* events (spawn/exit/stall, argv redacted by POSITION) are always-on
|
|
8
|
+
* evidence, not diagnostics. An abandoned turn (consumer breaks early)
|
|
9
|
+
* closes backpressure, disposes output, stops the child, and awaits both
|
|
10
|
+
* pumps before it returns.
|
|
11
|
+
*/
|
|
12
|
+
import { type LaunchOptions } from "../interpretation/argv.js";
|
|
13
|
+
import type { HarnessDescriptor } from "../knowledge/descriptor.js";
|
|
14
|
+
import type { RunnerDeps } from "./deps.js";
|
|
15
|
+
import type { HarnessEvent } from "./events.js";
|
|
16
|
+
/** SIGTERM -> SIGKILL escalation budget for a child that ignores the first
|
|
17
|
+
* signal, and the grace allowed for pipes still held open (by a grandchild)
|
|
18
|
+
* after the process itself exited. */
|
|
19
|
+
export declare const KILL_GRACE_MS = 5000;
|
|
20
|
+
export declare const PIPE_GRACE_MS = 2000;
|
|
21
|
+
/** Redact by POSITION, not shape: the prompt is a known argv slot and is
|
|
22
|
+
* masked wholesale (content never reaches a log line - v1 D-005); every
|
|
23
|
+
* other token is kept unless it is secret-shaped. */
|
|
24
|
+
export declare const redactArgv: (argv: readonly string[], prompt?: string) => string[];
|
|
25
|
+
/** Bounded tail of unmatched stderr - the crash context a nonzero exit is
|
|
26
|
+
* explained by (v1 kept the turn's output slice for exactly this). Shared
|
|
27
|
+
* with the session runner. */
|
|
28
|
+
export declare class StderrTail {
|
|
29
|
+
private readonly lines;
|
|
30
|
+
private bytes;
|
|
31
|
+
push(line: string): void;
|
|
32
|
+
snapshot(): readonly string[];
|
|
33
|
+
}
|
|
34
|
+
export interface TurnRunOptions extends LaunchOptions {
|
|
35
|
+
/** Resume this session id instead of launching fresh - the turn spawns
|
|
36
|
+
* with the descriptor's resume grammar, and identity decoding treats a
|
|
37
|
+
* DIFFERENT announced id as a rotation anomaly. */
|
|
38
|
+
readonly resume?: string;
|
|
39
|
+
/** Working directory for the spawned harness. */
|
|
40
|
+
readonly cwd?: string;
|
|
41
|
+
}
|
|
42
|
+
export declare function streamTurn(h: HarnessDescriptor, opts: TurnRunOptions, deps: RunnerDeps): AsyncIterable<HarnessEvent>;
|
|
43
|
+
//# sourceMappingURL=stream-turn.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream-turn.d.ts","sourceRoot":"","sources":["../../src/execution/stream-turn.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAGL,KAAK,aAAa,EAEnB,MAAM,2BAA2B,CAAC;AAGnC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAGpE,OAAO,KAAK,EAAE,UAAU,EAAkB,MAAM,WAAW,CAAC;AAC5D,OAAO,KAAK,EAAa,YAAY,EAAE,MAAM,aAAa,CAAC;AAO3D;;sCAEsC;AACtC,eAAO,MAAM,aAAa,OAAQ,CAAC;AACnC,eAAO,MAAM,aAAa,OAAQ,CAAC;AAWnC;;qDAEqD;AACrD,eAAO,MAAM,UAAU,SAAU,SAAS,MAAM,EAAE,WAAW,MAAM,KAAG,MAAM,EAKxE,CAAC;AAEL;;8BAE8B;AAC9B,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgB;IACtC,OAAO,CAAC,KAAK,CAAK;IAClB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAOvB;IACD,QAAQ,IAAI,SAAS,MAAM,EAAE,CAE5B;CACF;AAED,MAAM,WAAW,cAAe,SAAQ,aAAa;IACnD;;uDAEmD;IACnD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,iDAAiD;IACjD,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAuB,UAAU,CAC/B,CAAC,EAAE,iBAAiB,EACpB,IAAI,EAAE,cAAc,EACpB,IAAI,EAAE,UAAU,GACf,aAAa,CAAC,YAAY,CAAC,CA8N7B"}
|