@loucompanion/forge-bridge 0.1.3-dev.ab8510b71f9b → 0.1.3-dev.af261f369eae
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bridge/bridge.service.js +24 -4
- package/dist/bridge/bridge.types.d.ts +4 -0
- package/dist/cli/cli.help.d.ts +2 -0
- package/dist/cli/cli.help.js +171 -0
- package/dist/cli/cli.service.js +8 -183
- package/dist/cli/local-config.d.ts +2 -0
- package/dist/cli/local-config.js +6 -2
- package/dist/session/phase-completion.artifacts.d.ts +10 -0
- package/dist/session/phase-completion.artifacts.js +620 -0
- package/dist/session/phase-completion.d.ts +32 -44
- package/dist/session/phase-completion.helpers.d.ts +112 -0
- package/dist/session/phase-completion.helpers.js +660 -0
- package/dist/session/phase-completion.js +28 -3497
- package/dist/session/phase-completion.prompts.d.ts +14 -0
- package/dist/session/phase-completion.prompts.js +220 -0
- package/dist/session/phase-completion.runtime.d.ts +36 -0
- package/dist/session/phase-completion.runtime.js +609 -0
- package/dist/session/phase-completion.schemas.d.ts +3 -0
- package/dist/session/phase-completion.schemas.js +707 -0
- package/dist/session/phase-completion.validation.d.ts +34 -0
- package/dist/session/phase-completion.validation.js +724 -0
- package/dist/session/provider-cli/provider-cli.artifacts.d.ts +93 -0
- package/dist/session/provider-cli/provider-cli.artifacts.js +754 -0
- package/dist/session/provider-cli/provider-cli.base.d.ts +1 -0
- package/dist/session/provider-cli/provider-cli.deterministic-payloads.d.ts +12 -0
- package/dist/session/provider-cli/provider-cli.deterministic-payloads.js +279 -0
- package/dist/session/provider-cli/provider-cli.deterministic.d.ts +14 -0
- package/dist/session/provider-cli/provider-cli.deterministic.js +329 -0
- package/dist/session/provider-cli/provider-cli.process.d.ts +32 -0
- package/dist/session/provider-cli/provider-cli.process.js +287 -0
- package/dist/session/provider-cli/provider-cli.prompts.d.ts +44 -0
- package/dist/session/provider-cli/provider-cli.prompts.js +528 -0
- package/dist/session/provider-cli/provider-cli.qa-sidecars.d.ts +11 -0
- package/dist/session/provider-cli/provider-cli.qa-sidecars.js +65 -0
- package/dist/session/provider-cli/provider-cli.runtime.d.ts +9 -0
- package/dist/session/provider-cli/provider-cli.runtime.js +40 -0
- package/dist/session/provider-cli/provider-cli.service.d.ts +9 -53
- package/dist/session/provider-cli/provider-cli.service.js +161 -2561
- package/dist/session/provider-cli/provider-cli.types.d.ts +1 -0
- package/dist/session/provider-cli/provider-output-state.d.ts +20 -0
- package/dist/session/provider-cli/provider-output-state.js +445 -0
- package/dist/session/session.service.js +30 -23
- package/dist/session/session.types.d.ts +48 -0
- package/dist/session/session.types.js +90 -1
- package/dist/shared/process/windows-launch.d.ts +8 -0
- package/dist/shared/process/windows-launch.js +41 -0
- package/dist/shared/provider-capabilities.d.ts +1 -0
- package/dist/shared/provider-capabilities.js +3 -0
- package/dist/shared/redaction/redaction.js +4 -2
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/worktree/dependency-warmer.d.ts +11 -0
- package/dist/worktree/dependency-warmer.js +45 -1
- package/package.json +1 -1
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { HubConnectionBuilder, LogLevel } from "@microsoft/signalr";
|
|
1
|
+
import { HubConnectionBuilder, HttpTransportType, LogLevel } from "@microsoft/signalr";
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { defaultForgeBridgeConfig } from "../config.js";
|
|
5
|
+
import { supportsDraftImageAttachmentsFor } from "../shared/provider-capabilities.js";
|
|
5
6
|
import { redactSecrets, redactText } from "../shared/redaction/redaction.js";
|
|
6
7
|
import { BridgeSessionService } from "../session/session.service.js";
|
|
7
8
|
import { failureResult, parseRunOnceDispatchPacket } from "../session/session.types.js";
|
|
@@ -237,7 +238,9 @@ export class ForgeBridgeService {
|
|
|
237
238
|
supportsManagedWorktrees: this.config.supportsManagedWorktrees,
|
|
238
239
|
supportsManagedForgeArtifacts: this.config.supportsManagedForgeArtifacts,
|
|
239
240
|
supportsRunnerAuthoredPhaseArtifacts: this.config.supportsRunnerAuthoredPhaseArtifacts,
|
|
240
|
-
supportsDraftRunOnce: this.config.supportsDraftRunOnce
|
|
241
|
+
supportsDraftRunOnce: this.config.supportsDraftRunOnce,
|
|
242
|
+
supportsDraftAttachments: this.config.supportsDraftAttachments,
|
|
243
|
+
supportsDraftImageAttachments: this.config.supportsDraftImageAttachments
|
|
241
244
|
};
|
|
242
245
|
}
|
|
243
246
|
async invokeAck(methodName, payload) {
|
|
@@ -293,7 +296,13 @@ export class SignalRBridgeConnection {
|
|
|
293
296
|
url.searchParams.set("runnerId", config.runnerId);
|
|
294
297
|
this.connection = new HubConnectionBuilder()
|
|
295
298
|
.withUrl(url.toString(), {
|
|
296
|
-
|
|
299
|
+
// Query-string access tokens are intentionally rejected by the API. The bridge is
|
|
300
|
+
// a Node CLI, so use long polling where Authorization headers are carried on each
|
|
301
|
+
// HTTP request instead of relying on browser/WebSocket token fallbacks.
|
|
302
|
+
transport: HttpTransportType.LongPolling,
|
|
303
|
+
headers: {
|
|
304
|
+
Authorization: `Bearer ${config.deviceToken}`
|
|
305
|
+
}
|
|
297
306
|
})
|
|
298
307
|
.configureLogging(LogLevel.Warning)
|
|
299
308
|
.build();
|
|
@@ -342,6 +351,8 @@ export function defaultBridgeServiceConfig(overrides = {}) {
|
|
|
342
351
|
supportsManagedForgeArtifacts: true,
|
|
343
352
|
supportsRunnerAuthoredPhaseArtifacts: true,
|
|
344
353
|
supportsDraftRunOnce: true,
|
|
354
|
+
supportsDraftAttachments: true,
|
|
355
|
+
supportsDraftImageAttachments: supportsDraftImageAttachmentsFor(cliProviders),
|
|
345
356
|
version: process.env.FORGE_BRIDGE_VERSION ?? forgeBridgeVersion,
|
|
346
357
|
protocolVersion: 1,
|
|
347
358
|
minServerVersion: null,
|
|
@@ -351,7 +362,9 @@ export function defaultBridgeServiceConfig(overrides = {}) {
|
|
|
351
362
|
};
|
|
352
363
|
return {
|
|
353
364
|
...config,
|
|
365
|
+
providerStatuses: overrides.providerStatuses ?? providerStatusesFor(config.cliProviders),
|
|
354
366
|
sandboxProfiles: config.sandboxProfiles ?? defaultSandboxProfiles(config.cliProviders),
|
|
367
|
+
supportsDraftImageAttachments: (overrides.supportsDraftImageAttachments ?? true) && supportsDraftImageAttachmentsFor(config.cliProviders),
|
|
355
368
|
heartbeatIntervalMs: positiveFiniteNumber(config.heartbeatIntervalMs, 30_000)
|
|
356
369
|
};
|
|
357
370
|
}
|
|
@@ -533,9 +546,16 @@ function abortPromise(signal) {
|
|
|
533
546
|
}
|
|
534
547
|
return new Promise((resolve) => signal.addEventListener("abort", () => resolve(), { once: true }));
|
|
535
548
|
}
|
|
549
|
+
const maxAttachmentExactSecretLength = 8 * 1024;
|
|
536
550
|
function exactSecrets(dispatch, config) {
|
|
537
551
|
return [
|
|
538
552
|
dispatch.apiKeySecretGrant?.secret,
|
|
539
|
-
config.deviceToken
|
|
553
|
+
config.deviceToken,
|
|
554
|
+
...boundedAttachmentExactSecrets(dispatch)
|
|
540
555
|
].filter((secret) => typeof secret === "string" && secret.length > 0);
|
|
541
556
|
}
|
|
557
|
+
function boundedAttachmentExactSecrets(dispatch) {
|
|
558
|
+
return (dispatch.draft?.attachments ?? [])
|
|
559
|
+
.flatMap((attachment) => [attachment.textContent, attachment.contentBase64])
|
|
560
|
+
.filter((secret) => typeof secret === "string" && secret.length > 0 && secret.length <= maxAttachmentExactSecretLength);
|
|
561
|
+
}
|
|
@@ -17,6 +17,8 @@ export interface BridgeServiceConfig {
|
|
|
17
17
|
readonly supportsManagedForgeArtifacts: boolean;
|
|
18
18
|
readonly supportsRunnerAuthoredPhaseArtifacts: boolean;
|
|
19
19
|
readonly supportsDraftRunOnce: boolean;
|
|
20
|
+
readonly supportsDraftAttachments: boolean;
|
|
21
|
+
readonly supportsDraftImageAttachments: boolean;
|
|
20
22
|
readonly version: string;
|
|
21
23
|
readonly protocolVersion: number;
|
|
22
24
|
readonly minServerVersion?: string | null;
|
|
@@ -57,6 +59,8 @@ export interface BridgeCapabilities {
|
|
|
57
59
|
readonly supportsManagedForgeArtifacts?: boolean | null;
|
|
58
60
|
readonly supportsRunnerAuthoredPhaseArtifacts?: boolean | null;
|
|
59
61
|
readonly supportsDraftRunOnce?: boolean | null;
|
|
62
|
+
readonly supportsDraftAttachments?: boolean | null;
|
|
63
|
+
readonly supportsDraftImageAttachments?: boolean | null;
|
|
60
64
|
}
|
|
61
65
|
export interface BridgeHelloRequest {
|
|
62
66
|
readonly version: string;
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { defaultBridgeServiceConfig } from "../bridge/bridge.service.js";
|
|
2
|
+
import { forgeBridgeVersion } from "../version.js";
|
|
3
|
+
export function helpText() {
|
|
4
|
+
const version = defaultBridgeServiceConfig().version ?? forgeBridgeVersion;
|
|
5
|
+
return [
|
|
6
|
+
`🛠 Forge Bridge ${version} — Local provider runners for Forge.`,
|
|
7
|
+
"",
|
|
8
|
+
"Usage: forge-bridge [options] [command]",
|
|
9
|
+
"",
|
|
10
|
+
"Options:",
|
|
11
|
+
" -h, --help Display help for command",
|
|
12
|
+
" -v, --version Output the version number",
|
|
13
|
+
"",
|
|
14
|
+
"Commands:",
|
|
15
|
+
" Hint: commands suffixed with * have detailed help. Run <command> --help for details.",
|
|
16
|
+
" connect * Start the runner bridge and wait for Forge dispatches",
|
|
17
|
+
" pair * Pair this machine with Forge and save runner credentials",
|
|
18
|
+
" status * Show config, runner identity, repos, provider CLIs, and updates",
|
|
19
|
+
" add-repo * Map a Forge repo label/name to a local checkout path",
|
|
20
|
+
" remove-repo * Remove a saved repo mapping",
|
|
21
|
+
" cleanup * Prune managed bridge worktrees",
|
|
22
|
+
" version * Print the installed bridge package version",
|
|
23
|
+
" help * Display help for command",
|
|
24
|
+
" run-once * Internal: run one dispatch packet from JSON",
|
|
25
|
+
" mcp * Internal: run the phase-completion MCP server",
|
|
26
|
+
"",
|
|
27
|
+
"Examples:",
|
|
28
|
+
" npm install -g @loucompanion/forge-bridge@next",
|
|
29
|
+
" forge-bridge pair 1234-5678 --server https://srv1493013.tail66073d.ts.net:8443 --repo-root \"%USERPROFILE%\\ForgeRepos\"",
|
|
30
|
+
" forge-bridge connect",
|
|
31
|
+
" forge-bridge status --check-updates",
|
|
32
|
+
" forge-bridge add-repo Forge D:\\Programming\\repos\\Forge",
|
|
33
|
+
" forge-bridge cleanup --stale",
|
|
34
|
+
"",
|
|
35
|
+
"Troubleshooting:",
|
|
36
|
+
" If Forge says the bridge is old: npm install -g @loucompanion/forge-bridge@next",
|
|
37
|
+
" If connect shows 502/500: leave it open; it reconnects with backoff while dev restarts.",
|
|
38
|
+
" If a provider is missing: run forge-bridge status --check-updates and verify CLI login.",
|
|
39
|
+
"",
|
|
40
|
+
"Docs:",
|
|
41
|
+
" https://github.com/coleman399/Forge/tree/develop/tools/forge-bridge#readme",
|
|
42
|
+
"",
|
|
43
|
+
].join("\n");
|
|
44
|
+
}
|
|
45
|
+
export function commandHelpText(command) {
|
|
46
|
+
switch (command) {
|
|
47
|
+
case "pair":
|
|
48
|
+
return [
|
|
49
|
+
"Forge Bridge — pair",
|
|
50
|
+
"Pair this machine with Forge and save runner credentials.",
|
|
51
|
+
"",
|
|
52
|
+
"Usage:",
|
|
53
|
+
" forge-bridge pair [code] [options]",
|
|
54
|
+
"",
|
|
55
|
+
"Options:",
|
|
56
|
+
" --server <url> Forge server URL.",
|
|
57
|
+
" --repo-root <path> Folder where bridge-managed repos/worktrees live.",
|
|
58
|
+
" --name <name> Display name for this runner.",
|
|
59
|
+
" --fingerprint <value> Stable device fingerprint override.",
|
|
60
|
+
" --cli-provider <list> Comma-separated providers, e.g. codex,cursor.",
|
|
61
|
+
" --cleanup-worktrees Enable managed worktree cleanup.",
|
|
62
|
+
" --no-cleanup-worktrees Disable managed worktree cleanup.",
|
|
63
|
+
"",
|
|
64
|
+
"Example:",
|
|
65
|
+
" forge-bridge pair 1234-5678 --server https://forge.example.com --repo-root \"%USERPROFILE%\\ForgeRepos\"",
|
|
66
|
+
"",
|
|
67
|
+
].join("\n");
|
|
68
|
+
case "connect":
|
|
69
|
+
return [
|
|
70
|
+
"Forge Bridge — connect",
|
|
71
|
+
"Start the runner bridge and keep it connected for Forge dispatches.",
|
|
72
|
+
"",
|
|
73
|
+
"Usage:",
|
|
74
|
+
" forge-bridge connect [options]",
|
|
75
|
+
"",
|
|
76
|
+
"Options:",
|
|
77
|
+
" --server <url> Forge server URL; saved config is used when omitted.",
|
|
78
|
+
" --runner-id <id> Runner id; saved config is used when omitted.",
|
|
79
|
+
" --device-token <token> Device token; saved config is used when omitted.",
|
|
80
|
+
" --repo-root <path> Override repo/worktree folder for this run.",
|
|
81
|
+
" --cli-provider <list> Comma-separated providers, e.g. codex,cursor.",
|
|
82
|
+
" --heartbeat-interval-ms <n> Heartbeat interval in milliseconds.",
|
|
83
|
+
" --cleanup-worktrees Enable managed worktree cleanup for this run.",
|
|
84
|
+
" --no-cleanup-worktrees Disable managed worktree cleanup for this run.",
|
|
85
|
+
"",
|
|
86
|
+
"Example:",
|
|
87
|
+
" forge-bridge connect",
|
|
88
|
+
"",
|
|
89
|
+
].join("\n");
|
|
90
|
+
case "status":
|
|
91
|
+
return [
|
|
92
|
+
"Forge Bridge — status",
|
|
93
|
+
"Show saved configuration, paired runner identity, repo mappings, detected provider CLIs, and optional update info.",
|
|
94
|
+
"",
|
|
95
|
+
"Usage:",
|
|
96
|
+
" forge-bridge status [--check-updates]",
|
|
97
|
+
"",
|
|
98
|
+
"Example:",
|
|
99
|
+
" forge-bridge status --check-updates",
|
|
100
|
+
"",
|
|
101
|
+
].join("\n");
|
|
102
|
+
case "add-repo":
|
|
103
|
+
return [
|
|
104
|
+
"Forge Bridge — add-repo",
|
|
105
|
+
"Map a Forge repo label/name to an existing local checkout.",
|
|
106
|
+
"",
|
|
107
|
+
"Usage:",
|
|
108
|
+
" forge-bridge add-repo <label> <path>",
|
|
109
|
+
"",
|
|
110
|
+
"Example:",
|
|
111
|
+
" forge-bridge add-repo Forge D:\\Programming\\repos\\Forge",
|
|
112
|
+
"",
|
|
113
|
+
].join("\n");
|
|
114
|
+
case "remove-repo":
|
|
115
|
+
return [
|
|
116
|
+
"Forge Bridge — remove-repo",
|
|
117
|
+
"Remove a saved local repo mapping.",
|
|
118
|
+
"",
|
|
119
|
+
"Usage:",
|
|
120
|
+
" forge-bridge remove-repo <label>",
|
|
121
|
+
"",
|
|
122
|
+
].join("\n");
|
|
123
|
+
case "cleanup":
|
|
124
|
+
return [
|
|
125
|
+
"Forge Bridge — cleanup",
|
|
126
|
+
"Prune managed bridge worktrees under the configured repo folder.",
|
|
127
|
+
"",
|
|
128
|
+
"Usage:",
|
|
129
|
+
" forge-bridge cleanup [--stale|--merged|--all] [--force]",
|
|
130
|
+
"",
|
|
131
|
+
"Examples:",
|
|
132
|
+
" forge-bridge cleanup --stale",
|
|
133
|
+
" forge-bridge cleanup --all --force",
|
|
134
|
+
"",
|
|
135
|
+
].join("\n");
|
|
136
|
+
case "run-once":
|
|
137
|
+
return [
|
|
138
|
+
"Forge Bridge — run-once",
|
|
139
|
+
"Internal command used by Forge to run a single dispatch packet.",
|
|
140
|
+
"",
|
|
141
|
+
"Usage:",
|
|
142
|
+
" forge-bridge run-once --dispatch <dispatch-json-path> --result <result-json-path>",
|
|
143
|
+
"",
|
|
144
|
+
].join("\n");
|
|
145
|
+
case "mcp":
|
|
146
|
+
return [
|
|
147
|
+
"Forge Bridge — mcp",
|
|
148
|
+
"Internal MCP server used by provider CLIs to report Forge phase artifacts.",
|
|
149
|
+
"",
|
|
150
|
+
"Usage:",
|
|
151
|
+
" forge-bridge mcp --worktree <path> --work-item-id <id> --phase <phase>",
|
|
152
|
+
"",
|
|
153
|
+
].join("\n");
|
|
154
|
+
case "version":
|
|
155
|
+
return [
|
|
156
|
+
"Forge Bridge — version",
|
|
157
|
+
"Print the installed bridge package version.",
|
|
158
|
+
"",
|
|
159
|
+
"Usage:",
|
|
160
|
+
" forge-bridge version",
|
|
161
|
+
"",
|
|
162
|
+
].join("\n");
|
|
163
|
+
default:
|
|
164
|
+
return [
|
|
165
|
+
`Unknown forge-bridge command: ${command}`,
|
|
166
|
+
"",
|
|
167
|
+
"Run `forge-bridge help` to see available commands.",
|
|
168
|
+
"",
|
|
169
|
+
].join("\n");
|
|
170
|
+
}
|
|
171
|
+
}
|
package/dist/cli/cli.service.js
CHANGED
|
@@ -5,6 +5,8 @@ import path from "node:path";
|
|
|
5
5
|
import { createInterface } from "node:readline/promises";
|
|
6
6
|
import { promisify } from "node:util";
|
|
7
7
|
import { resolveCursorAgentDirectLaunch } from "../shared/cursor-agent/cursor-agent.launch.js";
|
|
8
|
+
import { buildWindowsCmdLaunch } from "../shared/process/windows-launch.js";
|
|
9
|
+
import { supportsDraftImageAttachmentsFor } from "../shared/provider-capabilities.js";
|
|
8
10
|
import { redactSecrets, redactText } from "../shared/redaction/redaction.js";
|
|
9
11
|
import { defaultBridgeServiceConfig, ForgeBridgeService } from "../bridge/bridge.service.js";
|
|
10
12
|
import { forgeBridgeVersion } from "../version.js";
|
|
@@ -12,6 +14,7 @@ import { addRepoMapping, applyLocalConfigDefaults, providerStatusesFor, readLoca
|
|
|
12
14
|
import { BridgeSessionService } from "../session/session.service.js";
|
|
13
15
|
import { parseCompletionMcpArgs, runCompletionMcpServer } from "../session/phase-completion.js";
|
|
14
16
|
import { failureResult, parseRunOnceDispatchPacket } from "../session/session.types.js";
|
|
17
|
+
import { commandHelpText, helpText } from "./cli.help.js";
|
|
15
18
|
const apiKeySecretGrantEnv = "FORGE_API_KEY_SECRET_GRANT";
|
|
16
19
|
const execFileAsync = promisify(execFile);
|
|
17
20
|
export class ForgeBridgeCliService {
|
|
@@ -253,7 +256,7 @@ export function parseArgs(argv) {
|
|
|
253
256
|
if (argv[0] !== "run-once") {
|
|
254
257
|
return {
|
|
255
258
|
ok: false,
|
|
256
|
-
error:
|
|
259
|
+
error: helpText()
|
|
257
260
|
};
|
|
258
261
|
}
|
|
259
262
|
let dispatchPath = null;
|
|
@@ -497,6 +500,8 @@ function pairedConfig(current, args, claim) {
|
|
|
497
500
|
supportsManagedForgeArtifacts: current.supportsManagedForgeArtifacts ?? true,
|
|
498
501
|
supportsRunnerAuthoredPhaseArtifacts: current.supportsRunnerAuthoredPhaseArtifacts ?? true,
|
|
499
502
|
supportsDraftRunOnce: current.supportsDraftRunOnce ?? true,
|
|
503
|
+
supportsDraftAttachments: current.supportsDraftAttachments ?? true,
|
|
504
|
+
supportsDraftImageAttachments: supportsDraftImageAttachmentsFor(args.cliProviders),
|
|
500
505
|
repoMappings: current.repoMappings ?? []
|
|
501
506
|
};
|
|
502
507
|
}
|
|
@@ -544,178 +549,6 @@ function normalizePairingCode(code) {
|
|
|
544
549
|
function normalizeServerUrl(serverUrl) {
|
|
545
550
|
return serverUrl.endsWith("/") ? serverUrl : `${serverUrl}/`;
|
|
546
551
|
}
|
|
547
|
-
function usage() {
|
|
548
|
-
return helpText();
|
|
549
|
-
}
|
|
550
|
-
function helpText() {
|
|
551
|
-
const version = defaultBridgeServiceConfig().version ?? forgeBridgeVersion;
|
|
552
|
-
return [
|
|
553
|
-
`🛠 Forge Bridge ${version} — Local provider runners for Forge.`,
|
|
554
|
-
"",
|
|
555
|
-
"Usage: forge-bridge [options] [command]",
|
|
556
|
-
"",
|
|
557
|
-
"Options:",
|
|
558
|
-
" -h, --help Display help for command",
|
|
559
|
-
" -v, --version Output the version number",
|
|
560
|
-
"",
|
|
561
|
-
"Commands:",
|
|
562
|
-
" Hint: commands suffixed with * have detailed help. Run <command> --help for details.",
|
|
563
|
-
" connect * Start the runner bridge and wait for Forge dispatches",
|
|
564
|
-
" pair * Pair this machine with Forge and save runner credentials",
|
|
565
|
-
" status * Show config, runner identity, repos, provider CLIs, and updates",
|
|
566
|
-
" add-repo * Map a Forge repo label/name to a local checkout path",
|
|
567
|
-
" remove-repo * Remove a saved repo mapping",
|
|
568
|
-
" cleanup * Prune managed bridge worktrees",
|
|
569
|
-
" version * Print the installed bridge package version",
|
|
570
|
-
" help * Display help for command",
|
|
571
|
-
" run-once * Internal: run one dispatch packet from JSON",
|
|
572
|
-
" mcp * Internal: run the phase-completion MCP server",
|
|
573
|
-
"",
|
|
574
|
-
"Examples:",
|
|
575
|
-
" npm install -g @loucompanion/forge-bridge@next",
|
|
576
|
-
" forge-bridge pair 1234-5678 --server https://srv1493013.tail66073d.ts.net:8443 --repo-root \"%USERPROFILE%\\ForgeRepos\"",
|
|
577
|
-
" forge-bridge connect",
|
|
578
|
-
" forge-bridge status --check-updates",
|
|
579
|
-
" forge-bridge add-repo Forge D:\\Programming\\repos\\Forge",
|
|
580
|
-
" forge-bridge cleanup --stale",
|
|
581
|
-
"",
|
|
582
|
-
"Troubleshooting:",
|
|
583
|
-
" If Forge says the bridge is old: npm install -g @loucompanion/forge-bridge@next",
|
|
584
|
-
" If connect shows 502/500: leave it open; it reconnects with backoff while dev restarts.",
|
|
585
|
-
" If a provider is missing: run forge-bridge status --check-updates and verify CLI login.",
|
|
586
|
-
"",
|
|
587
|
-
"Docs:",
|
|
588
|
-
" https://github.com/coleman399/Forge/tree/develop/tools/forge-bridge#readme",
|
|
589
|
-
"",
|
|
590
|
-
].join("\n");
|
|
591
|
-
}
|
|
592
|
-
function commandHelpText(command) {
|
|
593
|
-
switch (command) {
|
|
594
|
-
case "pair":
|
|
595
|
-
return [
|
|
596
|
-
"Forge Bridge — pair",
|
|
597
|
-
"Pair this machine with Forge and save runner credentials.",
|
|
598
|
-
"",
|
|
599
|
-
"Usage:",
|
|
600
|
-
" forge-bridge pair [code] [options]",
|
|
601
|
-
"",
|
|
602
|
-
"Options:",
|
|
603
|
-
" --server <url> Forge server URL.",
|
|
604
|
-
" --repo-root <path> Folder where bridge-managed repos/worktrees live.",
|
|
605
|
-
" --name <name> Display name for this runner.",
|
|
606
|
-
" --fingerprint <value> Stable device fingerprint override.",
|
|
607
|
-
" --cli-provider <list> Comma-separated providers, e.g. codex,cursor.",
|
|
608
|
-
" --cleanup-worktrees Enable managed worktree cleanup.",
|
|
609
|
-
" --no-cleanup-worktrees Disable managed worktree cleanup.",
|
|
610
|
-
"",
|
|
611
|
-
"Example:",
|
|
612
|
-
" forge-bridge pair 1234-5678 --server https://forge.example.com --repo-root \"%USERPROFILE%\\ForgeRepos\"",
|
|
613
|
-
"",
|
|
614
|
-
].join("\n");
|
|
615
|
-
case "connect":
|
|
616
|
-
return [
|
|
617
|
-
"Forge Bridge — connect",
|
|
618
|
-
"Start the runner bridge and keep it connected for Forge dispatches.",
|
|
619
|
-
"",
|
|
620
|
-
"Usage:",
|
|
621
|
-
" forge-bridge connect [options]",
|
|
622
|
-
"",
|
|
623
|
-
"Options:",
|
|
624
|
-
" --server <url> Forge server URL; saved config is used when omitted.",
|
|
625
|
-
" --runner-id <id> Runner id; saved config is used when omitted.",
|
|
626
|
-
" --device-token <token> Device token; saved config is used when omitted.",
|
|
627
|
-
" --repo-root <path> Override repo/worktree folder for this run.",
|
|
628
|
-
" --cli-provider <list> Comma-separated providers, e.g. codex,cursor.",
|
|
629
|
-
" --heartbeat-interval-ms <n> Heartbeat interval in milliseconds.",
|
|
630
|
-
" --cleanup-worktrees Enable managed worktree cleanup for this run.",
|
|
631
|
-
" --no-cleanup-worktrees Disable managed worktree cleanup for this run.",
|
|
632
|
-
"",
|
|
633
|
-
"Example:",
|
|
634
|
-
" forge-bridge connect",
|
|
635
|
-
"",
|
|
636
|
-
].join("\n");
|
|
637
|
-
case "status":
|
|
638
|
-
return [
|
|
639
|
-
"Forge Bridge — status",
|
|
640
|
-
"Show saved configuration, paired runner identity, repo mappings, detected provider CLIs, and optional update info.",
|
|
641
|
-
"",
|
|
642
|
-
"Usage:",
|
|
643
|
-
" forge-bridge status [--check-updates]",
|
|
644
|
-
"",
|
|
645
|
-
"Example:",
|
|
646
|
-
" forge-bridge status --check-updates",
|
|
647
|
-
"",
|
|
648
|
-
].join("\n");
|
|
649
|
-
case "add-repo":
|
|
650
|
-
return [
|
|
651
|
-
"Forge Bridge — add-repo",
|
|
652
|
-
"Map a Forge repo label/name to an existing local checkout.",
|
|
653
|
-
"",
|
|
654
|
-
"Usage:",
|
|
655
|
-
" forge-bridge add-repo <label> <path>",
|
|
656
|
-
"",
|
|
657
|
-
"Example:",
|
|
658
|
-
" forge-bridge add-repo Forge D:\\Programming\\repos\\Forge",
|
|
659
|
-
"",
|
|
660
|
-
].join("\n");
|
|
661
|
-
case "remove-repo":
|
|
662
|
-
return [
|
|
663
|
-
"Forge Bridge — remove-repo",
|
|
664
|
-
"Remove a saved local repo mapping.",
|
|
665
|
-
"",
|
|
666
|
-
"Usage:",
|
|
667
|
-
" forge-bridge remove-repo <label>",
|
|
668
|
-
"",
|
|
669
|
-
].join("\n");
|
|
670
|
-
case "cleanup":
|
|
671
|
-
return [
|
|
672
|
-
"Forge Bridge — cleanup",
|
|
673
|
-
"Prune managed bridge worktrees under the configured repo folder.",
|
|
674
|
-
"",
|
|
675
|
-
"Usage:",
|
|
676
|
-
" forge-bridge cleanup [--stale|--merged|--all] [--force]",
|
|
677
|
-
"",
|
|
678
|
-
"Examples:",
|
|
679
|
-
" forge-bridge cleanup --stale",
|
|
680
|
-
" forge-bridge cleanup --all --force",
|
|
681
|
-
"",
|
|
682
|
-
].join("\n");
|
|
683
|
-
case "run-once":
|
|
684
|
-
return [
|
|
685
|
-
"Forge Bridge — run-once",
|
|
686
|
-
"Internal command used by Forge to run a single dispatch packet.",
|
|
687
|
-
"",
|
|
688
|
-
"Usage:",
|
|
689
|
-
" forge-bridge run-once --dispatch <dispatch-json-path> --result <result-json-path>",
|
|
690
|
-
"",
|
|
691
|
-
].join("\n");
|
|
692
|
-
case "mcp":
|
|
693
|
-
return [
|
|
694
|
-
"Forge Bridge — mcp",
|
|
695
|
-
"Internal MCP server used by provider CLIs to report Forge phase artifacts.",
|
|
696
|
-
"",
|
|
697
|
-
"Usage:",
|
|
698
|
-
" forge-bridge mcp --worktree <path> --work-item-id <id> --phase <phase>",
|
|
699
|
-
"",
|
|
700
|
-
].join("\n");
|
|
701
|
-
case "version":
|
|
702
|
-
return [
|
|
703
|
-
"Forge Bridge — version",
|
|
704
|
-
"Print the installed bridge package version.",
|
|
705
|
-
"",
|
|
706
|
-
"Usage:",
|
|
707
|
-
" forge-bridge version",
|
|
708
|
-
"",
|
|
709
|
-
].join("\n");
|
|
710
|
-
default:
|
|
711
|
-
return [
|
|
712
|
-
`Unknown forge-bridge command: ${command}`,
|
|
713
|
-
"",
|
|
714
|
-
"Run `forge-bridge help` to see available commands.",
|
|
715
|
-
"",
|
|
716
|
-
].join("\n");
|
|
717
|
-
}
|
|
718
|
-
}
|
|
719
552
|
function connectStartupText(config) {
|
|
720
553
|
const runner = config.runnerId
|
|
721
554
|
? `${config.runnerId}${config.deviceName ? ` (${config.deviceName})` : ""}`
|
|
@@ -862,17 +695,9 @@ async function execVersionCommand(probe, timeout = 2000) {
|
|
|
862
695
|
if (process.platform !== "win32") {
|
|
863
696
|
throw error;
|
|
864
697
|
}
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
}
|
|
868
|
-
function windowsCommandLine(probe) {
|
|
869
|
-
return [probe.command, ...probe.args].map(quoteWindowsCommandLineArg).join(" ");
|
|
870
|
-
}
|
|
871
|
-
function quoteWindowsCommandLineArg(value) {
|
|
872
|
-
if (value.length > 0 && !/[\s"]/.test(value)) {
|
|
873
|
-
return value;
|
|
698
|
+
const launch = buildWindowsCmdLaunch(probe.command, probe.args);
|
|
699
|
+
return await execFileAsync(launch.command, [...launch.args], { timeout });
|
|
874
700
|
}
|
|
875
|
-
return `"${value.replace(/(\\*)"/g, '$1$1\\"').replace(/(\\+)$/g, "$1$1")}"`;
|
|
876
701
|
}
|
|
877
702
|
function versionLine(output) {
|
|
878
703
|
const lines = output
|
|
@@ -17,6 +17,8 @@ export interface BridgeLocalConfig {
|
|
|
17
17
|
readonly supportsManagedForgeArtifacts?: boolean;
|
|
18
18
|
readonly supportsRunnerAuthoredPhaseArtifacts?: boolean;
|
|
19
19
|
readonly supportsDraftRunOnce?: boolean;
|
|
20
|
+
readonly supportsDraftAttachments?: boolean;
|
|
21
|
+
readonly supportsDraftImageAttachments?: boolean;
|
|
20
22
|
}
|
|
21
23
|
export interface LocalRepoMapping extends BridgeRepoMapping {
|
|
22
24
|
readonly label: string;
|
package/dist/cli/local-config.js
CHANGED
|
@@ -54,7 +54,9 @@ export function applyLocalConfigDefaults(config, local) {
|
|
|
54
54
|
supportsManagedWorktrees: local.supportsManagedWorktrees ?? config.supportsManagedWorktrees,
|
|
55
55
|
supportsManagedForgeArtifacts: local.supportsManagedForgeArtifacts ?? config.supportsManagedForgeArtifacts,
|
|
56
56
|
supportsRunnerAuthoredPhaseArtifacts: local.supportsRunnerAuthoredPhaseArtifacts ?? config.supportsRunnerAuthoredPhaseArtifacts,
|
|
57
|
-
supportsDraftRunOnce: local.supportsDraftRunOnce ?? config.supportsDraftRunOnce
|
|
57
|
+
supportsDraftRunOnce: local.supportsDraftRunOnce ?? config.supportsDraftRunOnce,
|
|
58
|
+
supportsDraftAttachments: local.supportsDraftAttachments ?? config.supportsDraftAttachments,
|
|
59
|
+
supportsDraftImageAttachments: local.supportsDraftImageAttachments ?? config.supportsDraftImageAttachments
|
|
58
60
|
};
|
|
59
61
|
}
|
|
60
62
|
export async function addRepoMapping(label, repoPath) {
|
|
@@ -113,7 +115,9 @@ function normalizeLocalConfig(config) {
|
|
|
113
115
|
supportsManagedWorktrees: config.supportsManagedWorktrees,
|
|
114
116
|
supportsManagedForgeArtifacts: config.supportsManagedForgeArtifacts,
|
|
115
117
|
supportsRunnerAuthoredPhaseArtifacts: config.supportsRunnerAuthoredPhaseArtifacts,
|
|
116
|
-
supportsDraftRunOnce: config.supportsDraftRunOnce
|
|
118
|
+
supportsDraftRunOnce: config.supportsDraftRunOnce,
|
|
119
|
+
supportsDraftAttachments: config.supportsDraftAttachments,
|
|
120
|
+
supportsDraftImageAttachments: config.supportsDraftImageAttachments
|
|
117
121
|
};
|
|
118
122
|
}
|
|
119
123
|
function emptyConfig() {
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type CompletionArtifactReference, type CompletionPhase, type CompletionToolServerConfig, type DecomposeCompletionGate, type DraftCompletionGate, type QaCompletionGate } from "./phase-completion.js";
|
|
2
|
+
import type { RunnerDispatchArtifact } from "./session.types.js";
|
|
3
|
+
export declare function writeDecomposeGateCompletionArtifact(config: CompletionToolServerConfig, gate: DecomposeCompletionGate, toolName: string, input: unknown): Promise<CompletionArtifactReference>;
|
|
4
|
+
export declare function writeDraftGateCompletionArtifact(config: CompletionToolServerConfig, gate: DraftCompletionGate, toolName: string, input: unknown): Promise<CompletionArtifactReference>;
|
|
5
|
+
export declare function writeCompletionArtifact(config: CompletionToolServerConfig, toolName: string, input: unknown): Promise<CompletionArtifactReference>;
|
|
6
|
+
export declare function writeArchitectCompletionArtifact(config: CompletionToolServerConfig, payload: Record<string, unknown>, status: string, producedBy: string): Promise<CompletionArtifactReference>;
|
|
7
|
+
export declare function writeQaGateCompletionArtifact(config: CompletionToolServerConfig, gate: QaCompletionGate, input: unknown): Promise<CompletionArtifactReference>;
|
|
8
|
+
export declare function writeQaCompletionArtifact(config: CompletionToolServerConfig, payload: Record<string, unknown>, status: string, producedBy: string): Promise<CompletionArtifactReference>;
|
|
9
|
+
export declare function readQaGateArtifact(config: CompletionToolServerConfig, gate: QaCompletionGate): Promise<Record<string, unknown>>;
|
|
10
|
+
export declare function readCompletionArtifact(worktreePath: string, workItemId: string, phase: CompletionPhase, ownerType?: string | null, ownerId?: string | null): Promise<RunnerDispatchArtifact | null>;
|