@loucompanion/forge-bridge 0.1.3-dev.b3bce6ba65a6 → 0.1.3-dev.ba293ccf876b
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 +127 -0
- package/dist/bridge/bridge.base.d.ts +8 -1
- package/dist/bridge/bridge.service.d.ts +98 -3
- package/dist/bridge/bridge.service.js +1425 -45
- package/dist/bridge/bridge.types.d.ts +205 -1
- package/dist/bridge/readiness-result-outbox.d.ts +21 -0
- package/dist/bridge/readiness-result-outbox.js +54 -0
- package/dist/bridge/readiness-result-worker.d.ts +2 -0
- package/dist/bridge/readiness-result-worker.js +100 -0
- package/dist/bridge/runner-host-capabilities.d.ts +15 -0
- package/dist/bridge/runner-host-capabilities.js +93 -0
- package/dist/cleanup/cleanup.service.d.ts +14 -2
- package/dist/cleanup/cleanup.service.js +496 -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 +47 -1
- package/dist/cli/cli.service.d.ts +45 -2
- package/dist/cli/cli.service.js +377 -27
- package/dist/cli/local-config.d.ts +5 -0
- package/dist/cli/local-config.js +45 -1
- package/dist/runtime/aspnet-runtime-prebuild.d.ts +36 -0
- package/dist/runtime/aspnet-runtime-prebuild.js +340 -0
- package/dist/runtime/attempt-node-runtime-launcher.d.ts +17 -0
- package/dist/runtime/attempt-node-runtime-launcher.js +105 -0
- package/dist/runtime/attempt-path-operation.d.ts +21 -0
- package/dist/runtime/attempt-path-operation.js +94 -0
- package/dist/runtime/attempt-private-directory.d.ts +6 -0
- package/dist/runtime/attempt-private-directory.js +54 -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 +97 -0
- package/dist/runtime/attempt-process-supervisor.js +386 -0
- package/dist/runtime/canonical-source-file.d.ts +3 -0
- package/dist/runtime/canonical-source-file.js +54 -0
- package/dist/runtime/docker-engine-probe.d.ts +83 -0
- package/dist/runtime/docker-engine-probe.js +300 -0
- package/dist/runtime/generated-output-reset.d.ts +10 -0
- package/dist/runtime/generated-output-reset.js +103 -0
- package/dist/runtime/host-diagnostics.d.ts +4 -0
- package/dist/runtime/host-diagnostics.js +95 -0
- package/dist/runtime/host-listener-inspector.d.ts +46 -0
- package/dist/runtime/host-listener-inspector.js +349 -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 +56 -0
- package/dist/runtime/host-runtime-contract.js +709 -0
- package/dist/runtime/host-runtime-lease.d.ts +201 -0
- package/dist/runtime/host-runtime-lease.js +2314 -0
- package/dist/runtime/host-runtime-promotion.d.ts +32 -0
- package/dist/runtime/host-runtime-promotion.js +206 -0
- package/dist/runtime/memory-capacity.d.ts +68 -0
- package/dist/runtime/memory-capacity.js +121 -0
- package/dist/runtime/node-host-runtime-adapter.d.ts +54 -0
- package/dist/runtime/node-host-runtime-adapter.js +284 -0
- package/dist/runtime/pinned-directory-process.d.ts +4 -0
- package/dist/runtime/pinned-directory-process.js +20 -0
- package/dist/runtime/pinned-source-directory.d.ts +9 -0
- package/dist/runtime/pinned-source-directory.js +56 -0
- package/dist/runtime/playwright-host-runtime-adapter.d.ts +21 -0
- package/dist/runtime/playwright-host-runtime-adapter.js +268 -0
- package/dist/runtime/prepared-runtime-identity.d.ts +3 -0
- package/dist/runtime/prepared-runtime-identity.js +191 -0
- package/dist/runtime/prepared-runtime-readiness.d.ts +22 -0
- package/dist/runtime/prepared-runtime-readiness.js +191 -0
- package/dist/runtime/runtime-isolation-lease.d.ts +67 -0
- package/dist/runtime/runtime-isolation-lease.js +158 -0
- package/dist/runtime/workspace-resource-estimator.d.ts +17 -0
- package/dist/runtime/workspace-resource-estimator.js +174 -0
- package/dist/sandbox/command-runner.d.ts +4 -0
- package/dist/sandbox/command-runner.js +47 -0
- package/dist/sandbox/contract.d.ts +5 -0
- package/dist/sandbox/contract.js +276 -0
- package/dist/sandbox/event-budget.d.ts +11 -0
- package/dist/sandbox/event-budget.js +27 -0
- package/dist/sandbox/image-policy.d.ts +35 -0
- package/dist/sandbox/image-policy.js +247 -0
- package/dist/sandbox/index.d.ts +5 -0
- package/dist/sandbox/index.js +5 -0
- package/dist/sandbox/lease-watchdog.d.ts +18 -0
- package/dist/sandbox/lease-watchdog.js +67 -0
- package/dist/sandbox/preflight.d.ts +84 -0
- package/dist/sandbox/preflight.js +521 -0
- package/dist/sandbox/process.d.ts +20 -0
- package/dist/sandbox/process.js +209 -0
- package/dist/sandbox/provider-auth/codex.d.ts +26 -0
- package/dist/sandbox/provider-auth/codex.js +212 -0
- package/dist/sandbox/repository-lock.d.ts +5 -0
- package/dist/sandbox/repository-lock.js +121 -0
- package/dist/sandbox/runtime.d.ts +297 -0
- package/dist/sandbox/runtime.js +2338 -0
- package/dist/sandbox/sandbox.types.d.ts +93 -0
- package/dist/sandbox/sandbox.types.js +1 -0
- package/dist/sandbox/smoke.d.ts +76 -0
- package/dist/sandbox/smoke.js +380 -0
- package/dist/sandbox/worker-supervisor.d.ts +13 -0
- package/dist/sandbox/worker-supervisor.js +36 -0
- package/dist/sandbox/worker.d.ts +1 -0
- package/dist/sandbox/worker.js +225 -0
- package/dist/sandbox/workspace.service.d.ts +13 -0
- package/dist/sandbox/workspace.service.js +72 -0
- package/dist/session/managed-attempt-tools.d.ts +21 -0
- package/dist/session/managed-attempt-tools.js +912 -0
- package/dist/session/managed-build-coordinator.d.ts +5 -0
- package/dist/session/managed-build-coordinator.js +105 -0
- package/dist/session/managed-build-receipt.d.ts +21 -0
- package/dist/session/managed-build-receipt.js +335 -0
- package/dist/session/phase-completion.artifacts.d.ts +17 -0
- package/dist/session/phase-completion.artifacts.js +256 -26
- package/dist/session/phase-completion.d.ts +12 -2
- package/dist/session/phase-completion.helpers.d.ts +5 -0
- package/dist/session/phase-completion.helpers.js +51 -10
- package/dist/session/phase-completion.js +14 -3
- package/dist/session/phase-completion.prompts.d.ts +3 -3
- package/dist/session/phase-completion.prompts.js +24 -8
- package/dist/session/phase-completion.runtime.d.ts +13 -1
- package/dist/session/phase-completion.runtime.js +189 -8
- package/dist/session/phase-completion.schemas.js +117 -4
- package/dist/session/phase-completion.validation.d.ts +4 -1
- package/dist/session/phase-completion.validation.js +153 -22
- package/dist/session/pre-publication-validation.d.ts +47 -0
- package/dist/session/pre-publication-validation.js +249 -0
- package/dist/session/provider-cli/ci-repair-readiness.d.ts +16 -0
- package/dist/session/provider-cli/ci-repair-readiness.js +110 -0
- package/dist/session/provider-cli/provider-cli.artifacts.d.ts +3 -2
- package/dist/session/provider-cli/provider-cli.artifacts.js +65 -7
- package/dist/session/provider-cli/provider-cli.base.d.ts +1 -0
- package/dist/session/provider-cli/provider-cli.deterministic.d.ts +2 -0
- package/dist/session/provider-cli/provider-cli.deterministic.js +68 -9
- package/dist/session/provider-cli/provider-cli.process.d.ts +26 -0
- package/dist/session/provider-cli/provider-cli.process.js +474 -23
- package/dist/session/provider-cli/provider-cli.prompts.d.ts +14 -2
- package/dist/session/provider-cli/provider-cli.prompts.js +147 -25
- package/dist/session/provider-cli/provider-cli.qa-sidecars.js +1 -0
- package/dist/session/provider-cli/provider-cli.repair-epoch.d.ts +6 -0
- package/dist/session/provider-cli/provider-cli.repair-epoch.js +11 -0
- package/dist/session/provider-cli/provider-cli.runtime.d.ts +1 -1
- package/dist/session/provider-cli/provider-cli.runtime.js +6 -3
- package/dist/session/provider-cli/provider-cli.service.d.ts +25 -2
- package/dist/session/provider-cli/provider-cli.service.js +636 -84
- 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 +91 -16
- package/dist/session/provider-cli/provider-usage.d.ts +7 -0
- package/dist/session/provider-cli/provider-usage.js +28 -5
- package/dist/session/session-redaction.d.ts +3 -0
- package/dist/session/session-redaction.js +38 -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 +531 -42
- package/dist/session/session.types.d.ts +115 -1
- package/dist/session/session.types.js +194 -3
- package/dist/shared/format/format-bytes.d.ts +1 -0
- package/dist/shared/format/format-bytes.js +9 -0
- package/dist/shared/git/git.js +2 -1
- package/dist/shared/path/path.d.ts +1 -0
- package/dist/shared/path/path.js +21 -1
- package/dist/shared/process/dotnet-toolchain.d.ts +14 -0
- package/dist/shared/process/dotnet-toolchain.js +179 -0
- 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 +59 -0
- package/dist/shared/process/host-process-supervisor.js +330 -0
- package/dist/shared/process/process.d.ts +2 -0
- package/dist/shared/process/process.js +11 -6
- package/dist/shared/provider-capabilities.d.ts +1 -0
- package/dist/shared/provider-capabilities.js +3 -0
- package/dist/shared/redaction/redaction.js +12 -2
- 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 +28 -1
- package/dist/worktree/dependency-warmer.js +308 -9
- package/dist/worktree/index.d.ts +2 -1
- 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 +14 -2
- package/dist/worktree/worktree.service.js +296 -47
- package/dist/worktree/worktree.types.d.ts +5 -1
- package/package.json +8 -4
- package/runtime/windows-job-supervisor.ps1 +444 -0
- package/runtime/windows-listener-owner.ps1 +33 -0
|
@@ -1,11 +1,18 @@
|
|
|
1
|
-
import { execFile, spawn } from "node:child_process";
|
|
1
|
+
import { execFile, execFileSync, spawn } from "node:child_process";
|
|
2
|
+
import fs from "node:fs";
|
|
2
3
|
import os from "node:os";
|
|
3
4
|
import path from "node:path";
|
|
4
5
|
import readline from "node:readline";
|
|
5
6
|
import { promisify } from "node:util";
|
|
6
7
|
import { resolveCursorAgentDirectLaunch } from "../../shared/cursor-agent/cursor-agent.launch.js";
|
|
8
|
+
import { persistHostProcessSupervisorMetadata, resolveHostProcessSupervisedLaunch, terminateHostProcessTree, } from "../../shared/process/host-process-supervisor.js";
|
|
7
9
|
import { buildWindowsLaunchCommand } from "../../shared/process/windows-launch.js";
|
|
8
10
|
const execFileAsync = promisify(execFile);
|
|
11
|
+
// Provider processes can emit many gigabytes over a long-running session. The
|
|
12
|
+
// line handlers stream that output to Forge as it arrives; the completed result
|
|
13
|
+
// only needs a bounded diagnostic tail for failure classification.
|
|
14
|
+
export const PROVIDER_OUTPUT_CAPTURE_LIMIT_CHARS = 128 * 1024;
|
|
15
|
+
const PROVIDER_TERMINAL_EXIT_GRACE_MS = 15_000;
|
|
9
16
|
const allowedProviderParentEnvNames = [
|
|
10
17
|
"PATH",
|
|
11
18
|
"HOME",
|
|
@@ -56,8 +63,37 @@ export function buildProviderChildEnvironment(requestEnv, options = {}) {
|
|
|
56
63
|
if (platform === "win32") {
|
|
57
64
|
normalizeWindowsDotNetEnvironment(env, parentEnv, options.homeDir ?? os.homedir());
|
|
58
65
|
}
|
|
66
|
+
normalizeProviderBuildEnvironment(env);
|
|
59
67
|
return env;
|
|
60
68
|
}
|
|
69
|
+
function normalizeProviderBuildEnvironment(env) {
|
|
70
|
+
// Provider sessions are long lived and commonly run many dotnet builds. Persistent
|
|
71
|
+
// MSBuild and Roslyn compiler servers otherwise survive individual commands and can
|
|
72
|
+
// retain more memory than the active Forge lane. Keep those caches process-scoped by
|
|
73
|
+
// default on every runner OS; an explicitly supplied request value still wins.
|
|
74
|
+
setCanonicalProviderBuildEnvironmentValue(env, "DOTNET_CLI_USE_MSBUILD_SERVER", "0");
|
|
75
|
+
setCanonicalProviderBuildEnvironmentValue(env, "MSBUILDDISABLENODEREUSE", "1");
|
|
76
|
+
setCanonicalProviderBuildEnvironmentValue(env, "UseSharedCompilation", "false");
|
|
77
|
+
}
|
|
78
|
+
function setCanonicalProviderBuildEnvironmentValue(env, name, value) {
|
|
79
|
+
// The dotnet CLI uses case-sensitive environment lookup on POSIX, while MSBuild
|
|
80
|
+
// property names are case-insensitive on every OS. Collapse request aliases to
|
|
81
|
+
// one canonical key so the explicit value wins without producing ambiguity.
|
|
82
|
+
const exact = env[name];
|
|
83
|
+
const alias = Object.entries(env).find(([key, candidate]) => key !== name
|
|
84
|
+
&& key.toLowerCase() === name.toLowerCase()
|
|
85
|
+
&& typeof candidate === "string"
|
|
86
|
+
&& candidate.trim().length > 0)?.[1];
|
|
87
|
+
const resolved = typeof exact === "string" && exact.trim().length > 0
|
|
88
|
+
? exact
|
|
89
|
+
: alias ?? value;
|
|
90
|
+
for (const key of Object.keys(env)) {
|
|
91
|
+
if (key !== name && key.toLowerCase() === name.toLowerCase()) {
|
|
92
|
+
delete env[key];
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
env[name] = resolved;
|
|
96
|
+
}
|
|
61
97
|
function isAllowedProviderParentEnv(key, platform = process.platform) {
|
|
62
98
|
return isAllowedProviderParentEnvName(key, allowedProviderParentEnvNames)
|
|
63
99
|
|| key.toUpperCase().startsWith("LC_")
|
|
@@ -136,26 +172,53 @@ function setEnvironmentValueIfMissing(env, name, value) {
|
|
|
136
172
|
env[name] = value;
|
|
137
173
|
}
|
|
138
174
|
export class StreamingProviderProcessRunner {
|
|
175
|
+
terminalExitGraceMs;
|
|
176
|
+
constructor(terminalExitGraceMs = PROVIDER_TERMINAL_EXIT_GRACE_MS) {
|
|
177
|
+
this.terminalExitGraceMs = terminalExitGraceMs;
|
|
178
|
+
}
|
|
139
179
|
async run(request, handlers = {}, signal) {
|
|
140
|
-
const
|
|
180
|
+
const providerLaunch = await resolveProviderProcessLaunch(request.command, request.args);
|
|
181
|
+
const supervisedLaunch = resolveHostProcessSupervisedLaunch(request, providerLaunch.command, providerLaunch.args);
|
|
182
|
+
// An unsupervised Unix provider still gets a dedicated process group so a
|
|
183
|
+
// cancellation can stop descendants instead of only the CLI root.
|
|
184
|
+
const launch = supervisedLaunch ?? { ...providerLaunch, detached: process.platform !== "win32" };
|
|
141
185
|
return await new Promise((resolve, reject) => {
|
|
186
|
+
const rootCreatedAt = new Date().toISOString();
|
|
142
187
|
const child = spawn(launch.command, launch.args, {
|
|
143
188
|
cwd: request.cwd,
|
|
144
189
|
env: buildProviderChildEnvironment(request.env),
|
|
145
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
146
|
-
windowsHide: true
|
|
190
|
+
stdio: [request.stdin === undefined ? "ignore" : "pipe", "pipe", "pipe"],
|
|
191
|
+
windowsHide: true,
|
|
192
|
+
detached: launch.detached,
|
|
147
193
|
});
|
|
194
|
+
const memoryObserver = supervisedLaunch
|
|
195
|
+
? new HostProcessTreeMemoryObserver(supervisedLaunch, child.pid ?? 0)
|
|
196
|
+
: null;
|
|
197
|
+
let termination = null;
|
|
198
|
+
const terminate = () => {
|
|
199
|
+
termination ??= terminateHostProcessTree(child, supervisedLaunch);
|
|
200
|
+
return termination;
|
|
201
|
+
};
|
|
148
202
|
const childStdout = child.stdout;
|
|
149
203
|
const childStderr = child.stderr;
|
|
150
204
|
if (!childStdout || !childStderr) {
|
|
151
|
-
|
|
152
|
-
reject(new
|
|
205
|
+
const pipeError = new Error("Provider process stdout/stderr streams were not piped.");
|
|
206
|
+
void terminate().then(() => reject(pipeError), terminationError => reject(new AggregateError([pipeError, terminationError], "Provider launch failed and its process tree could not be proven stopped.")));
|
|
153
207
|
return;
|
|
154
208
|
}
|
|
155
|
-
|
|
156
|
-
|
|
209
|
+
const stdout = new BoundedOutputTail(PROVIDER_OUTPUT_CAPTURE_LIMIT_CHARS);
|
|
210
|
+
const stderr = new BoundedOutputTail(PROVIDER_OUTPUT_CAPTURE_LIMIT_CHARS);
|
|
157
211
|
let settled = false;
|
|
212
|
+
let closed = false;
|
|
213
|
+
let cancellationRequested = false;
|
|
214
|
+
let terminalTerminationStarted = false;
|
|
215
|
+
let terminalExitTimer = null;
|
|
216
|
+
let readiness = null;
|
|
158
217
|
const cleanup = () => {
|
|
218
|
+
if (terminalExitTimer) {
|
|
219
|
+
clearTimeout(terminalExitTimer);
|
|
220
|
+
terminalExitTimer = null;
|
|
221
|
+
}
|
|
159
222
|
signal?.removeEventListener("abort", abort);
|
|
160
223
|
};
|
|
161
224
|
const fail = (error) => {
|
|
@@ -164,15 +227,16 @@ export class StreamingProviderProcessRunner {
|
|
|
164
227
|
}
|
|
165
228
|
settled = true;
|
|
166
229
|
cleanup();
|
|
167
|
-
|
|
230
|
+
// Do not release the caller's reservation/worktree/port ownership until
|
|
231
|
+
// descendant termination has completed (or failed with explicit proof).
|
|
232
|
+
void terminate().then(() => reject(error), terminationError => reject(new AggregateError([error, terminationError], "Provider process failed and its process tree could not be proven stopped.")));
|
|
168
233
|
};
|
|
169
234
|
const abort = () => {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
}
|
|
235
|
+
cancellationRequested = true;
|
|
236
|
+
// Cancellation is not a launch failure when the supervised tree can be
|
|
237
|
+
// proven stopped. Let the close handler settle the command after exact
|
|
238
|
+
// termination; only a failed termination proof rejects the run.
|
|
239
|
+
void terminate().catch(fail);
|
|
176
240
|
};
|
|
177
241
|
if (signal?.aborted) {
|
|
178
242
|
abort();
|
|
@@ -181,18 +245,79 @@ export class StreamingProviderProcessRunner {
|
|
|
181
245
|
signal?.addEventListener("abort", abort, { once: true });
|
|
182
246
|
}
|
|
183
247
|
child.on("error", fail);
|
|
248
|
+
child.once("spawn", () => {
|
|
249
|
+
readiness = (async () => {
|
|
250
|
+
const providerReady = supervisedLaunch?.strategy === "windows_job_object"
|
|
251
|
+
? await waitForWindowsProviderReady(supervisedLaunch, signal, () => closed)
|
|
252
|
+
: undefined;
|
|
253
|
+
if (supervisedLaunch) {
|
|
254
|
+
persistHostProcessSupervisorMetadata(supervisedLaunch, request, child.pid ?? 0, rootCreatedAt, providerReady);
|
|
255
|
+
}
|
|
256
|
+
await handlers.onStarted?.();
|
|
257
|
+
if (supervisedLaunch?.strategy === "windows_job_object") {
|
|
258
|
+
grantWindowsProviderStart(supervisedLaunch);
|
|
259
|
+
}
|
|
260
|
+
})();
|
|
261
|
+
void readiness.catch(error => {
|
|
262
|
+
if (!closed && !signal?.aborted)
|
|
263
|
+
fail(error);
|
|
264
|
+
});
|
|
265
|
+
});
|
|
266
|
+
const writeProviderInput = () => {
|
|
267
|
+
if (request.stdin === undefined)
|
|
268
|
+
return;
|
|
269
|
+
if (!child.stdin) {
|
|
270
|
+
void terminate();
|
|
271
|
+
fail(new Error("Provider process stdin stream was not piped."));
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
child.stdin.on("error", (error) => {
|
|
275
|
+
void terminate();
|
|
276
|
+
fail(error);
|
|
277
|
+
});
|
|
278
|
+
child.stdin.end(request.stdin, "utf8");
|
|
279
|
+
};
|
|
280
|
+
if (request.stdin !== undefined) {
|
|
281
|
+
if (supervisedLaunch?.strategy === "windows_job_object") {
|
|
282
|
+
// The outer supervisor must receive stdin before it can launch the
|
|
283
|
+
// inner provider. Its start-grant file prevents prompt delivery.
|
|
284
|
+
writeProviderInput();
|
|
285
|
+
}
|
|
286
|
+
else {
|
|
287
|
+
child.once("spawn", () => {
|
|
288
|
+
void readiness?.then(writeProviderInput).catch(fail);
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
}
|
|
184
292
|
const readers = [
|
|
185
293
|
readProcessLines(childStdout, (line) => {
|
|
186
|
-
|
|
187
|
-
|
|
294
|
+
if (request.captureOutput !== false)
|
|
295
|
+
stdout.appendLine(line);
|
|
296
|
+
const handled = handlers.onStdoutLine?.(line);
|
|
297
|
+
if (!terminalExitTimer && isProviderTerminalSuccess(line)) {
|
|
298
|
+
terminalExitTimer = setTimeout(() => {
|
|
299
|
+
if (closed || settled || cancellationRequested)
|
|
300
|
+
return;
|
|
301
|
+
terminalTerminationStarted = true;
|
|
302
|
+
void terminate().catch(fail);
|
|
303
|
+
}, this.terminalExitGraceMs);
|
|
304
|
+
terminalExitTimer.unref?.();
|
|
305
|
+
}
|
|
306
|
+
return handled;
|
|
188
307
|
}),
|
|
189
308
|
readProcessLines(childStderr, (line) => {
|
|
190
|
-
|
|
309
|
+
if (request.captureOutput !== false)
|
|
310
|
+
stderr.appendLine(line);
|
|
191
311
|
return handlers.onStderrLine?.(line);
|
|
192
312
|
})
|
|
193
313
|
];
|
|
314
|
+
for (const reader of readers) {
|
|
315
|
+
void reader.catch(fail);
|
|
316
|
+
}
|
|
194
317
|
child.on("close", (code) => {
|
|
195
|
-
|
|
318
|
+
closed = true;
|
|
319
|
+
Promise.allSettled(readers).then(async (readerResults) => {
|
|
320
|
+
await readiness?.catch(() => undefined);
|
|
196
321
|
const rejected = readerResults.find((result) => result.status === "rejected");
|
|
197
322
|
if (rejected?.status === "rejected") {
|
|
198
323
|
fail(rejected.reason);
|
|
@@ -201,18 +326,204 @@ export class StreamingProviderProcessRunner {
|
|
|
201
326
|
if (settled) {
|
|
202
327
|
return;
|
|
203
328
|
}
|
|
329
|
+
try {
|
|
330
|
+
memoryObserver?.sample();
|
|
331
|
+
if (supervisedLaunch?.strategy === "unix_process_group" || !supervisedLaunch) {
|
|
332
|
+
await terminate();
|
|
333
|
+
}
|
|
334
|
+
else if (termination) {
|
|
335
|
+
await termination;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
catch (error) {
|
|
339
|
+
fail(error);
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
204
342
|
settled = true;
|
|
205
343
|
cleanup();
|
|
344
|
+
const memory = memoryObserver?.complete();
|
|
206
345
|
resolve({
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
346
|
+
// A structured terminal-success event is the provider protocol's
|
|
347
|
+
// authoritative completion signal. If the CLI stays resident after
|
|
348
|
+
// that event, terminate the supervised tree after a short grace
|
|
349
|
+
// period and preserve the successful handoff so the existing
|
|
350
|
+
// artifact, commit, and publication gates can run.
|
|
351
|
+
exitCode: terminalTerminationStarted && !cancellationRequested ? 0 : code ?? 1,
|
|
352
|
+
stdout: stdout.toString(),
|
|
353
|
+
stderr: stderr.toString(),
|
|
354
|
+
...(memory ?? {}),
|
|
210
355
|
});
|
|
211
356
|
}).catch(fail);
|
|
212
357
|
});
|
|
213
358
|
});
|
|
214
359
|
}
|
|
215
360
|
}
|
|
361
|
+
function isProviderTerminalSuccess(line) {
|
|
362
|
+
const trimmed = line.trim();
|
|
363
|
+
if (!trimmed.startsWith("{"))
|
|
364
|
+
return false;
|
|
365
|
+
try {
|
|
366
|
+
const event = JSON.parse(trimmed);
|
|
367
|
+
return event.type === "turn.completed"
|
|
368
|
+
|| (event.type === "result" && event.subtype === "success" && event.is_error !== true);
|
|
369
|
+
}
|
|
370
|
+
catch {
|
|
371
|
+
return false;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
class HostProcessTreeMemoryObserver {
|
|
375
|
+
launch;
|
|
376
|
+
processGroupId;
|
|
377
|
+
peakMemoryBytes = 0;
|
|
378
|
+
sampleCount = 0;
|
|
379
|
+
observedAt = null;
|
|
380
|
+
timer;
|
|
381
|
+
constructor(launch, processGroupId) {
|
|
382
|
+
this.launch = launch;
|
|
383
|
+
this.processGroupId = processGroupId;
|
|
384
|
+
if (launch.strategy === "unix_process_group" && processGroupId > 0) {
|
|
385
|
+
this.sample();
|
|
386
|
+
this.timer = setInterval(() => this.sample(), 1_000);
|
|
387
|
+
this.timer.unref?.();
|
|
388
|
+
}
|
|
389
|
+
else {
|
|
390
|
+
this.timer = null;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
sample() {
|
|
394
|
+
if (this.launch.strategy !== "unix_process_group" || this.processGroupId <= 0)
|
|
395
|
+
return;
|
|
396
|
+
const bytes = processGroupResidentMemoryBytes(this.processGroupId);
|
|
397
|
+
if (bytes === null)
|
|
398
|
+
return;
|
|
399
|
+
this.sampleCount += 1;
|
|
400
|
+
this.peakMemoryBytes = Math.max(this.peakMemoryBytes, bytes);
|
|
401
|
+
this.observedAt = new Date().toISOString();
|
|
402
|
+
}
|
|
403
|
+
complete() {
|
|
404
|
+
if (this.timer)
|
|
405
|
+
clearInterval(this.timer);
|
|
406
|
+
if (this.launch.strategy === "windows_job_object") {
|
|
407
|
+
return readWindowsJobMemoryTelemetry(this.launch.memoryTelemetryPath);
|
|
408
|
+
}
|
|
409
|
+
if (this.peakMemoryBytes <= 0 || this.sampleCount <= 0 || !this.observedAt)
|
|
410
|
+
return undefined;
|
|
411
|
+
return {
|
|
412
|
+
peakMemoryBytes: this.peakMemoryBytes,
|
|
413
|
+
memorySampleCount: this.sampleCount,
|
|
414
|
+
memorySource: process.platform === "linux"
|
|
415
|
+
? "linux_process_group_rss"
|
|
416
|
+
: "unix_process_group_rss",
|
|
417
|
+
memoryObservedAt: this.observedAt,
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
/** Returns aggregate resident bytes for the exact supervised Unix process group. */
|
|
422
|
+
export function processGroupResidentMemoryBytes(processGroupId, platform = process.platform, procRoot = "/proc") {
|
|
423
|
+
if (!Number.isSafeInteger(processGroupId) || processGroupId <= 0)
|
|
424
|
+
return null;
|
|
425
|
+
if (platform === "linux") {
|
|
426
|
+
let totalKilobytes = 0;
|
|
427
|
+
let matched = 0;
|
|
428
|
+
try {
|
|
429
|
+
for (const entry of fs.readdirSync(procRoot, { withFileTypes: true })) {
|
|
430
|
+
if (!entry.isDirectory() || !/^\d+$/u.test(entry.name))
|
|
431
|
+
continue;
|
|
432
|
+
try {
|
|
433
|
+
const stat = fs.readFileSync(path.join(procRoot, entry.name, "stat"), "utf8");
|
|
434
|
+
const close = stat.lastIndexOf(")");
|
|
435
|
+
const fields = close >= 0 ? stat.slice(close + 2).trim().split(/\s+/u) : [];
|
|
436
|
+
if (Number.parseInt(fields[2] ?? "", 10) !== processGroupId)
|
|
437
|
+
continue;
|
|
438
|
+
const status = fs.readFileSync(path.join(procRoot, entry.name, "status"), "utf8");
|
|
439
|
+
const rss = /^VmRSS:\s+(\d+)\s+kB$/mu.exec(status);
|
|
440
|
+
if (!rss)
|
|
441
|
+
continue;
|
|
442
|
+
totalKilobytes += Number.parseInt(rss[1], 10);
|
|
443
|
+
matched += 1;
|
|
444
|
+
}
|
|
445
|
+
catch {
|
|
446
|
+
// Processes can exit between the directory, stat, and status reads.
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
return matched > 0 ? totalKilobytes * 1024 : null;
|
|
450
|
+
}
|
|
451
|
+
catch {
|
|
452
|
+
return null;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
if (platform !== "win32") {
|
|
456
|
+
try {
|
|
457
|
+
const output = execFileSync("ps", ["-axo", "pgid=,rss="], {
|
|
458
|
+
encoding: "utf8",
|
|
459
|
+
timeout: 5_000,
|
|
460
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
461
|
+
});
|
|
462
|
+
let totalKilobytes = 0;
|
|
463
|
+
let matched = 0;
|
|
464
|
+
for (const line of output.split(/\r?\n/u)) {
|
|
465
|
+
const fields = line.trim().split(/\s+/u);
|
|
466
|
+
if (Number.parseInt(fields[0] ?? "", 10) !== processGroupId)
|
|
467
|
+
continue;
|
|
468
|
+
const rss = Number.parseInt(fields[1] ?? "", 10);
|
|
469
|
+
if (!Number.isSafeInteger(rss) || rss < 0)
|
|
470
|
+
continue;
|
|
471
|
+
totalKilobytes += rss;
|
|
472
|
+
matched += 1;
|
|
473
|
+
}
|
|
474
|
+
return matched > 0 ? totalKilobytes * 1024 : null;
|
|
475
|
+
}
|
|
476
|
+
catch {
|
|
477
|
+
return null;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
return null;
|
|
481
|
+
}
|
|
482
|
+
function readWindowsJobMemoryTelemetry(target) {
|
|
483
|
+
if (!target)
|
|
484
|
+
return undefined;
|
|
485
|
+
try {
|
|
486
|
+
const value = JSON.parse(fs.readFileSync(target, "utf8"));
|
|
487
|
+
const peakMemoryBytes = value.peakMemoryBytes;
|
|
488
|
+
const sampleCount = value.sampleCount;
|
|
489
|
+
const source = value.source;
|
|
490
|
+
const observedAt = value.observedAt;
|
|
491
|
+
if (!Number.isSafeInteger(peakMemoryBytes) || peakMemoryBytes <= 0
|
|
492
|
+
|| !Number.isSafeInteger(sampleCount) || sampleCount <= 0
|
|
493
|
+
|| typeof source !== "string" || source.length === 0
|
|
494
|
+
|| typeof observedAt !== "string" || !Number.isFinite(Date.parse(observedAt))) {
|
|
495
|
+
return undefined;
|
|
496
|
+
}
|
|
497
|
+
return {
|
|
498
|
+
peakMemoryBytes: peakMemoryBytes,
|
|
499
|
+
memorySampleCount: sampleCount,
|
|
500
|
+
memorySource: source,
|
|
501
|
+
memoryObservedAt: observedAt,
|
|
502
|
+
};
|
|
503
|
+
}
|
|
504
|
+
catch {
|
|
505
|
+
return undefined;
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
class BoundedOutputTail {
|
|
509
|
+
maxChars;
|
|
510
|
+
value = "";
|
|
511
|
+
constructor(maxChars) {
|
|
512
|
+
this.maxChars = maxChars;
|
|
513
|
+
}
|
|
514
|
+
appendLine(line) {
|
|
515
|
+
const chunk = `${line}\n`;
|
|
516
|
+
if (chunk.length >= this.maxChars) {
|
|
517
|
+
this.value = chunk.slice(-this.maxChars);
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
520
|
+
const retainedPrefixChars = this.maxChars - chunk.length;
|
|
521
|
+
this.value = `${this.value.slice(-retainedPrefixChars)}${chunk}`;
|
|
522
|
+
}
|
|
523
|
+
toString() {
|
|
524
|
+
return this.value;
|
|
525
|
+
}
|
|
526
|
+
}
|
|
216
527
|
async function resolveProviderProcessLaunch(command, args) {
|
|
217
528
|
if (process.platform !== "win32") {
|
|
218
529
|
return { command, args };
|
|
@@ -222,12 +533,115 @@ async function resolveProviderProcessLaunch(command, args) {
|
|
|
222
533
|
return cursorDirect;
|
|
223
534
|
}
|
|
224
535
|
const resolved = await resolveWindowsCommand(command);
|
|
225
|
-
|
|
536
|
+
if (!resolved) {
|
|
537
|
+
return { command, args };
|
|
538
|
+
}
|
|
539
|
+
return resolveCodexNpmDirectLaunch(resolved, args)
|
|
540
|
+
?? resolvePackageManagerDirectLaunch(resolved, args)
|
|
541
|
+
?? buildWindowsLaunchCommand(resolved, args);
|
|
542
|
+
}
|
|
543
|
+
function grantWindowsProviderStart(launch) {
|
|
544
|
+
if (!launch.startGrantPath) {
|
|
545
|
+
throw new Error("host_process_supervisor_invalid: Windows provider start-grant path was not assigned.");
|
|
546
|
+
}
|
|
547
|
+
fs.writeFileSync(launch.startGrantPath, "granted\n", {
|
|
548
|
+
encoding: "utf8",
|
|
549
|
+
flag: "wx",
|
|
550
|
+
mode: 0o600,
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
async function waitForWindowsProviderReady(launch, signal, isClosed) {
|
|
554
|
+
const readyPath = launch.readyPath;
|
|
555
|
+
if (!readyPath) {
|
|
556
|
+
throw new Error("host_process_supervisor_invalid: Windows provider-ready path was not assigned.");
|
|
557
|
+
}
|
|
558
|
+
while (true) {
|
|
559
|
+
try {
|
|
560
|
+
const parsed = JSON.parse(await fs.promises.readFile(readyPath, "utf8"));
|
|
561
|
+
if (parsed.schemaVersion !== 1
|
|
562
|
+
|| parsed.supervisorId !== launch.supervisorId
|
|
563
|
+
|| !Number.isSafeInteger(parsed.rootPid)
|
|
564
|
+
|| (parsed.rootPid ?? 0) <= 0
|
|
565
|
+
|| typeof parsed.rootIdentity !== "string"
|
|
566
|
+
|| !/^win32:\d+$/u.test(parsed.rootIdentity)
|
|
567
|
+
|| !Number.isSafeInteger(parsed.providerPid)
|
|
568
|
+
|| (parsed.providerPid ?? 0) <= 0
|
|
569
|
+
|| typeof parsed.providerCreatedAt !== "string"
|
|
570
|
+
|| Number.isNaN(Date.parse(parsed.providerCreatedAt))
|
|
571
|
+
|| (parsed.providerIdentity !== undefined
|
|
572
|
+
&& (typeof parsed.providerIdentity !== "string" || !/^win32:\d+$/u.test(parsed.providerIdentity)))
|
|
573
|
+
|| !Number.isSafeInteger(parsed.startAttempt)
|
|
574
|
+
|| (parsed.startAttempt ?? 0) < 1) {
|
|
575
|
+
throw new Error("host_process_supervisor_invalid: provider-ready receipt was invalid.");
|
|
576
|
+
}
|
|
577
|
+
return parsed;
|
|
578
|
+
}
|
|
579
|
+
catch (error) {
|
|
580
|
+
if (error.code !== "ENOENT")
|
|
581
|
+
throw error;
|
|
582
|
+
}
|
|
583
|
+
if (isClosed()) {
|
|
584
|
+
throw new Error("host_process_supervisor_start_failed: supervisor exited before the provider became ready.");
|
|
585
|
+
}
|
|
586
|
+
if (signal?.aborted) {
|
|
587
|
+
throw signal.reason instanceof Error ? signal.reason : new Error("Provider process launch was aborted.");
|
|
588
|
+
}
|
|
589
|
+
await new Promise(resolve => setTimeout(resolve, 25));
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
export function resolveCodexNpmDirectLaunch(commandPath, args) {
|
|
593
|
+
const extension = path.extname(commandPath).toLowerCase();
|
|
594
|
+
if ((extension !== ".cmd" && extension !== ".ps1")
|
|
595
|
+
|| path.basename(commandPath, extension).toLowerCase() !== "codex") {
|
|
596
|
+
return null;
|
|
597
|
+
}
|
|
598
|
+
const entryPoint = path.join(path.dirname(commandPath), "node_modules", "@openai", "codex", "bin", "codex.js");
|
|
599
|
+
return fs.existsSync(entryPoint)
|
|
600
|
+
? { command: process.execPath, args: [entryPoint, ...args] }
|
|
601
|
+
: null;
|
|
602
|
+
}
|
|
603
|
+
/**
|
|
604
|
+
* Avoids cmd.exe's nested-quote handling for package-manager shims. That
|
|
605
|
+
* quoting loses executable paths containing spaces after the command is
|
|
606
|
+
* wrapped by the Windows Job Object supervisor.
|
|
607
|
+
*/
|
|
608
|
+
export function resolvePackageManagerDirectLaunch(commandPath, args) {
|
|
609
|
+
const extension = path.extname(commandPath).toLowerCase();
|
|
610
|
+
if (extension !== ".cmd" && extension !== ".ps1")
|
|
611
|
+
return null;
|
|
612
|
+
const packageManager = path.basename(commandPath, extension).toLowerCase();
|
|
613
|
+
if (!["corepack", "npm", "npx", "pnpm", "pnpx", "yarn", "yarnpkg"].includes(packageManager))
|
|
614
|
+
return null;
|
|
615
|
+
const root = path.dirname(commandPath);
|
|
616
|
+
const candidates = [
|
|
617
|
+
path.join(root, "node_modules", "corepack", "dist", packageManager === "corepack" ? "corepack.js" : `${packageManager}.js`),
|
|
618
|
+
...(packageManager === "npm" || packageManager === "npx"
|
|
619
|
+
? [path.join(root, "node_modules", "npm", "bin", `${packageManager}-cli.js`)]
|
|
620
|
+
: []),
|
|
621
|
+
...(packageManager === "pnpm" || packageManager === "pnpx"
|
|
622
|
+
? [path.join(root, "node_modules", "pnpm", "bin", `${packageManager}.cjs`)]
|
|
623
|
+
: []),
|
|
624
|
+
...(packageManager === "yarn" || packageManager === "yarnpkg"
|
|
625
|
+
? [path.join(root, "node_modules", "yarn", "bin", "yarn.js")]
|
|
626
|
+
: []),
|
|
627
|
+
];
|
|
628
|
+
const entryPoint = candidates.find(candidate => fs.existsSync(candidate));
|
|
629
|
+
if (!entryPoint)
|
|
630
|
+
return null;
|
|
631
|
+
const adjacentNode = path.join(root, "node.exe");
|
|
632
|
+
return {
|
|
633
|
+
command: fs.existsSync(adjacentNode) ? adjacentNode : process.execPath,
|
|
634
|
+
args: [entryPoint, ...args],
|
|
635
|
+
};
|
|
226
636
|
}
|
|
227
637
|
async function resolveWindowsCommand(command) {
|
|
228
638
|
if (path.isAbsolute(command)) {
|
|
229
639
|
return command;
|
|
230
640
|
}
|
|
641
|
+
const resolvedFromPath = resolveWindowsCommandFromPath(command);
|
|
642
|
+
if (resolvedFromPath) {
|
|
643
|
+
return resolvedFromPath;
|
|
644
|
+
}
|
|
231
645
|
try {
|
|
232
646
|
const result = await execFileAsync("where.exe", [command], { timeout: 2000 });
|
|
233
647
|
return chooseWindowsCommandCandidate(result.stdout.split(/\r?\n/));
|
|
@@ -236,6 +650,43 @@ async function resolveWindowsCommand(command) {
|
|
|
236
650
|
return null;
|
|
237
651
|
}
|
|
238
652
|
}
|
|
653
|
+
/**
|
|
654
|
+
* Resolves Windows commands without spawning where.exe. Runtime launches can
|
|
655
|
+
* happen while the machine is under enough process pressure for where.exe to
|
|
656
|
+
* miss its timeout; returning the unresolved package-manager name in that case
|
|
657
|
+
* makes Node fall back to a shell shim that cannot survive Job Object wrapping.
|
|
658
|
+
*/
|
|
659
|
+
export function resolveWindowsCommandFromPath(command, pathValue = process.env.PATH ?? "", pathExtValue = process.env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD") {
|
|
660
|
+
if (!command || path.isAbsolute(command) || command.includes("/") || command.includes("\\")) {
|
|
661
|
+
return null;
|
|
662
|
+
}
|
|
663
|
+
const hasExtension = path.extname(command).length > 0;
|
|
664
|
+
const extensions = hasExtension
|
|
665
|
+
? [""]
|
|
666
|
+
: [...new Set([
|
|
667
|
+
"",
|
|
668
|
+
".exe",
|
|
669
|
+
".ps1",
|
|
670
|
+
".cmd",
|
|
671
|
+
".bat",
|
|
672
|
+
...pathExtValue.split(";").map(value => value.trim().toLowerCase()).filter(Boolean),
|
|
673
|
+
])];
|
|
674
|
+
for (const rawDirectory of pathValue.split(path.delimiter)) {
|
|
675
|
+
const directory = rawDirectory.trim().replace(/^"|"$/gu, "");
|
|
676
|
+
if (!directory)
|
|
677
|
+
continue;
|
|
678
|
+
const candidates = [];
|
|
679
|
+
for (const extension of extensions) {
|
|
680
|
+
const candidate = path.join(directory, `${command}${extension}`);
|
|
681
|
+
if (fs.existsSync(candidate))
|
|
682
|
+
candidates.push(candidate);
|
|
683
|
+
}
|
|
684
|
+
const resolved = chooseWindowsCommandCandidate(candidates);
|
|
685
|
+
if (resolved)
|
|
686
|
+
return resolved;
|
|
687
|
+
}
|
|
688
|
+
return null;
|
|
689
|
+
}
|
|
239
690
|
export function chooseWindowsCommandCandidate(candidates) {
|
|
240
691
|
const normalized = candidates
|
|
241
692
|
.map((candidate) => candidate.trim())
|
|
@@ -2,7 +2,13 @@ import { completionPhaseFromDispatch, type CompletionToolRuntime } from "../phas
|
|
|
2
2
|
import type { RunOnceDispatchPacket } from "../session.types.js";
|
|
3
3
|
import type { ProviderCliCommand } from "./provider-cli.process.js";
|
|
4
4
|
export declare function buildDraftSpec(dispatch: RunOnceDispatchPacket): string;
|
|
5
|
-
export
|
|
5
|
+
export interface DraftAttachmentPromptReference {
|
|
6
|
+
readonly index: number;
|
|
7
|
+
readonly path: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function buildDraftPrompt(dispatch: RunOnceDispatchPacket, options?: {
|
|
10
|
+
readonly attachmentReferences?: readonly DraftAttachmentPromptReference[];
|
|
11
|
+
}): string;
|
|
6
12
|
export declare function durableDraftInput(dispatch: RunOnceDispatchPacket): RunOnceDispatchPacket["draft"];
|
|
7
13
|
export declare function isDecomposeDraftKind(kind: string | null | undefined): boolean;
|
|
8
14
|
export declare function isDecomposeDraftDispatch(dispatch: RunOnceDispatchPacket): boolean;
|
|
@@ -11,11 +17,15 @@ export declare function formatProviderCliCommandForCheckpoint(command: ProviderC
|
|
|
11
17
|
export declare function singleLine(value: string): string;
|
|
12
18
|
export declare function buildProviderCliCommand(dispatch: RunOnceDispatchPacket, run?: {
|
|
13
19
|
readonly prompt?: string;
|
|
20
|
+
readonly promptFromStdin?: boolean;
|
|
14
21
|
readonly worktreePath?: string;
|
|
15
22
|
readonly completionTools?: CompletionToolRuntime;
|
|
16
23
|
readonly skipGitRepoCheck?: boolean;
|
|
24
|
+
readonly imagePaths?: readonly string[];
|
|
25
|
+
readonly runtimeEnvironment?: Readonly<Record<string, string>>;
|
|
17
26
|
}): ProviderCliCommand;
|
|
18
|
-
export declare function
|
|
27
|
+
export declare function buildProviderCliPrompt(dispatch: RunOnceDispatchPacket, prompt: string, runtimeEnvironment?: Readonly<Record<string, string>>): string;
|
|
28
|
+
export declare function codexSandboxModeForPlatform(platform?: NodeJS.Platform, executionMode?: string): "workspace-write" | "danger-full-access";
|
|
19
29
|
export declare function buildArchitectPrompt(dispatch: RunOnceDispatchPacket): string;
|
|
20
30
|
export declare function architectDependencyInstruction(dispatch: RunOnceDispatchPacket): string;
|
|
21
31
|
export declare function designerRefInstruction(dispatch: RunOnceDispatchPacket): string;
|
|
@@ -31,5 +41,7 @@ export declare function qaBrowserInstruction(dispatch: RunOnceDispatchPacket): s
|
|
|
31
41
|
export declare function storyQaInstruction(dispatch: RunOnceDispatchPacket): string;
|
|
32
42
|
export declare function buildQaPrompt(dispatch: RunOnceDispatchPacket, laneSpec: string): string;
|
|
33
43
|
export declare function buildConflictResolvePrompt(dispatch: RunOnceDispatchPacket, branchName: string): string;
|
|
44
|
+
export declare function buildPullRequestCheckRepairPrompt(dispatch: RunOnceDispatchPacket, branchName: string): string;
|
|
34
45
|
export declare function buildPullRequestCommentsPrompt(dispatch: RunOnceDispatchPacket, branchName: string): string;
|
|
46
|
+
export declare function isPullRequestCheckRepairDispatch(dispatch: RunOnceDispatchPacket): boolean;
|
|
35
47
|
export declare function isPullRequestCommentsDispatch(dispatch: RunOnceDispatchPacket): boolean;
|