@loucompanion/forge-bridge 0.1.1-dev.03b8ba168599 → 0.1.1-dev.32d4dd5874ee

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.
@@ -14,6 +14,10 @@ export declare function parseArgs(argv: readonly string[]): {
14
14
  readonly command: "run-once";
15
15
  readonly dispatchPath: string;
16
16
  readonly resultPath: string;
17
+ } | {
18
+ readonly ok: true;
19
+ readonly command: "mcp";
20
+ readonly argv: readonly string[];
17
21
  } | {
18
22
  readonly ok: true;
19
23
  readonly command: "connect";
@@ -4,10 +4,12 @@ import os from "node:os";
4
4
  import path from "node:path";
5
5
  import { createInterface } from "node:readline/promises";
6
6
  import { promisify } from "node:util";
7
+ import { resolveCursorAgentDirectLaunch } from "../shared/cursor-agent/cursor-agent.launch.js";
7
8
  import { redactSecrets, redactText } from "../shared/redaction/redaction.js";
8
9
  import { defaultBridgeServiceConfig, ForgeBridgeService } from "../bridge/bridge.service.js";
9
10
  import { addRepoMapping, applyLocalConfigDefaults, providerStatusesFor, readLocalConfigSync, removeRepoMapping, resolveLocalConfigPath, writeLocalConfig } from "./local-config.js";
10
11
  import { BridgeSessionService } from "../session/session.service.js";
12
+ import { parseCompletionMcpArgs, runCompletionMcpServer } from "../session/phase-completion.js";
11
13
  import { failureResult, parseRunOnceDispatchPacket } from "../session/session.types.js";
12
14
  const apiKeySecretGrantEnv = "FORGE_API_KEY_SECRET_GRANT";
13
15
  const execFileAsync = promisify(execFile);
@@ -102,6 +104,15 @@ export class ForgeBridgeCliService {
102
104
  if (args.command === "cleanup") {
103
105
  return await cleanupRepos(args.config, args.mode, args.force, io);
104
106
  }
107
+ if (args.command === "mcp") {
108
+ const parsed = parseCompletionMcpArgs(args.argv);
109
+ if (!parsed.ok) {
110
+ io.stderr.write(`${parsed.error}\n`);
111
+ return 2;
112
+ }
113
+ await runCompletionMcpServer(parsed.config);
114
+ return 0;
115
+ }
105
116
  let redactionSecrets = readEnvSecretValuesForRedaction();
106
117
  try {
107
118
  const dispatchJson = await fs.readFile(args.dispatchPath, "utf8");
@@ -214,6 +225,9 @@ export function parseArgs(argv) {
214
225
  if (argv[0] === "cleanup") {
215
226
  return parseCleanupArgs(argv);
216
227
  }
228
+ if (argv[0] === "mcp") {
229
+ return { ok: true, command: "mcp", argv };
230
+ }
217
231
  if (argv[0] !== "run-once") {
218
232
  return {
219
233
  ok: false,
@@ -508,7 +522,7 @@ function normalizeServerUrl(serverUrl) {
508
522
  return serverUrl.endsWith("/") ? serverUrl : `${serverUrl}/`;
509
523
  }
510
524
  function usage() {
511
- return "Usage: forge-bridge run-once --dispatch <dispatch-json-path> --result <result-json-path> | forge-bridge pair [code] [--server <url>] | forge-bridge connect --server <url> --runner-id <id> --device-token <token> | forge-bridge add-repo <label> <path> | forge-bridge remove-repo <label> | forge-bridge status [--check-updates] | forge-bridge cleanup [--stale|--merged|--all|--force]";
525
+ return "Usage: forge-bridge run-once --dispatch <dispatch-json-path> --result <result-json-path> | forge-bridge mcp --worktree <path> --work-item-id <id> --phase <phase> | forge-bridge pair [code] [--server <url>] | forge-bridge connect --server <url> --runner-id <id> --device-token <token> | forge-bridge add-repo <label> <path> | forge-bridge remove-repo <label> | forge-bridge status [--check-updates] | forge-bridge cleanup [--stale|--merged|--all|--force]";
512
526
  }
513
527
  async function writeJsonAtomic(outputPath, value) {
514
528
  await fs.mkdir(path.dirname(outputPath), { recursive: true });
@@ -620,6 +634,12 @@ function cliProbeCommandsFor(provider) {
620
634
  ];
621
635
  }
622
636
  async function execVersionCommand(probe, timeout = 2000) {
637
+ const directLaunch = process.platform === "win32"
638
+ ? await resolveCursorAgentDirectLaunch(probe.command, probe.args)
639
+ : null;
640
+ if (directLaunch) {
641
+ return await execFileAsync(directLaunch.command, [...directLaunch.args], { timeout });
642
+ }
623
643
  try {
624
644
  return await execFileAsync(probe.command, probe.args, { timeout });
625
645
  }
@@ -1,2 +1,4 @@
1
1
  export { BridgeSessionService } from "./session.service.js";
2
+ export { buildCompletionToolServerArgs, codexMcpConfigArgs, completionPhaseFromDispatch, expectedCompletionToolName, prepareCompletionToolRuntime, readCompletionArtifact, writeCompletionArtifact } from "./phase-completion.js";
3
+ export type { CompletionArtifactReference, CompletionPhase, CompletionToolRuntime } from "./phase-completion.js";
2
4
  export type { SessionService } from "./session.base.js";
@@ -1 +1,2 @@
1
1
  export { BridgeSessionService } from "./session.service.js";
2
+ export { buildCompletionToolServerArgs, codexMcpConfigArgs, completionPhaseFromDispatch, expectedCompletionToolName, prepareCompletionToolRuntime, readCompletionArtifact, writeCompletionArtifact } from "./phase-completion.js";
@@ -1,4 +1,6 @@
1
1
  export { parseRunOnceDispatchPacket, failureResult } from "./session.types.js";
2
+ export { buildCompletionToolServerArgs, codexMcpConfigArgs, completionPhaseFromDispatch, expectedCompletionToolName, prepareCompletionToolRuntime, readCompletionArtifact, writeCompletionArtifact } from "./phase-completion.js";
3
+ export type { CompletionArtifactReference, CompletionPhase, CompletionToolRuntime } from "./phase-completion.js";
2
4
  export type { SessionEventSink, SessionService } from "./session.base.js";
3
5
  export type { ApiKeySecretGrant, DispatchCycleRun, DispatchExecution, DispatchLease, DispatchSession, DispatchRepo, DispatchServerLocalConfig, DispatchWorkItem, RunOnceDispatchPacket, RunOnceResultPacket, RunnerDispatchArtifact, RunnerDispatchEvent, RunnerDispatchSpec, RunnerEventLine } from "./session.types.js";
4
6
  export { DeterministicProviderCliService, ProcessBackedProviderCliService, RoutingProviderCliService, buildProviderCliCommand } from "./provider-cli/provider-cli.service.js";
@@ -1,2 +1,3 @@
1
1
  export { parseRunOnceDispatchPacket, failureResult } from "./session.types.js";
2
+ export { buildCompletionToolServerArgs, codexMcpConfigArgs, completionPhaseFromDispatch, expectedCompletionToolName, prepareCompletionToolRuntime, readCompletionArtifact, writeCompletionArtifact } from "./phase-completion.js";
2
3
  export { DeterministicProviderCliService, ProcessBackedProviderCliService, RoutingProviderCliService, buildProviderCliCommand } from "./provider-cli/provider-cli.service.js";
@@ -0,0 +1,54 @@
1
+ import type { RunOnceDispatchPacket, RunnerDispatchArtifact } from "./session.types.js";
2
+ import type { WorktreeHandle } from "../worktree/worktree.types.js";
3
+ export type CompletionPhase = "implementation" | "self_review" | "validation";
4
+ export interface CompletionToolRuntime {
5
+ readonly serverName: string;
6
+ readonly command: string;
7
+ readonly args: readonly string[];
8
+ readonly env: Readonly<Record<string, string>>;
9
+ readonly cursorMcpConfigPath?: string | null;
10
+ cleanup(): Promise<void>;
11
+ }
12
+ export interface CompletionToolRuntimeOptions {
13
+ readonly dispatch: RunOnceDispatchPacket;
14
+ readonly worktree: WorktreeHandle;
15
+ readonly phase?: CompletionPhase;
16
+ }
17
+ export interface CompletionToolServerConfig {
18
+ readonly worktreePath: string;
19
+ readonly workItemId: string;
20
+ readonly phase: CompletionPhase;
21
+ readonly producedBy?: string;
22
+ }
23
+ export interface CompletionArtifactReference {
24
+ readonly phase: CompletionPhase;
25
+ readonly workItemId: string;
26
+ readonly repoPath: string;
27
+ readonly path: string;
28
+ readonly reportPath: string;
29
+ readonly contentHash: string;
30
+ readonly status: string;
31
+ readonly producedBy: string;
32
+ }
33
+ export declare function completionPhaseFromDispatch(dispatch: RunOnceDispatchPacket): CompletionPhase;
34
+ export declare function normalizeCompletionPhase(value: string | null | undefined): CompletionPhase;
35
+ export declare function completionToolNamesForPhase(phase: CompletionPhase): readonly string[];
36
+ export declare function expectedCompletionToolName(phase: CompletionPhase): string;
37
+ export declare function artifactRootFor(worktreePath: string, workItemId: string): string;
38
+ export declare function completionArtifactJsonPath(worktreePath: string, workItemId: string, phase: CompletionPhase): string;
39
+ export declare function completionArtifactReportPath(worktreePath: string, workItemId: string, phase: CompletionPhase): string;
40
+ export declare function prepareCompletionToolRuntime(options: CompletionToolRuntimeOptions): Promise<CompletionToolRuntime>;
41
+ export declare function buildCompletionToolServerArgs(config: CompletionToolServerConfig): readonly string[];
42
+ export declare function codexMcpConfigArgs(runtime: CompletionToolRuntime): readonly string[];
43
+ export declare function cursorMcpServerConfig(runtime: CompletionToolRuntime): unknown;
44
+ export declare function completionPromptForPhase(phase: CompletionPhase): string;
45
+ export declare function writeCompletionArtifact(config: CompletionToolServerConfig, toolName: string, input: unknown): Promise<CompletionArtifactReference>;
46
+ export declare function readCompletionArtifact(worktreePath: string, workItemId: string, phase: CompletionPhase): Promise<RunnerDispatchArtifact | null>;
47
+ export declare function runCompletionMcpServer(config: CompletionToolServerConfig): Promise<void>;
48
+ export declare function parseCompletionMcpArgs(argv: readonly string[]): {
49
+ readonly ok: true;
50
+ readonly config: CompletionToolServerConfig;
51
+ } | {
52
+ readonly ok: false;
53
+ readonly error: string;
54
+ };