@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/cli/cli.help.js
CHANGED
|
@@ -16,10 +16,11 @@ export function helpText() {
|
|
|
16
16
|
" connect * Start the runner bridge and wait for Forge dispatches",
|
|
17
17
|
" pair * Pair this machine with Forge and save runner credentials",
|
|
18
18
|
" status * Show config, runner identity, repos, provider CLIs, and updates",
|
|
19
|
+
" server * Show or change the saved Forge server URL",
|
|
19
20
|
" add-repo * Map a Forge repo label/name to a local checkout path",
|
|
20
21
|
" remove-repo * Remove a saved repo mapping",
|
|
21
22
|
" cleanup * Prune managed bridge worktrees",
|
|
22
|
-
" sandbox * Initialize, diagnose, or reap Docker sandboxes",
|
|
23
|
+
" sandbox * Initialize, diagnose, smoke-test, or reap Docker sandboxes",
|
|
23
24
|
" version * Print the installed bridge package version",
|
|
24
25
|
" help * Display help for command",
|
|
25
26
|
" run-once * Internal: run one dispatch packet from JSON",
|
|
@@ -30,6 +31,7 @@ export function helpText() {
|
|
|
30
31
|
" forge-bridge pair 1234-5678 --server https://srv1493013.tail66073d.ts.net:8443 --repo-root \"%USERPROFILE%\\ForgeRepos\"",
|
|
31
32
|
" forge-bridge connect",
|
|
32
33
|
" forge-bridge status --check-updates",
|
|
34
|
+
" forge-bridge server set http://localhost:5208",
|
|
33
35
|
" forge-bridge add-repo Forge D:\\Programming\\repos\\Forge",
|
|
34
36
|
" forge-bridge cleanup --stale",
|
|
35
37
|
"",
|
|
@@ -100,6 +102,23 @@ export function commandHelpText(command) {
|
|
|
100
102
|
" forge-bridge status --check-updates",
|
|
101
103
|
"",
|
|
102
104
|
].join("\n");
|
|
105
|
+
case "server":
|
|
106
|
+
return [
|
|
107
|
+
"Forge Bridge — server",
|
|
108
|
+
"Show or change the saved Forge server URL.",
|
|
109
|
+
"",
|
|
110
|
+
"Usage:",
|
|
111
|
+
" forge-bridge server show",
|
|
112
|
+
" forge-bridge server set <url>",
|
|
113
|
+
"",
|
|
114
|
+
"The saved runner credentials are retained. Pair again when switching to a different Forge deployment.",
|
|
115
|
+
"FORGE_URL overrides the saved server when that environment variable is set.",
|
|
116
|
+
"",
|
|
117
|
+
"Examples:",
|
|
118
|
+
" forge-bridge server set http://localhost:5208",
|
|
119
|
+
" forge-bridge server set https://srv1493013.tail66073d.ts.net:8443",
|
|
120
|
+
"",
|
|
121
|
+
].join("\n");
|
|
103
122
|
case "add-repo":
|
|
104
123
|
return [
|
|
105
124
|
"Forge Bridge — add-repo",
|
|
@@ -137,13 +156,28 @@ export function commandHelpText(command) {
|
|
|
137
156
|
case "sandbox":
|
|
138
157
|
return [
|
|
139
158
|
"Forge Bridge — sandbox",
|
|
140
|
-
"
|
|
159
|
+
"Configure local Docker sandbox placement or inspect a repository-owned sandbox contract.",
|
|
141
160
|
"",
|
|
142
161
|
"Usage:",
|
|
162
|
+
" forge-bridge sandbox on [--allow-open-public]",
|
|
163
|
+
" forge-bridge sandbox off",
|
|
164
|
+
" forge-bridge sandbox status",
|
|
143
165
|
" forge-bridge sandbox init [--repo <path>]",
|
|
144
166
|
" forge-bridge sandbox doctor [--repo <path>] [--require-pinned-base]",
|
|
167
|
+
" forge-bridge sandbox smoke [--repo <path>] [--report <path>] [--require-pinned-base] [--probe-loopback-port]",
|
|
145
168
|
" forge-bridge sandbox reap",
|
|
146
169
|
"",
|
|
170
|
+
"`sandbox on` keeps unrestricted public networking denied unless the explicit",
|
|
171
|
+
"developer-only --allow-open-public option is supplied. The local policy is",
|
|
172
|
+
"saved in bridge.json and takes effect after the connected bridge restarts.",
|
|
173
|
+
"Environment variables remain higher-priority operator overrides.",
|
|
174
|
+
"",
|
|
175
|
+
"The smoke command builds the repository Dockerfile, runs a disposable hardened",
|
|
176
|
+
"container, verifies exact-label teardown, and writes a redacted JSON report.",
|
|
177
|
+
"The optional port probe publishes 127.0.0.1::8080 only for the disposable fixture",
|
|
178
|
+
"and verifies Docker-assigned host-port discovery; normal sandboxes publish no ports.",
|
|
179
|
+
"Stop the connected bridge first so the Docker ownership lock can be acquired.",
|
|
180
|
+
"",
|
|
147
181
|
].join("\n");
|
|
148
182
|
case "run-once":
|
|
149
183
|
return [
|
|
@@ -160,7 +194,7 @@ export function commandHelpText(command) {
|
|
|
160
194
|
"Internal MCP server used by provider CLIs to report Forge phase artifacts.",
|
|
161
195
|
"",
|
|
162
196
|
"Usage:",
|
|
163
|
-
" forge-bridge mcp --worktree <path> --work-item-id <id> --phase <phase>",
|
|
197
|
+
" forge-bridge mcp --worktree <path> --work-item-id <id> --phase <phase> # includes ci-repair",
|
|
164
198
|
"",
|
|
165
199
|
].join("\n");
|
|
166
200
|
case "version":
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import type { BridgeService } from "../bridge/bridge.base.js";
|
|
2
2
|
import type { BridgeServiceConfig } from "../bridge/bridge.types.js";
|
|
3
|
+
import type { CleanupMode } from "../cleanup/cleanup.types.js";
|
|
4
|
+
import type { CleanupService } from "../cleanup/cleanup.base.js";
|
|
3
5
|
import type { SessionService } from "../session/session.base.js";
|
|
4
6
|
import type { CliIo, CliService } from "./cli.base.js";
|
|
5
7
|
export declare class ForgeBridgeCliService implements CliService {
|
|
6
8
|
private readonly sessions;
|
|
7
9
|
private readonly bridgeFactory;
|
|
8
10
|
private readonly pairRunner;
|
|
9
|
-
|
|
11
|
+
private readonly cleanupFactory;
|
|
12
|
+
constructor(sessions?: SessionService, bridgeFactory?: (config: BridgeServiceConfig) => BridgeService, pairRunner?: PairRunnerClient, cleanupFactory?: CleanupServiceFactory);
|
|
10
13
|
run(argv: readonly string[], io?: CliIo): Promise<number>;
|
|
11
14
|
}
|
|
12
15
|
export declare function parseArgs(argv: readonly string[]): {
|
|
@@ -34,6 +37,14 @@ export declare function parseArgs(argv: readonly string[]): {
|
|
|
34
37
|
readonly ok: true;
|
|
35
38
|
readonly command: "remove-repo";
|
|
36
39
|
readonly label: string;
|
|
40
|
+
} | {
|
|
41
|
+
readonly ok: true;
|
|
42
|
+
readonly command: "server-show";
|
|
43
|
+
readonly config: BridgeServiceConfig;
|
|
44
|
+
} | {
|
|
45
|
+
readonly ok: true;
|
|
46
|
+
readonly command: "server-set";
|
|
47
|
+
readonly serverUrl: string;
|
|
37
48
|
} | {
|
|
38
49
|
readonly ok: true;
|
|
39
50
|
readonly command: "status";
|
|
@@ -54,9 +65,26 @@ export declare function parseArgs(argv: readonly string[]): {
|
|
|
54
65
|
readonly command: "sandbox-doctor";
|
|
55
66
|
readonly repoPath: string;
|
|
56
67
|
readonly requirePinnedBase: boolean;
|
|
68
|
+
} | {
|
|
69
|
+
readonly ok: true;
|
|
70
|
+
readonly command: "sandbox-smoke";
|
|
71
|
+
readonly repoPath: string;
|
|
72
|
+
readonly reportPath?: string;
|
|
73
|
+
readonly requirePinnedBase: boolean;
|
|
74
|
+
readonly probeLoopbackPort: boolean;
|
|
57
75
|
} | {
|
|
58
76
|
readonly ok: true;
|
|
59
77
|
readonly command: "sandbox-reap";
|
|
78
|
+
} | {
|
|
79
|
+
readonly ok: true;
|
|
80
|
+
readonly command: "sandbox-on";
|
|
81
|
+
readonly allowOpenPublic: boolean;
|
|
82
|
+
} | {
|
|
83
|
+
readonly ok: true;
|
|
84
|
+
readonly command: "sandbox-off";
|
|
85
|
+
} | {
|
|
86
|
+
readonly ok: true;
|
|
87
|
+
readonly command: "sandbox-status";
|
|
60
88
|
} | {
|
|
61
89
|
readonly ok: false;
|
|
62
90
|
readonly error: string;
|
|
@@ -78,5 +106,5 @@ interface PairRunnerClaim {
|
|
|
78
106
|
type PairRunnerClient = (args: PairArgs) => Promise<PairRunnerClaim>;
|
|
79
107
|
export declare function parseCodexModelCatalog(raw: string): string[];
|
|
80
108
|
export declare function parseCursorModelList(raw: string): string[];
|
|
81
|
-
type
|
|
109
|
+
type CleanupServiceFactory = (stateRoot: string) => CleanupService;
|
|
82
110
|
export {};
|
package/dist/cli/cli.service.js
CHANGED
|
@@ -7,14 +7,17 @@ import { promisify } from "node:util";
|
|
|
7
7
|
import { resolveCursorAgentDirectLaunch } from "../shared/cursor-agent/cursor-agent.launch.js";
|
|
8
8
|
import { buildWindowsCmdLaunch } from "../shared/process/windows-launch.js";
|
|
9
9
|
import { supportsDraftImageAttachmentsFor } from "../shared/provider-capabilities.js";
|
|
10
|
-
import {
|
|
10
|
+
import { redactText } from "../shared/redaction/redaction.js";
|
|
11
11
|
import { defaultBridgeServiceConfig, ForgeBridgeService } from "../bridge/bridge.service.js";
|
|
12
12
|
import { forgeBridgeVersion } from "../version.js";
|
|
13
|
-
import {
|
|
13
|
+
import { ManagedWorktreeCleanupService } from "../cleanup/cleanup.service.js";
|
|
14
|
+
import { addRepoMapping, applyLocalConfigDefaults, providerStatusesFor, readLocalConfigSync, removeRepoMapping, resolveLocalConfigPath, setSandboxPolicy, setServerUrl, writeLocalConfig } from "./local-config.js";
|
|
14
15
|
import { BridgeSessionService } from "../session/session.service.js";
|
|
16
|
+
import { redactRunnerDispatchEvent, redactRunOnceResultPacket } from "../session/session-redaction.js";
|
|
15
17
|
import { validateDockerfilePolicy, validateSandboxContract } from "../sandbox/contract.js";
|
|
16
18
|
import { DockerPreflight } from "../sandbox/preflight.js";
|
|
17
19
|
import { DockerSandboxRuntime } from "../sandbox/runtime.js";
|
|
20
|
+
import { DockerSandboxSmoke } from "../sandbox/smoke.js";
|
|
18
21
|
import { parseCompletionMcpArgs, runCompletionMcpServer } from "../session/phase-completion.js";
|
|
19
22
|
import { failureResult, parseRunOnceDispatchPacket } from "../session/session.types.js";
|
|
20
23
|
import { commandHelpText, helpText } from "./cli.help.js";
|
|
@@ -24,10 +27,12 @@ export class ForgeBridgeCliService {
|
|
|
24
27
|
sessions;
|
|
25
28
|
bridgeFactory;
|
|
26
29
|
pairRunner;
|
|
27
|
-
|
|
30
|
+
cleanupFactory;
|
|
31
|
+
constructor(sessions = new BridgeSessionService(), bridgeFactory = (config) => new ForgeBridgeService(config), pairRunner = claimBridgeRunner, cleanupFactory = stateRoot => new ManagedWorktreeCleanupService(stateRoot)) {
|
|
28
32
|
this.sessions = sessions;
|
|
29
33
|
this.bridgeFactory = bridgeFactory;
|
|
30
34
|
this.pairRunner = pairRunner;
|
|
35
|
+
this.cleanupFactory = cleanupFactory;
|
|
31
36
|
}
|
|
32
37
|
async run(argv, io = { stdout: process.stdout, stderr: process.stderr }) {
|
|
33
38
|
if (argv.length === 0 || argv[0] === "--help" || argv[0] === "-h") {
|
|
@@ -122,12 +127,38 @@ export class ForgeBridgeCliService {
|
|
|
122
127
|
return 2;
|
|
123
128
|
}
|
|
124
129
|
}
|
|
130
|
+
if (args.command === "server-show") {
|
|
131
|
+
const saved = readLocalConfigSync().serverUrl ?? "not configured";
|
|
132
|
+
io.stdout.write(`Saved server: ${saved}\n`);
|
|
133
|
+
if (process.env.FORGE_URL?.trim()) {
|
|
134
|
+
io.stdout.write(`Effective server: ${process.env.FORGE_URL.trim()} (FORGE_URL override)\n`);
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
io.stdout.write(`Effective server: ${args.config.serverUrl || "not configured"}\n`);
|
|
138
|
+
}
|
|
139
|
+
return 0;
|
|
140
|
+
}
|
|
141
|
+
if (args.command === "server-set") {
|
|
142
|
+
try {
|
|
143
|
+
const config = await setServerUrl(args.serverUrl);
|
|
144
|
+
io.stdout.write(`Saved Forge server: ${config.serverUrl}\n`);
|
|
145
|
+
io.stdout.write("Existing runner credentials were retained. Re-run `forge-bridge pair --server <url>` if this is a different Forge deployment.\n");
|
|
146
|
+
if (process.env.FORGE_URL?.trim()) {
|
|
147
|
+
io.stdout.write(`Warning: FORGE_URL is set to ${process.env.FORGE_URL.trim()} and overrides the saved server.\n`);
|
|
148
|
+
}
|
|
149
|
+
return 0;
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
io.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
|
|
153
|
+
return 2;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
125
156
|
if (args.command === "status") {
|
|
126
157
|
await writeStatus(args.config, args.checkUpdates, io);
|
|
127
158
|
return 0;
|
|
128
159
|
}
|
|
129
160
|
if (args.command === "cleanup") {
|
|
130
|
-
return await cleanupRepos(args.config, args.mode, args.force, io);
|
|
161
|
+
return await cleanupRepos(args.config, args.mode, args.force, this.cleanupFactory(args.config.sandboxStateRoot), io);
|
|
131
162
|
}
|
|
132
163
|
if (args.command === "sandbox-init") {
|
|
133
164
|
return await initializeSandbox(args.repoPath, io);
|
|
@@ -135,9 +166,28 @@ export class ForgeBridgeCliService {
|
|
|
135
166
|
if (args.command === "sandbox-doctor") {
|
|
136
167
|
return await diagnoseSandbox(args.repoPath, args.requirePinnedBase, io);
|
|
137
168
|
}
|
|
169
|
+
if (args.command === "sandbox-smoke") {
|
|
170
|
+
return await smokeSandbox(args.repoPath, args.reportPath, args.requirePinnedBase, args.probeLoopbackPort, io);
|
|
171
|
+
}
|
|
138
172
|
if (args.command === "sandbox-reap") {
|
|
139
173
|
return await reapSandboxes(io);
|
|
140
174
|
}
|
|
175
|
+
if (args.command === "sandbox-on") {
|
|
176
|
+
const saved = await setSandboxPolicy(true, args.allowOpenPublic);
|
|
177
|
+
io.stdout.write("Saved local Docker sandbox policy. Restart the bridge to apply it.\n");
|
|
178
|
+
writeSandboxPolicyStatus(saved, io);
|
|
179
|
+
return 0;
|
|
180
|
+
}
|
|
181
|
+
if (args.command === "sandbox-off") {
|
|
182
|
+
const saved = await setSandboxPolicy(false, false);
|
|
183
|
+
io.stdout.write("Disabled local Docker sandbox placement. Restart the bridge to apply it.\n");
|
|
184
|
+
writeSandboxPolicyStatus(saved, io);
|
|
185
|
+
return 0;
|
|
186
|
+
}
|
|
187
|
+
if (args.command === "sandbox-status") {
|
|
188
|
+
writeSandboxPolicyStatus(readLocalConfigSync(), io);
|
|
189
|
+
return 0;
|
|
190
|
+
}
|
|
141
191
|
if (args.command === "mcp") {
|
|
142
192
|
const parsed = parseCompletionMcpArgs(args.argv);
|
|
143
193
|
if (!parsed.ok) {
|
|
@@ -156,12 +206,12 @@ export class ForgeBridgeCliService {
|
|
|
156
206
|
emit: async (event) => {
|
|
157
207
|
const line = {
|
|
158
208
|
type: "runner_event",
|
|
159
|
-
event:
|
|
209
|
+
event: redactRunnerDispatchEvent(event, redactionSecrets)
|
|
160
210
|
};
|
|
161
211
|
io.stdout.write(`${JSON.stringify(line)}\n`);
|
|
162
212
|
}
|
|
163
213
|
});
|
|
164
|
-
await writeJsonAtomic(args.resultPath,
|
|
214
|
+
await writeJsonAtomic(args.resultPath, redactRunOnceResultPacket(result, redactionSecrets));
|
|
165
215
|
return result.exitCode;
|
|
166
216
|
}
|
|
167
217
|
catch (error) {
|
|
@@ -247,6 +297,15 @@ export function parseArgs(argv) {
|
|
|
247
297
|
}
|
|
248
298
|
return { ok: true, command: "remove-repo", label: argv[1] };
|
|
249
299
|
}
|
|
300
|
+
if (argv[0] === "server") {
|
|
301
|
+
if (argv.length === 1 || (argv[1] === "show" && argv.length === 2)) {
|
|
302
|
+
return { ok: true, command: "server-show", config: configuredBridgeServiceConfig() };
|
|
303
|
+
}
|
|
304
|
+
if (argv[1] === "set" && argv[2] && argv.length === 3) {
|
|
305
|
+
return { ok: true, command: "server-set", serverUrl: argv[2] };
|
|
306
|
+
}
|
|
307
|
+
return { ok: false, error: "Usage: forge-bridge server <show|set <url>>" };
|
|
308
|
+
}
|
|
250
309
|
if (argv[0] === "status") {
|
|
251
310
|
let checkUpdates = false;
|
|
252
311
|
for (let index = 1; index < argv.length; index += 1) {
|
|
@@ -301,8 +360,26 @@ export function parseArgs(argv) {
|
|
|
301
360
|
}
|
|
302
361
|
function parseSandboxArgs(argv) {
|
|
303
362
|
const action = argv[1];
|
|
363
|
+
if (action === "on") {
|
|
364
|
+
let allowOpenPublic = false;
|
|
365
|
+
for (let index = 2; index < argv.length; index += 1) {
|
|
366
|
+
if (argv[index] === "--allow-open-public") {
|
|
367
|
+
allowOpenPublic = true;
|
|
368
|
+
}
|
|
369
|
+
else {
|
|
370
|
+
return { ok: false, error: `Unknown sandbox argument: ${argv[index]}` };
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
return { ok: true, command: "sandbox-on", allowOpenPublic };
|
|
374
|
+
}
|
|
375
|
+
if (action === "off" && argv.length === 2)
|
|
376
|
+
return { ok: true, command: "sandbox-off" };
|
|
377
|
+
if (action === "status" && argv.length === 2)
|
|
378
|
+
return { ok: true, command: "sandbox-status" };
|
|
304
379
|
let repoPath = process.cwd();
|
|
380
|
+
let reportPath;
|
|
305
381
|
let requirePinnedBase = false;
|
|
382
|
+
let probeLoopbackPort = false;
|
|
306
383
|
for (let index = 2; index < argv.length; index += 1) {
|
|
307
384
|
const arg = argv[index];
|
|
308
385
|
if (arg === "--repo") {
|
|
@@ -310,9 +387,17 @@ function parseSandboxArgs(argv) {
|
|
|
310
387
|
if (!repoPath)
|
|
311
388
|
return { ok: false, error: "--repo requires a path." };
|
|
312
389
|
}
|
|
313
|
-
else if (arg === "--
|
|
390
|
+
else if (arg === "--report" && action === "smoke") {
|
|
391
|
+
reportPath = argv[++index];
|
|
392
|
+
if (!reportPath)
|
|
393
|
+
return { ok: false, error: "--report requires a path." };
|
|
394
|
+
}
|
|
395
|
+
else if (arg === "--require-pinned-base" && (action === "doctor" || action === "smoke")) {
|
|
314
396
|
requirePinnedBase = true;
|
|
315
397
|
}
|
|
398
|
+
else if (arg === "--probe-loopback-port" && action === "smoke") {
|
|
399
|
+
probeLoopbackPort = true;
|
|
400
|
+
}
|
|
316
401
|
else {
|
|
317
402
|
return { ok: false, error: `Unknown sandbox argument: ${arg}` };
|
|
318
403
|
}
|
|
@@ -321,9 +406,18 @@ function parseSandboxArgs(argv) {
|
|
|
321
406
|
return { ok: true, command: "sandbox-init", repoPath: path.resolve(repoPath) };
|
|
322
407
|
if (action === "doctor")
|
|
323
408
|
return { ok: true, command: "sandbox-doctor", repoPath: path.resolve(repoPath), requirePinnedBase };
|
|
409
|
+
if (action === "smoke")
|
|
410
|
+
return {
|
|
411
|
+
ok: true,
|
|
412
|
+
command: "sandbox-smoke",
|
|
413
|
+
repoPath: path.resolve(repoPath),
|
|
414
|
+
reportPath: reportPath ? path.resolve(reportPath) : undefined,
|
|
415
|
+
requirePinnedBase,
|
|
416
|
+
probeLoopbackPort,
|
|
417
|
+
};
|
|
324
418
|
if (action === "reap" && argv.length === 2)
|
|
325
419
|
return { ok: true, command: "sandbox-reap" };
|
|
326
|
-
return { ok: false, error: "Usage: forge-bridge sandbox <init|doctor|reap> [--repo <path>] [--require-pinned-base]" };
|
|
420
|
+
return { ok: false, error: "Usage: forge-bridge sandbox <on|off|status|init|doctor|smoke|reap> [--allow-open-public] [--repo <path>] [--report <path>] [--require-pinned-base] [--probe-loopback-port]" };
|
|
327
421
|
}
|
|
328
422
|
const sandboxContractTemplate = `schemaVersion: 1
|
|
329
423
|
workingDirectory: /workspace
|
|
@@ -389,6 +483,10 @@ async function diagnoseSandbox(repoPath, requirePinnedBase, io) {
|
|
|
389
483
|
diskHighWatermarkPercent: config.diskHighWatermarkPercent,
|
|
390
484
|
diskLowWatermarkPercent: config.diskLowWatermarkPercent,
|
|
391
485
|
minimumWorkspaceBytes: config.minimumWorkspaceBytes,
|
|
486
|
+
hostMemoryReserveBytes: config.sandboxHostMemoryReserveBytes,
|
|
487
|
+
defaultWorkerMemoryLimitBytes: config.defaultSandboxWorkerMemoryLimitBytes,
|
|
488
|
+
defaultServiceMemoryLimitBytes: config.defaultSandboxServiceMemoryLimitBytes,
|
|
489
|
+
runtimeOverheadBytes: config.sandboxRuntimeOverheadBytes,
|
|
392
490
|
requireRootless: config.requireRootlessDocker
|
|
393
491
|
});
|
|
394
492
|
try {
|
|
@@ -409,6 +507,42 @@ async function diagnoseSandbox(repoPath, requirePinnedBase, io) {
|
|
|
409
507
|
return 1;
|
|
410
508
|
}
|
|
411
509
|
}
|
|
510
|
+
async function smokeSandbox(repoPath, reportPath, requirePinnedBase, probeLoopbackPort, io) {
|
|
511
|
+
try {
|
|
512
|
+
const result = await new DockerSandboxSmoke(defaultBridgeServiceConfig()).run({
|
|
513
|
+
repoPath,
|
|
514
|
+
reportPath,
|
|
515
|
+
requirePinnedBase,
|
|
516
|
+
probeLoopbackPort,
|
|
517
|
+
onProgress: (stage) => io.stdout.write(`Smoke: ${stage}...\n`),
|
|
518
|
+
});
|
|
519
|
+
const { report } = result;
|
|
520
|
+
if (report.repository.contractDigest)
|
|
521
|
+
io.stdout.write(`Contract: valid (${report.repository.contractDigest})\n`);
|
|
522
|
+
for (const warning of report.repository.policyWarnings)
|
|
523
|
+
io.stdout.write(`Warning: ${warning}\n`);
|
|
524
|
+
if (report.docker.runtimeVersion) {
|
|
525
|
+
io.stdout.write(`Docker: healthy (${report.docker.runtimeVersion}; capacity ${report.docker.capacity})\n`);
|
|
526
|
+
}
|
|
527
|
+
io.stdout.write(`Attempt: ${report.dispatchAttemptId}\n`);
|
|
528
|
+
io.stdout.write(`Resource lease: ${report.resourceLeaseId}\n`);
|
|
529
|
+
if (report.publishedPortProbe) {
|
|
530
|
+
io.stdout.write(`Loopback port: ${report.publishedPortProbe.hostIp}:${report.publishedPortProbe.hostPort} -> ${report.publishedPortProbe.containerPort}/tcp\n`);
|
|
531
|
+
}
|
|
532
|
+
io.stdout.write(`Cleanup: ${report.cleanup.verified ? "verified (zero exact-label resources)" : "failed"}\n`);
|
|
533
|
+
io.stdout.write(`Report: ${result.reportPath}\n`);
|
|
534
|
+
if (report.status === "passed") {
|
|
535
|
+
io.stdout.write("Sandbox smoke: PASS\n");
|
|
536
|
+
return 0;
|
|
537
|
+
}
|
|
538
|
+
io.stderr.write(`Sandbox smoke: FAIL (${report.failure?.code ?? "sandbox_smoke_failed"} at ${report.failure?.stage ?? "unknown"}): ${report.failure?.message ?? "unknown failure"}\n`);
|
|
539
|
+
return 1;
|
|
540
|
+
}
|
|
541
|
+
catch (error) {
|
|
542
|
+
io.stderr.write(`Sandbox smoke could not write its report: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
543
|
+
return 1;
|
|
544
|
+
}
|
|
545
|
+
}
|
|
412
546
|
async function reapSandboxes(io) {
|
|
413
547
|
const config = defaultBridgeServiceConfig();
|
|
414
548
|
if (!/^[0-9a-f-]{32,36}$/iu.test(config.runnerId)) {
|
|
@@ -423,6 +557,10 @@ async function reapSandboxes(io) {
|
|
|
423
557
|
diskHighWatermarkPercent: config.diskHighWatermarkPercent,
|
|
424
558
|
diskLowWatermarkPercent: config.diskLowWatermarkPercent,
|
|
425
559
|
minimumWorkspaceBytes: config.minimumWorkspaceBytes,
|
|
560
|
+
hostMemoryReserveBytes: config.sandboxHostMemoryReserveBytes,
|
|
561
|
+
defaultWorkerMemoryLimitBytes: config.defaultSandboxWorkerMemoryLimitBytes,
|
|
562
|
+
defaultServiceMemoryLimitBytes: config.defaultSandboxServiceMemoryLimitBytes,
|
|
563
|
+
runtimeOverheadBytes: config.sandboxRuntimeOverheadBytes,
|
|
426
564
|
requireRootless: config.requireRootlessDocker
|
|
427
565
|
});
|
|
428
566
|
try {
|
|
@@ -731,11 +869,27 @@ function connectStartupText(config) {
|
|
|
731
869
|
` repo folder: ${config.defaultRepoRoot || "not configured"}`,
|
|
732
870
|
` providers: ${formatList(config.cliProviders)}`,
|
|
733
871
|
` cleanup worktrees: ${config.cleanupWorktrees ? "enabled" : "disabled"}`,
|
|
872
|
+
` open public sandbox networking: ${config.allowOpenPublicSandbox ? "enabled" : "disabled"}`,
|
|
734
873
|
"",
|
|
735
874
|
"Press Ctrl+C to stop.",
|
|
736
875
|
"",
|
|
737
876
|
].join("\n");
|
|
738
877
|
}
|
|
878
|
+
function writeSandboxPolicyStatus(local, io) {
|
|
879
|
+
const effective = configuredBridgeServiceConfig({}, local);
|
|
880
|
+
io.stdout.write(`Config: ${resolveLocalConfigPath()}\n`);
|
|
881
|
+
io.stdout.write(`Docker sandbox placement: ${effective.dockerEnabled ? "on" : "off"}\n`);
|
|
882
|
+
io.stdout.write(`Open public sandbox networking: ${effective.allowOpenPublicSandbox ? "allowed" : "denied"}\n`);
|
|
883
|
+
if (process.env.FORGE_DOCKER_SANDBOX !== undefined) {
|
|
884
|
+
io.stdout.write("Docker setting source: FORGE_DOCKER_SANDBOX override\n");
|
|
885
|
+
}
|
|
886
|
+
if (process.env.FORGE_ALLOW_OPEN_PUBLIC_SANDBOX !== undefined) {
|
|
887
|
+
io.stdout.write("Open public setting source: FORGE_ALLOW_OPEN_PUBLIC_SANDBOX override\n");
|
|
888
|
+
}
|
|
889
|
+
if (effective.allowOpenPublicSandbox) {
|
|
890
|
+
io.stdout.write("Warning: open_public permits unrestricted outbound network access from developer sandboxes.\n");
|
|
891
|
+
}
|
|
892
|
+
}
|
|
739
893
|
function formatList(values) {
|
|
740
894
|
return values.length > 0 ? values.join(", ") : "none";
|
|
741
895
|
}
|
|
@@ -772,7 +926,7 @@ async function writeStatus(config, checkUpdates, io) {
|
|
|
772
926
|
io.stdout.write("Update check: no update channel configured.\n");
|
|
773
927
|
}
|
|
774
928
|
}
|
|
775
|
-
async function cleanupRepos(config, mode, force, io) {
|
|
929
|
+
async function cleanupRepos(config, mode, force, cleanup, io) {
|
|
776
930
|
const repos = config.repoMappings.filter((mapping) => mapping.localPath?.trim());
|
|
777
931
|
if (repos.length === 0) {
|
|
778
932
|
io.stdout.write("No repos configured.\n");
|
|
@@ -781,20 +935,28 @@ async function cleanupRepos(config, mode, force, io) {
|
|
|
781
935
|
let failures = 0;
|
|
782
936
|
for (const repo of repos) {
|
|
783
937
|
const repoPath = path.resolve(repo.localPath);
|
|
784
|
-
const worktreeRoot = path.join(path.dirname(repoPath), ".forge-worktrees", path.basename(repoPath));
|
|
785
|
-
if (!force) {
|
|
786
|
-
const action = mode === "all" ? "remove" : "prune";
|
|
787
|
-
io.stdout.write(`[dry-run] Would ${action} ${worktreeRoot}\n`);
|
|
788
|
-
continue;
|
|
789
|
-
}
|
|
790
938
|
try {
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
939
|
+
const result = await cleanup.run({
|
|
940
|
+
repoRoot: repoPath,
|
|
941
|
+
allowedRepoRoot: config.defaultRepoRoot || undefined,
|
|
942
|
+
mode,
|
|
943
|
+
force,
|
|
944
|
+
});
|
|
945
|
+
if (!force) {
|
|
946
|
+
const action = mode === "all"
|
|
947
|
+
? "remove"
|
|
948
|
+
: mode === "stale"
|
|
949
|
+
? `remove ${result.candidateWorktrees} stale managed ${result.candidateWorktrees === 1 ? "worktree" : "worktrees"} from`
|
|
950
|
+
: "prune";
|
|
951
|
+
io.stdout.write(`[dry-run] Would ${action} ${result.worktreeRoot}\n`);
|
|
952
|
+
}
|
|
953
|
+
else if (mode === "all") {
|
|
954
|
+
io.stdout.write(`Removed ${result.worktreeRoot}\n`);
|
|
955
|
+
}
|
|
956
|
+
else if (mode === "stale") {
|
|
957
|
+
io.stdout.write(`Removed ${result.removedWorktrees} stale managed ${result.removedWorktrees === 1 ? "worktree" : "worktrees"} from ${result.worktreeRoot}\n`);
|
|
795
958
|
}
|
|
796
959
|
else {
|
|
797
|
-
await runGit(repoPath, ["worktree", "prune"]);
|
|
798
960
|
io.stdout.write(`Pruned stale worktree metadata for ${repoPath}\n`);
|
|
799
961
|
}
|
|
800
962
|
}
|
|
@@ -992,6 +1154,3 @@ function uniqueProviders(providers) {
|
|
|
992
1154
|
.filter((provider) => provider.length > 0)
|
|
993
1155
|
.filter((provider, index, all) => all.findIndex((candidate) => candidate.toLowerCase() === provider.toLowerCase()) === index);
|
|
994
1156
|
}
|
|
995
|
-
async function runGit(cwd, args) {
|
|
996
|
-
await execFileAsync("git", args, { cwd, timeout: 10_000 });
|
|
997
|
-
}
|
|
@@ -7,6 +7,8 @@ export interface BridgeLocalConfig {
|
|
|
7
7
|
readonly deviceName?: string;
|
|
8
8
|
readonly defaultRepoRoot?: string;
|
|
9
9
|
readonly cleanupWorktrees?: boolean;
|
|
10
|
+
readonly dockerEnabled?: boolean;
|
|
11
|
+
readonly allowOpenPublicSandbox?: boolean;
|
|
10
12
|
readonly cliProviders?: readonly string[];
|
|
11
13
|
readonly providerStatuses?: Readonly<Record<string, BridgeProviderStatus>>;
|
|
12
14
|
readonly projectLabels?: readonly string[];
|
|
@@ -34,4 +36,6 @@ export declare function removeRepoMapping(label: string): Promise<{
|
|
|
34
36
|
readonly config: BridgeLocalConfig;
|
|
35
37
|
readonly removed: boolean;
|
|
36
38
|
}>;
|
|
39
|
+
export declare function setServerUrl(serverUrl: string): Promise<BridgeLocalConfig>;
|
|
40
|
+
export declare function setSandboxPolicy(dockerEnabled: boolean, allowOpenPublicSandbox: boolean): Promise<BridgeLocalConfig>;
|
|
37
41
|
export declare function providerStatusesFor(providers: readonly string[]): Readonly<Record<string, BridgeProviderStatus>>;
|
package/dist/cli/local-config.js
CHANGED
|
@@ -45,6 +45,12 @@ export function applyLocalConfigDefaults(config, local) {
|
|
|
45
45
|
deviceName: process.env.FORGE_DEVICE_NAME ?? local.deviceName ?? config.deviceName,
|
|
46
46
|
defaultRepoRoot: process.env.FORGE_REPO_ROOT ?? local.defaultRepoRoot ?? config.defaultRepoRoot,
|
|
47
47
|
cleanupWorktrees: local.cleanupWorktrees ?? config.cleanupWorktrees,
|
|
48
|
+
dockerEnabled: process.env.FORGE_DOCKER_SANDBOX === undefined
|
|
49
|
+
? local.dockerEnabled ?? config.dockerEnabled
|
|
50
|
+
: config.dockerEnabled,
|
|
51
|
+
allowOpenPublicSandbox: process.env.FORGE_ALLOW_OPEN_PUBLIC_SANDBOX === undefined
|
|
52
|
+
? local.allowOpenPublicSandbox ?? config.allowOpenPublicSandbox
|
|
53
|
+
: config.allowOpenPublicSandbox,
|
|
48
54
|
cliProviders,
|
|
49
55
|
providerStatuses: normalizeProviderStatuses(local.providerStatuses) ?? providerStatusesFor(cliProviders),
|
|
50
56
|
projectLabels: local.projectLabels ?? config.projectLabels,
|
|
@@ -88,6 +94,19 @@ export async function removeRepoMapping(label) {
|
|
|
88
94
|
await writeLocalConfig(next);
|
|
89
95
|
return { config: next, removed: after.length !== before.length };
|
|
90
96
|
}
|
|
97
|
+
export async function setServerUrl(serverUrl) {
|
|
98
|
+
const normalized = normalizeServerUrl(serverUrl);
|
|
99
|
+
const current = await readLocalConfig();
|
|
100
|
+
const next = normalizeLocalConfig({ ...current, serverUrl: normalized });
|
|
101
|
+
await writeLocalConfig(next);
|
|
102
|
+
return next;
|
|
103
|
+
}
|
|
104
|
+
export async function setSandboxPolicy(dockerEnabled, allowOpenPublicSandbox) {
|
|
105
|
+
const current = await readLocalConfig();
|
|
106
|
+
const next = normalizeLocalConfig({ ...current, dockerEnabled, allowOpenPublicSandbox });
|
|
107
|
+
await writeLocalConfig(next);
|
|
108
|
+
return next;
|
|
109
|
+
}
|
|
91
110
|
export function providerStatusesFor(providers) {
|
|
92
111
|
return Object.fromEntries(providers.map((provider) => [provider, { signedIn: true, version: "", models: configuredModelsFor(provider) }]));
|
|
93
112
|
}
|
|
@@ -106,6 +125,8 @@ function normalizeLocalConfig(config) {
|
|
|
106
125
|
deviceName: cleanString(config.deviceName),
|
|
107
126
|
defaultRepoRoot: cleanString(config.defaultRepoRoot),
|
|
108
127
|
cleanupWorktrees: config.cleanupWorktrees,
|
|
128
|
+
dockerEnabled: config.dockerEnabled,
|
|
129
|
+
allowOpenPublicSandbox: config.allowOpenPublicSandbox,
|
|
109
130
|
cliProviders: cleanList(config.cliProviders),
|
|
110
131
|
providerStatuses: normalizeProviderStatuses(config.providerStatuses),
|
|
111
132
|
projectLabels: cleanList(config.projectLabels),
|
|
@@ -200,10 +221,11 @@ function normalizeQaAppLaunchTarget(value) {
|
|
|
200
221
|
command: cleanString(value.command),
|
|
201
222
|
working_directory: cleanString(value.working_directory),
|
|
202
223
|
ready_url: cleanString(value.ready_url),
|
|
224
|
+
managed_runtime_port: cleanString(value.managed_runtime_port),
|
|
203
225
|
routes,
|
|
204
226
|
notes: cleanString(value.notes)
|
|
205
227
|
};
|
|
206
|
-
return normalized.url || normalized.command || normalized.ready_url ||
|
|
228
|
+
return normalized.url || normalized.command || normalized.ready_url || normalized.managed_runtime_port
|
|
207
229
|
? normalized
|
|
208
230
|
: undefined;
|
|
209
231
|
}
|
|
@@ -211,6 +233,24 @@ function cleanString(value) {
|
|
|
211
233
|
const clean = value?.trim();
|
|
212
234
|
return clean ? clean : undefined;
|
|
213
235
|
}
|
|
236
|
+
function normalizeServerUrl(value) {
|
|
237
|
+
const clean = value.trim();
|
|
238
|
+
let parsed;
|
|
239
|
+
try {
|
|
240
|
+
parsed = new URL(clean);
|
|
241
|
+
}
|
|
242
|
+
catch {
|
|
243
|
+
throw new Error(`Invalid Forge server URL: ${value}`);
|
|
244
|
+
}
|
|
245
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
246
|
+
throw new Error("Forge server URL must use http or https.");
|
|
247
|
+
}
|
|
248
|
+
if (parsed.username || parsed.password || parsed.search || parsed.hash) {
|
|
249
|
+
throw new Error("Forge server URL cannot include credentials, a query string, or a fragment.");
|
|
250
|
+
}
|
|
251
|
+
parsed.pathname = parsed.pathname.replace(/\/+$/u, "") || "/";
|
|
252
|
+
return parsed.toString().replace(/\/$/u, "");
|
|
253
|
+
}
|
|
214
254
|
function cleanList(values) {
|
|
215
255
|
const clean = [...new Set((values ?? []).map((value) => value.trim()).filter(Boolean))];
|
|
216
256
|
return clean.length > 0 ? clean : undefined;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { AttemptProcessChildHandle, AttemptProcessSupervisor } from "./attempt-process-supervisor.js";
|
|
2
|
+
import type { HostPortLeaseOwner } from "./host-port-broker.js";
|
|
3
|
+
import { HostListenerInspector } from "./host-listener-inspector.js";
|
|
4
|
+
import type { HostListenerOwnership, NodeRuntimeCommandLauncher, NodeRuntimeLaunchRequest, NodeRuntimeReadinessDiagnostics } from "./node-host-runtime-adapter.js";
|
|
5
|
+
/** Launches one explicitly configured HTTP project beneath the attempt coordinator. */
|
|
6
|
+
export declare class AttemptNodeRuntimeLauncher implements NodeRuntimeCommandLauncher<AttemptProcessChildHandle> {
|
|
7
|
+
private readonly supervisor;
|
|
8
|
+
private readonly owner;
|
|
9
|
+
private readonly logDirectory;
|
|
10
|
+
private readonly listenerInspector;
|
|
11
|
+
private readonly diagnosticsByChild;
|
|
12
|
+
constructor(supervisor: AttemptProcessSupervisor, owner: HostPortLeaseOwner, logDirectory: string, listenerInspector?: HostListenerInspector);
|
|
13
|
+
launch(request: NodeRuntimeLaunchRequest, signal?: AbortSignal): Promise<AttemptProcessChildHandle>;
|
|
14
|
+
inspectListener(child: AttemptProcessChildHandle, request: NodeRuntimeLaunchRequest): Promise<HostListenerOwnership>;
|
|
15
|
+
stop(child: AttemptProcessChildHandle): Promise<void>;
|
|
16
|
+
readinessDiagnostics(child: AttemptProcessChildHandle): Promise<NodeRuntimeReadinessDiagnostics>;
|
|
17
|
+
}
|