@loucompanion/forge-bridge 0.1.3-dev.d46a8e73d03d → 0.1.3-dev.eeefdb0d19c1
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/bridge/bridge.base.d.ts +2 -1
- package/dist/bridge/bridge.service.d.ts +22 -3
- package/dist/bridge/bridge.service.js +416 -40
- package/dist/bridge/bridge.types.d.ts +59 -1
- package/dist/cleanup/cleanup.service.d.ts +13 -2
- package/dist/cleanup/cleanup.service.js +435 -3
- package/dist/cleanup/cleanup.types.d.ts +10 -0
- package/dist/cleanup/index.d.ts +1 -1
- package/dist/cleanup/index.js +1 -1
- package/dist/cleanup/internals.d.ts +2 -2
- package/dist/cleanup/internals.js +1 -1
- package/dist/cli/cli.help.js +37 -3
- package/dist/cli/cli.service.d.ts +30 -2
- package/dist/cli/cli.service.js +182 -23
- package/dist/cli/local-config.d.ts +4 -0
- package/dist/cli/local-config.js +41 -1
- package/dist/runtime/attempt-node-runtime-launcher.d.ts +17 -0
- package/dist/runtime/attempt-node-runtime-launcher.js +101 -0
- package/dist/runtime/attempt-process-supervisor-registry.d.ts +20 -0
- package/dist/runtime/attempt-process-supervisor-registry.js +64 -0
- package/dist/runtime/attempt-process-supervisor.d.ts +86 -0
- package/dist/runtime/attempt-process-supervisor.js +343 -0
- package/dist/runtime/generated-output-reset.d.ts +10 -0
- package/dist/runtime/generated-output-reset.js +103 -0
- package/dist/runtime/host-listener-inspector.d.ts +44 -0
- package/dist/runtime/host-listener-inspector.js +324 -0
- package/dist/runtime/host-port-broker.d.ts +76 -0
- package/dist/runtime/host-port-broker.js +333 -0
- package/dist/runtime/host-runtime-contract.d.ts +47 -0
- package/dist/runtime/host-runtime-contract.js +700 -0
- package/dist/runtime/host-runtime-lease.d.ts +133 -0
- package/dist/runtime/host-runtime-lease.js +1460 -0
- package/dist/runtime/host-runtime-promotion.d.ts +23 -0
- package/dist/runtime/host-runtime-promotion.js +159 -0
- package/dist/runtime/node-host-runtime-adapter.d.ts +51 -0
- package/dist/runtime/node-host-runtime-adapter.js +268 -0
- package/dist/runtime/playwright-host-runtime-adapter.d.ts +20 -0
- package/dist/runtime/playwright-host-runtime-adapter.js +220 -0
- package/dist/runtime/runtime-isolation-lease.d.ts +67 -0
- package/dist/runtime/runtime-isolation-lease.js +158 -0
- package/dist/sandbox/preflight.d.ts +14 -0
- package/dist/sandbox/preflight.js +91 -12
- package/dist/sandbox/process.js +125 -40
- package/dist/sandbox/repository-lock.js +37 -1
- package/dist/sandbox/runtime.d.ts +66 -3
- package/dist/sandbox/runtime.js +670 -105
- package/dist/sandbox/sandbox.types.d.ts +3 -0
- package/dist/sandbox/smoke.d.ts +76 -0
- package/dist/sandbox/smoke.js +380 -0
- package/dist/sandbox/worker-supervisor.js +1 -1
- package/dist/sandbox/worker.js +2 -5
- package/dist/sandbox/workspace.service.d.ts +1 -0
- package/dist/sandbox/workspace.service.js +28 -5
- package/dist/session/managed-attempt-tools.d.ts +12 -0
- package/dist/session/managed-attempt-tools.js +350 -0
- package/dist/session/phase-completion.artifacts.js +9 -2
- package/dist/session/phase-completion.d.ts +4 -2
- package/dist/session/phase-completion.helpers.js +27 -3
- package/dist/session/phase-completion.js +12 -3
- package/dist/session/phase-completion.prompts.d.ts +3 -3
- package/dist/session/phase-completion.prompts.js +19 -5
- package/dist/session/phase-completion.runtime.d.ts +12 -1
- package/dist/session/phase-completion.runtime.js +127 -7
- package/dist/session/phase-completion.schemas.js +108 -3
- package/dist/session/phase-completion.validation.d.ts +4 -1
- package/dist/session/phase-completion.validation.js +106 -2
- package/dist/session/provider-cli/ci-repair-readiness.d.ts +8 -0
- package/dist/session/provider-cli/ci-repair-readiness.js +90 -0
- package/dist/session/provider-cli/provider-cli.artifacts.d.ts +1 -1
- package/dist/session/provider-cli/provider-cli.artifacts.js +28 -4
- package/dist/session/provider-cli/provider-cli.deterministic.js +47 -1
- package/dist/session/provider-cli/provider-cli.process.d.ts +16 -0
- package/dist/session/provider-cli/provider-cli.process.js +212 -25
- package/dist/session/provider-cli/provider-cli.prompts.d.ts +4 -1
- package/dist/session/provider-cli/provider-cli.prompts.js +84 -17
- package/dist/session/provider-cli/provider-cli.qa-sidecars.js +1 -0
- package/dist/session/provider-cli/provider-cli.runtime.d.ts +1 -1
- package/dist/session/provider-cli/provider-cli.runtime.js +3 -2
- package/dist/session/provider-cli/provider-cli.service.d.ts +3 -2
- package/dist/session/provider-cli/provider-cli.service.js +254 -71
- package/dist/session/provider-cli/provider-cli.types.d.ts +5 -0
- package/dist/session/provider-cli/provider-output-state.d.ts +2 -0
- package/dist/session/provider-cli/provider-output-state.js +30 -2
- package/dist/session/session-redaction.d.ts +3 -0
- package/dist/session/session-redaction.js +23 -0
- package/dist/session/session.base.d.ts +6 -1
- package/dist/session/session.service.d.ts +8 -2
- package/dist/session/session.service.js +436 -41
- package/dist/session/session.types.d.ts +55 -0
- package/dist/session/session.types.js +69 -2
- package/dist/shared/path/path.js +3 -1
- package/dist/shared/process/host-process-recovery.d.ts +12 -0
- package/dist/shared/process/host-process-recovery.js +78 -0
- package/dist/shared/process/host-process-supervisor.d.ts +57 -0
- package/dist/shared/process/host-process-supervisor.js +282 -0
- package/dist/shared/process/process.d.ts +1 -0
- package/dist/shared/process/process.js +1 -0
- package/dist/shared/redaction/redaction.js +6 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/worktree/artifact-injector.d.ts +3 -2
- package/dist/worktree/artifact-injector.js +43 -4
- package/dist/worktree/dependency-warmer.d.ts +10 -1
- package/dist/worktree/dependency-warmer.js +94 -5
- package/dist/worktree/index.d.ts +1 -0
- package/dist/worktree/index.js +1 -0
- package/dist/worktree/prior-phase-artifact-hydrator.d.ts +2 -0
- package/dist/worktree/prior-phase-artifact-hydrator.js +136 -0
- package/dist/worktree/worktree-paths.d.ts +4 -0
- package/dist/worktree/worktree-paths.js +30 -0
- package/dist/worktree/worktree.base.d.ts +3 -0
- package/dist/worktree/worktree.service.d.ts +7 -2
- package/dist/worktree/worktree.service.js +72 -44
- package/dist/worktree/worktree.types.d.ts +3 -1
- package/package.json +3 -2
- package/runtime/windows-job-supervisor.ps1 +356 -0
- package/runtime/windows-listener-owner.ps1 +33 -0
package/dist/sandbox/process.js
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
2
|
import { StringDecoder } from "node:string_decoder";
|
|
3
|
+
const terminationSigkillDelayMs = 5_000;
|
|
4
|
+
const forcedCloseSettleDelayMs = 5_000;
|
|
5
|
+
const expectedStdinCloseErrorCodes = new Set(["EPIPE", "ECONNRESET", "ERR_STREAM_DESTROYED"]);
|
|
6
|
+
function isExpectedStdinCloseError(error) {
|
|
7
|
+
return "code" in error
|
|
8
|
+
&& typeof error.code === "string"
|
|
9
|
+
&& expectedStdinCloseErrorCodes.has(error.code);
|
|
10
|
+
}
|
|
3
11
|
export async function runSandboxProcess(request) {
|
|
4
12
|
const limit = Math.max(1024, request.maxOutputBytes ?? 1024 * 1024);
|
|
5
13
|
return await new Promise((resolve, reject) => {
|
|
@@ -14,10 +22,15 @@ export async function runSandboxProcess(request) {
|
|
|
14
22
|
let stderr = Buffer.alloc(0);
|
|
15
23
|
let truncated = false;
|
|
16
24
|
let settled = false;
|
|
25
|
+
let terminating = false;
|
|
26
|
+
let discardStdoutLineCallbacks = false;
|
|
17
27
|
let stdoutText = "";
|
|
18
28
|
const stdoutDecoder = new StringDecoder("utf8");
|
|
19
29
|
let stdoutLineChain = Promise.resolve();
|
|
20
30
|
let stdoutLineError = null;
|
|
31
|
+
let timeout = null;
|
|
32
|
+
let sigkillTimer = null;
|
|
33
|
+
let forcedSettleTimer = null;
|
|
21
34
|
const append = (current, chunk) => {
|
|
22
35
|
if (current.length >= limit) {
|
|
23
36
|
truncated = true;
|
|
@@ -31,9 +44,87 @@ export async function runSandboxProcess(request) {
|
|
|
31
44
|
}
|
|
32
45
|
return Buffer.concat([current, chunk.subarray(0, remaining)]);
|
|
33
46
|
};
|
|
34
|
-
|
|
47
|
+
const appendStderrLine = (line) => {
|
|
48
|
+
stderr = append(stderr, Buffer.from(`\n${line}\n`));
|
|
49
|
+
};
|
|
50
|
+
const cleanup = () => {
|
|
51
|
+
if (timeout)
|
|
52
|
+
clearTimeout(timeout);
|
|
53
|
+
if (sigkillTimer)
|
|
54
|
+
clearTimeout(sigkillTimer);
|
|
55
|
+
if (forcedSettleTimer)
|
|
56
|
+
clearTimeout(forcedSettleTimer);
|
|
57
|
+
child.stdout.removeListener("data", onStdoutData);
|
|
58
|
+
child.stderr.removeListener("data", onStderrData);
|
|
59
|
+
child.removeListener("error", onProcessError);
|
|
60
|
+
child.removeListener("close", onProcessClose);
|
|
61
|
+
request.signal?.removeEventListener("abort", abort);
|
|
62
|
+
};
|
|
63
|
+
const settle = async (code, force) => {
|
|
64
|
+
if (settled)
|
|
65
|
+
return;
|
|
66
|
+
settled = true;
|
|
67
|
+
discardStdoutLineCallbacks = force;
|
|
68
|
+
cleanup();
|
|
69
|
+
if (stdoutLineError) {
|
|
70
|
+
reject(stdoutLineError);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (!force) {
|
|
74
|
+
if (request.onStdoutLine)
|
|
75
|
+
stdoutText += stdoutDecoder.end();
|
|
76
|
+
if (request.onStdoutLine && stdoutText) {
|
|
77
|
+
stdoutLineChain = stdoutLineChain.then(() => request.onStdoutLine(stdoutText));
|
|
78
|
+
}
|
|
79
|
+
await stdoutLineChain.catch(error => { stdoutLineError ??= error; });
|
|
80
|
+
if (stdoutLineError) {
|
|
81
|
+
reject(stdoutLineError);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
resolve({
|
|
86
|
+
exitCode: code ?? 1,
|
|
87
|
+
stdout: stdout.toString("utf8"),
|
|
88
|
+
stderr: stderr.toString("utf8"),
|
|
89
|
+
truncated
|
|
90
|
+
});
|
|
91
|
+
};
|
|
92
|
+
const forceSettle = (reason) => {
|
|
93
|
+
if (settled)
|
|
94
|
+
return;
|
|
95
|
+
appendStderrLine(reason);
|
|
96
|
+
void settle(1, true);
|
|
97
|
+
};
|
|
98
|
+
const killChild = (signal) => {
|
|
99
|
+
if (child.exitCode !== null || child.signalCode !== null)
|
|
100
|
+
return;
|
|
101
|
+
try {
|
|
102
|
+
child.kill(signal);
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
// The process may have exited between timeout/abort and close. Still let the
|
|
106
|
+
// supervisor timers settle if close never arrives.
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
const terminate = (reason) => {
|
|
110
|
+
if (settled || terminating)
|
|
111
|
+
return;
|
|
112
|
+
terminating = true;
|
|
113
|
+
appendStderrLine(reason);
|
|
114
|
+
killChild("SIGTERM");
|
|
115
|
+
sigkillTimer = setTimeout(() => {
|
|
116
|
+
killChild("SIGKILL");
|
|
117
|
+
forcedSettleTimer = setTimeout(() => forceSettle("process did not close after SIGKILL; forcing supervisor settlement"), forcedCloseSettleDelayMs);
|
|
118
|
+
forcedSettleTimer.unref?.();
|
|
119
|
+
}, terminationSigkillDelayMs);
|
|
120
|
+
sigkillTimer.unref?.();
|
|
121
|
+
};
|
|
122
|
+
const abort = () => terminate(String(request.signal?.reason ?? "process aborted"));
|
|
123
|
+
const onStdoutData = (chunk) => {
|
|
124
|
+
if (settled)
|
|
125
|
+
return;
|
|
35
126
|
stdout = append(stdout, chunk);
|
|
36
|
-
if (!request.onStdoutLine)
|
|
127
|
+
if (!request.onStdoutLine || settled)
|
|
37
128
|
return;
|
|
38
129
|
stdoutText += stdoutDecoder.write(chunk);
|
|
39
130
|
if (Buffer.byteLength(stdoutText, "utf8") > 1024 * 1024 && !stdoutText.includes("\n")) {
|
|
@@ -48,6 +139,8 @@ export async function runSandboxProcess(request) {
|
|
|
48
139
|
child.stdout.pause();
|
|
49
140
|
for (const line of lines) {
|
|
50
141
|
stdoutLineChain = stdoutLineChain.then(async () => {
|
|
142
|
+
if (discardStdoutLineCallbacks)
|
|
143
|
+
return;
|
|
51
144
|
if (Buffer.byteLength(line, "utf8") > 1024 * 1024)
|
|
52
145
|
throw new Error("sandbox process emitted an oversized stdout line");
|
|
53
146
|
await request.onStdoutLine(line);
|
|
@@ -62,57 +155,49 @@ export async function runSandboxProcess(request) {
|
|
|
62
155
|
if (!settled)
|
|
63
156
|
child.stdout.resume();
|
|
64
157
|
});
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
|
|
158
|
+
};
|
|
159
|
+
const onStderrData = (chunk) => {
|
|
160
|
+
if (!settled)
|
|
161
|
+
stderr = append(stderr, chunk);
|
|
162
|
+
};
|
|
163
|
+
const onProcessError = (error) => {
|
|
68
164
|
if (!settled) {
|
|
69
165
|
settled = true;
|
|
166
|
+
cleanup();
|
|
70
167
|
reject(error);
|
|
71
168
|
}
|
|
72
|
-
}
|
|
73
|
-
const
|
|
74
|
-
if (
|
|
169
|
+
};
|
|
170
|
+
const onStdinError = (error) => {
|
|
171
|
+
if (isExpectedStdinCloseError(error))
|
|
75
172
|
return;
|
|
76
|
-
|
|
77
|
-
setTimeout(() => child.kill("SIGKILL"), 5_000).unref?.();
|
|
78
|
-
if (!settled) {
|
|
79
|
-
// Completion is still resolved by close so stderr remains available.
|
|
80
|
-
stderr = append(stderr, Buffer.from(`\n${reason}\n`));
|
|
81
|
-
}
|
|
173
|
+
onProcessError(error);
|
|
82
174
|
};
|
|
83
|
-
const
|
|
175
|
+
const onProcessClose = (code) => {
|
|
176
|
+
void settle(code, false);
|
|
177
|
+
};
|
|
178
|
+
child.stdout.on("data", onStdoutData);
|
|
179
|
+
child.stderr.on("data", onStderrData);
|
|
180
|
+
child.on("error", onProcessError);
|
|
181
|
+
child.on("close", onProcessClose);
|
|
182
|
+
// Keep this listener for the lifetime of stdin. A pipe error can be emitted
|
|
183
|
+
// after the child close event has settled the supervisor promise.
|
|
184
|
+
child.stdin?.on("error", onStdinError);
|
|
185
|
+
timeout = request.timeoutMs
|
|
84
186
|
? setTimeout(() => terminate(`process timeout after ${request.timeoutMs}ms`), request.timeoutMs)
|
|
85
187
|
: null;
|
|
86
188
|
timeout?.unref?.();
|
|
87
|
-
const abort = () => terminate(String(request.signal?.reason ?? "process aborted"));
|
|
88
189
|
request.signal?.addEventListener("abort", abort, { once: true });
|
|
89
|
-
if (request.
|
|
90
|
-
|
|
190
|
+
if (request.signal?.aborted) {
|
|
191
|
+
abort();
|
|
91
192
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
settled = true;
|
|
96
|
-
if (timeout)
|
|
97
|
-
clearTimeout(timeout);
|
|
98
|
-
request.signal?.removeEventListener("abort", abort);
|
|
99
|
-
if (request.onStdoutLine)
|
|
100
|
-
stdoutText += stdoutDecoder.end();
|
|
101
|
-
if (request.onStdoutLine && stdoutText) {
|
|
102
|
-
stdoutLineChain = stdoutLineChain.then(() => request.onStdoutLine(stdoutText));
|
|
193
|
+
if (request.input !== undefined) {
|
|
194
|
+
try {
|
|
195
|
+
child.stdin.end(request.input);
|
|
103
196
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
reject(stdoutLineError);
|
|
107
|
-
return;
|
|
197
|
+
catch (error) {
|
|
198
|
+
onStdinError(error instanceof Error ? error : new Error(String(error)));
|
|
108
199
|
}
|
|
109
|
-
|
|
110
|
-
exitCode: code ?? 1,
|
|
111
|
-
stdout: stdout.toString("utf8"),
|
|
112
|
-
stderr: stderr.toString("utf8"),
|
|
113
|
-
truncated
|
|
114
|
-
});
|
|
115
|
-
});
|
|
200
|
+
}
|
|
116
201
|
});
|
|
117
202
|
}
|
|
118
203
|
export async function requireSandboxProcess(request) {
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { createHash, randomUUID } from "node:crypto";
|
|
2
|
+
import { constants as fsConstants } from "node:fs";
|
|
2
3
|
import fs from "node:fs/promises";
|
|
3
4
|
import path from "node:path";
|
|
5
|
+
const LOCK_HEARTBEAT_INTERVAL_MS = 30_000;
|
|
6
|
+
const LOCK_STALE_AFTER_MS = 2 * 60_000;
|
|
4
7
|
export class RepositoryCoordinatorLock {
|
|
5
8
|
stateRoot;
|
|
6
9
|
constructor(stateRoot) {
|
|
@@ -41,10 +44,12 @@ export class RepositoryCoordinatorLock {
|
|
|
41
44
|
await abortableDelay(50, signal);
|
|
42
45
|
}
|
|
43
46
|
}
|
|
47
|
+
const heartbeat = startHeartbeat(target, token);
|
|
44
48
|
try {
|
|
45
49
|
return await action();
|
|
46
50
|
}
|
|
47
51
|
finally {
|
|
52
|
+
clearInterval(heartbeat);
|
|
48
53
|
const owner = await readOwner(target);
|
|
49
54
|
if (owner?.token === token)
|
|
50
55
|
await fs.rm(target, { force: true });
|
|
@@ -58,7 +63,7 @@ async function staleLock(target) {
|
|
|
58
63
|
const owner = await readOwner(target);
|
|
59
64
|
if (!owner || typeof owner.pid !== "number" || !Number.isInteger(owner.pid) || owner.pid <= 0)
|
|
60
65
|
return true;
|
|
61
|
-
if (Date.now() - stat.mtimeMs
|
|
66
|
+
if (Date.now() - stat.mtimeMs >= LOCK_STALE_AFTER_MS)
|
|
62
67
|
return true;
|
|
63
68
|
try {
|
|
64
69
|
process.kill(owner.pid, 0);
|
|
@@ -68,6 +73,37 @@ async function staleLock(target) {
|
|
|
68
73
|
return true;
|
|
69
74
|
}
|
|
70
75
|
}
|
|
76
|
+
function startHeartbeat(target, token) {
|
|
77
|
+
let refreshing = false;
|
|
78
|
+
const timer = setInterval(() => {
|
|
79
|
+
if (refreshing)
|
|
80
|
+
return;
|
|
81
|
+
refreshing = true;
|
|
82
|
+
void refreshHeartbeat(target, token).finally(() => { refreshing = false; });
|
|
83
|
+
}, LOCK_HEARTBEAT_INTERVAL_MS);
|
|
84
|
+
timer.unref?.();
|
|
85
|
+
return timer;
|
|
86
|
+
}
|
|
87
|
+
async function refreshHeartbeat(target, token) {
|
|
88
|
+
let handle = null;
|
|
89
|
+
try {
|
|
90
|
+
handle = await fs.open(target, fsConstants.O_RDWR | fsConstants.O_NOFOLLOW);
|
|
91
|
+
const stat = await handle.stat();
|
|
92
|
+
if (!stat.isFile() || stat.size > 16 * 1024)
|
|
93
|
+
return;
|
|
94
|
+
const owner = await handle.readFile("utf8").then(value => JSON.parse(value)).catch(() => null);
|
|
95
|
+
if (owner?.token !== token)
|
|
96
|
+
return;
|
|
97
|
+
const now = new Date();
|
|
98
|
+
await handle.utimes(now, now);
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
// A missing or replaced lock is no longer owned by this action.
|
|
102
|
+
}
|
|
103
|
+
finally {
|
|
104
|
+
await handle?.close().catch(() => undefined);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
71
107
|
async function readOwner(target) {
|
|
72
108
|
return await fs.readFile(target, "utf8").then(value => JSON.parse(value)).catch(() => null);
|
|
73
109
|
}
|
|
@@ -2,6 +2,7 @@ import type { BridgeServiceConfig } from "../bridge/bridge.types.js";
|
|
|
2
2
|
import type { SessionEventSink } from "../session/session.base.js";
|
|
3
3
|
import { type RunOnceDispatchPacket, type RunOnceResultPacket } from "../session/session.types.js";
|
|
4
4
|
import type { SandboxService, ValidatedSandboxContract } from "./sandbox.types.js";
|
|
5
|
+
import { type RuntimeIsolationLease } from "../runtime/runtime-isolation-lease.js";
|
|
5
6
|
export interface SandboxRuntime {
|
|
6
7
|
runOnce(dispatch: RunOnceDispatchPacket, sink: SessionEventSink, signal?: AbortSignal): Promise<RunOnceResultPacket>;
|
|
7
8
|
reap(options?: SandboxReapOptions): Promise<void>;
|
|
@@ -41,6 +42,28 @@ export interface SandboxRuntimeSnapshot {
|
|
|
41
42
|
readonly active: number;
|
|
42
43
|
readonly degraded: number;
|
|
43
44
|
}
|
|
45
|
+
export interface SandboxContainerMemoryPeak {
|
|
46
|
+
readonly containerId: string;
|
|
47
|
+
readonly name: string;
|
|
48
|
+
readonly role: string;
|
|
49
|
+
readonly peakMemoryBytes: number;
|
|
50
|
+
}
|
|
51
|
+
export interface SandboxPeakMemoryTelemetry {
|
|
52
|
+
readonly schemaVersion: 1;
|
|
53
|
+
readonly source: "docker_stats_sampled";
|
|
54
|
+
readonly sampleIntervalMs: number;
|
|
55
|
+
readonly sampleCount: number;
|
|
56
|
+
readonly failedSampleCount: number;
|
|
57
|
+
readonly peakMemoryBytes: number;
|
|
58
|
+
readonly firstSampledAt: string;
|
|
59
|
+
readonly lastSampledAt: string;
|
|
60
|
+
readonly containers: readonly SandboxContainerMemoryPeak[];
|
|
61
|
+
}
|
|
62
|
+
export interface DockerStatsMemorySample {
|
|
63
|
+
readonly containerId: string;
|
|
64
|
+
readonly name: string;
|
|
65
|
+
readonly memoryBytes: number;
|
|
66
|
+
}
|
|
44
67
|
export interface SandboxPublicationGrantRequest {
|
|
45
68
|
readonly dispatchAttemptId: string;
|
|
46
69
|
readonly leaseId: string;
|
|
@@ -84,6 +107,7 @@ export declare class DockerSandboxRuntime implements SandboxRuntime {
|
|
|
84
107
|
private buildImageCore;
|
|
85
108
|
private runBuildStage;
|
|
86
109
|
private ensureBuildxBuilder;
|
|
110
|
+
private stopBuildxBuilder;
|
|
87
111
|
private initializeVolumes;
|
|
88
112
|
private inspectContainerState;
|
|
89
113
|
private initializeServiceSecrets;
|
|
@@ -102,9 +126,12 @@ export declare class DockerSandboxRuntime implements SandboxRuntime {
|
|
|
102
126
|
private readImageCacheRecord;
|
|
103
127
|
private collectExpiredImages;
|
|
104
128
|
private purgeRestrictedAuditArtifacts;
|
|
129
|
+
private inspectImageMetadata;
|
|
130
|
+
private startPeakMemorySampler;
|
|
105
131
|
private docker;
|
|
106
132
|
private dockerArgs;
|
|
107
133
|
}
|
|
134
|
+
export declare function managedBranchUpdateExpectedValue(current: string, expectedInput: string, imported: string): string;
|
|
108
135
|
export declare function publicationPushArgs(branch: string, resultCommitSha: string, inputCommitSha: string, remoteCommitSha: string, remote?: string): string[] | null;
|
|
109
136
|
export declare function validatePublicationCredential(credential: SandboxPublicationCredential, nowMs?: number): void;
|
|
110
137
|
export declare function publicationCredentialEnvironment(credential: SandboxPublicationCredential, environment?: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
|
|
@@ -129,6 +156,7 @@ export declare function selectSandboxConfigRefs(executionPolicy: string, configu
|
|
|
129
156
|
readonly refs: readonly string[];
|
|
130
157
|
readonly approvedSha: string | null;
|
|
131
158
|
};
|
|
159
|
+
export declare function selectSandboxInputRefs(worktreeKey: string, baseBranch: string): readonly string[];
|
|
132
160
|
export declare function sandboxTimeLimits(environment?: NodeJS.ProcessEnv): {
|
|
133
161
|
readonly hardWallMs: number;
|
|
134
162
|
readonly idleMs: number;
|
|
@@ -144,8 +172,10 @@ export interface ImageCacheRecord {
|
|
|
144
172
|
readonly overlayTag: string;
|
|
145
173
|
readonly imageDigest: string;
|
|
146
174
|
readonly helperImageDigest: string;
|
|
175
|
+
readonly bridgeRuntimeDigest?: string;
|
|
147
176
|
readonly policyDigest: string;
|
|
148
177
|
}
|
|
178
|
+
export declare function sandboxWorkerFailureMessage(exitCode: number, stderr: string, containerError: string | null): string;
|
|
149
179
|
interface ResourceNames {
|
|
150
180
|
prefix: string;
|
|
151
181
|
container: string;
|
|
@@ -162,18 +192,30 @@ interface SandboxRuntimeVolume {
|
|
|
162
192
|
readonly name: string;
|
|
163
193
|
readonly role: string;
|
|
164
194
|
}
|
|
195
|
+
export declare function parseDockerMemoryBytes(value: string): number | null;
|
|
196
|
+
export declare function parseDockerStatsMemorySample(output: string): DockerStatsMemorySample[];
|
|
165
197
|
interface ActiveSandbox {
|
|
166
198
|
dispatchAttemptId: string;
|
|
167
199
|
fencingToken: string;
|
|
168
200
|
expiresAt: string;
|
|
169
201
|
controller: AbortController;
|
|
170
202
|
phase: "starting" | "active";
|
|
203
|
+
runtimeLease: RuntimeIsolationLease;
|
|
171
204
|
ledger: SandboxLedger | null;
|
|
172
205
|
leaseControlKey: string;
|
|
173
206
|
}
|
|
174
207
|
export declare function assertSandboxImportCurrent(expected: Pick<ActiveSandbox, "dispatchAttemptId" | "fencingToken" | "expiresAt">, current: Pick<ActiveSandbox, "dispatchAttemptId" | "fencingToken"> | undefined, signal: AbortSignal, nowMs?: number): void;
|
|
175
208
|
interface SandboxLedger {
|
|
176
|
-
schemaVersion:
|
|
209
|
+
schemaVersion: 3;
|
|
210
|
+
runtimeLease: RuntimeIsolationLease;
|
|
211
|
+
resources: ResourceNames;
|
|
212
|
+
labels: Record<string, string>;
|
|
213
|
+
includeCredentials?: boolean;
|
|
214
|
+
peakMemory?: SandboxPeakMemoryTelemetry;
|
|
215
|
+
}
|
|
216
|
+
interface LegacySandboxLedger {
|
|
217
|
+
schemaVersion: 2;
|
|
218
|
+
resourceLeaseId: string;
|
|
177
219
|
dispatchAttemptId: string;
|
|
178
220
|
fencingToken: string;
|
|
179
221
|
runnerInstanceId: string;
|
|
@@ -181,13 +223,18 @@ interface SandboxLedger {
|
|
|
181
223
|
resources: ResourceNames;
|
|
182
224
|
labels: Record<string, string>;
|
|
183
225
|
includeCredentials?: boolean;
|
|
226
|
+
peakMemory?: SandboxPeakMemoryTelemetry;
|
|
184
227
|
}
|
|
228
|
+
export declare function validSandboxLedger(value: unknown): boolean;
|
|
229
|
+
export declare function normalizeSandboxLedger(value: unknown): SandboxLedger | null;
|
|
185
230
|
export declare function resourceNames(attemptHex: string, perAttemptCaches?: readonly string[]): ResourceNames;
|
|
186
231
|
export declare function dockerObjectId(output: string, kind: "container" | "network"): string;
|
|
187
232
|
export declare function sandboxRuntimeVolumes(resources: ResourceNames, includeEgressPolicy?: boolean, includeCredentials?: boolean): SandboxRuntimeVolume[];
|
|
188
233
|
export declare function sandboxRuntimeCleanupVolumeNames(resources: ResourceNames, includeCredentials?: boolean): string[];
|
|
234
|
+
export declare function sandboxResourceLabels(dispatch: RunOnceDispatchPacket, image: string, contract: string): Record<string, string>;
|
|
189
235
|
export declare function mayReapManagedResource(labels: Readonly<Record<string, string>>, runnerId: string, liveAttempts: ReadonlySet<string>): boolean;
|
|
190
|
-
export declare function shouldReapSandboxLedger(ledger: Readonly<Pick<SandboxLedger, "dispatchAttemptId" | "fencingToken" | "runnerInstanceId" | "expiresAt">>, currentRunnerInstanceId: string, serverAttempt: SandboxAttemptSnapshot | undefined, snapshotAvailable: boolean, nowMs?: number): boolean;
|
|
236
|
+
export declare function shouldReapSandboxLedger(ledger: Readonly<Pick<SandboxLedger, "runtimeLease">> | Readonly<Pick<LegacySandboxLedger, "dispatchAttemptId" | "fencingToken" | "runnerInstanceId" | "expiresAt">>, currentRunnerInstanceId: string, serverAttempt: SandboxAttemptSnapshot | undefined, snapshotAvailable: boolean, nowMs?: number): boolean;
|
|
237
|
+
export declare function bridgeRuntimeCacheMatches(record: Pick<ImageCacheRecord, "bridgeRuntimeDigest"> | null | undefined, expectedDigest: string, imageLabels: readonly (Readonly<Record<string, string>> | null | undefined)[]): boolean;
|
|
191
238
|
export declare function prepareOverlayBuildRoot(overlayRoot: string): Promise<void>;
|
|
192
239
|
export declare function extractOciLayoutArchive(archivePath: string, destination: string, signal?: AbortSignal): Promise<void>;
|
|
193
240
|
export declare function ociLayoutContextRef(layoutPath: string): string;
|
|
@@ -200,6 +247,20 @@ export declare function readOciLayoutImageDigest(layoutRoot: string): Promise<st
|
|
|
200
247
|
export declare function removeExtractedOciLayout(layoutRoot: string): Promise<void>;
|
|
201
248
|
export declare function ociLayoutScanTarget(layoutPath: string): string;
|
|
202
249
|
export declare function agentOverlayDockerignore(): string;
|
|
250
|
+
export interface SandboxImageCacheKeyInput {
|
|
251
|
+
readonly contextDigest: string;
|
|
252
|
+
readonly contractDigest: string;
|
|
253
|
+
readonly platform: string;
|
|
254
|
+
readonly architecture: string;
|
|
255
|
+
readonly bridgeVersion: string;
|
|
256
|
+
readonly bridgeRuntimeDigest: string;
|
|
257
|
+
readonly toolingImage: string;
|
|
258
|
+
readonly codexVersion: string;
|
|
259
|
+
readonly policy: string;
|
|
260
|
+
readonly policyConfigurationDigest: string;
|
|
261
|
+
}
|
|
262
|
+
export declare function sandboxImageCacheKey(input: SandboxImageCacheKeyInput): string;
|
|
263
|
+
export declare function bridgeRuntimeContentDigest(packageRoot: string): Promise<string>;
|
|
203
264
|
export declare function agentOverlayDockerfile(toolingImage: string, projectContextName: string, installMode: BridgePackageInstallMode, codexVersion: string): string;
|
|
204
265
|
export type BridgePackageInstallMode = "ci" | "install";
|
|
205
266
|
export declare function copyBridgePackageManifests(packageRoot: string, bridgeRoot: string): Promise<BridgePackageInstallMode>;
|
|
@@ -211,17 +272,19 @@ export declare function buildResourcePolicy(environment?: NodeJS.ProcessEnv): {
|
|
|
211
272
|
readonly nofile: number;
|
|
212
273
|
readonly sharedMemory: string;
|
|
213
274
|
readonly builderPidsLimit: number;
|
|
275
|
+
readonly builderMemoryBytes: number;
|
|
214
276
|
};
|
|
215
277
|
export declare function dedicatedBuildxBuilderName(runnerId: string, dockerContext: string | null | undefined): string;
|
|
216
278
|
export declare function dedicatedBuildxBuilderContainerName(builder: string): string;
|
|
217
279
|
export declare function selectImageGcCandidates(records: readonly ImageCacheRecord[], keepPerProject: number, ttlMs: number, nowMs: number): ImageCacheRecord[];
|
|
218
280
|
export declare function workerCreateArgs(dispatch: RunOnceDispatchPacket, contract: ValidatedSandboxContract, resources: ResourceNames, labels: Record<string, string>, image: string, securityOptions?: readonly string[]): string[];
|
|
281
|
+
export declare function validateSandboxMemoryReservation(dispatch: RunOnceDispatchPacket, contract: ValidatedSandboxContract): void;
|
|
219
282
|
export declare function cacheVolumeArgs(contract: ValidatedSandboxContract, resources: ResourceNames): string[];
|
|
220
283
|
export declare function proxyEnvironmentArgs(dispatch: RunOnceDispatchPacket, contract: ValidatedSandboxContract, resources: ResourceNames): string[];
|
|
221
284
|
export declare function egressProxyConfig(allowedHosts: readonly string[]): string;
|
|
222
285
|
export declare function serviceContainerArgs(service: SandboxService, image: string, resources: ResourceNames, labels: Record<string, string>, securityOptions: readonly string[], environment?: NodeJS.ProcessEnv): string[];
|
|
223
286
|
export declare function resolveSandboxSecurityOptions(executionPolicy: string, environment?: NodeJS.ProcessEnv): string[];
|
|
224
|
-
export declare function networkCreateArgs(dispatch: RunOnceDispatchPacket, environment?: NodeJS.ProcessEnv): string[];
|
|
287
|
+
export declare function networkCreateArgs(dispatch: RunOnceDispatchPacket, environment?: NodeJS.ProcessEnv, allowOpenPublicSandbox?: boolean): string[];
|
|
225
288
|
export declare function classifySandboxRuntimeFailure(value: string): {
|
|
226
289
|
readonly code: string;
|
|
227
290
|
readonly phase: string;
|