@bridge_gpt/mcp-server 0.2.55 → 0.2.57
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 +26 -10
- package/build/agent-capabilities/types.js +4 -0
- package/build/agent-registry.js +20 -3
- package/build/codex-bridge-profile.js +151 -0
- package/build/codex-home.js +7 -0
- package/build/codex-launch-scope.js +54 -0
- package/build/codex-skill-adapter.js +8 -5
- package/build/command-host.js +9 -0
- package/build/command-provisioning.js +35 -4
- package/build/commands.generated.js +5 -5
- package/build/doctor.js +9 -1
- package/build/epic-implementer-bin.js +3 -3
- package/build/index.js +121 -116
- package/build/init.js +2 -1
- package/build/install-bridge.js +69 -10
- package/build/mcp-host-config.js +4 -0
- package/build/mcp-host-targets.js +21 -11
- package/build/mcp-provisioning.js +1 -1
- package/build/mcp-registration-doctor.js +1 -1
- package/build/readme.generated.js +1 -1
- package/build/review-tickets.js +50 -35
- package/build/start-tickets.js +335 -58
- package/build/version.generated.js +3 -3
- package/package.json +1 -1
package/build/init.js
CHANGED
|
@@ -13,6 +13,7 @@ import { writeFile, mkdir, readFile, stat } from "fs/promises";
|
|
|
13
13
|
import path from "path";
|
|
14
14
|
import os from "os";
|
|
15
15
|
import { COMMANDS } from "./commands.generated.js";
|
|
16
|
+
import { renderCommandForHost } from "./command-host.js";
|
|
16
17
|
import { CODEX_SKILLS_DIR, codexSkillAssets } from "./codex-skill-adapter.js";
|
|
17
18
|
import { AGENTS } from "./agents.generated.js";
|
|
18
19
|
import { DOCS } from "./docs.generated.js";
|
|
@@ -770,7 +771,7 @@ export async function runInit(cwd, options = {}) {
|
|
|
770
771
|
await mkdir(dir, { recursive: true });
|
|
771
772
|
// Per-file read/compare/write runs concurrently; outcomes are applied to the
|
|
772
773
|
// Sets afterward in entry order so the summary counts are unchanged.
|
|
773
|
-
const outcomes = await Promise.all(commandEntries.map(([filename, content]) => scaffoldFile(path.join(dir, filename), content)));
|
|
774
|
+
const outcomes = await Promise.all(commandEntries.map(([filename, content]) => scaffoldFile(path.join(dir, filename), renderCommandForHost(filename, content, dir === path.join(cwd, ".cursor", "commands") ? "cursor" : "claude-code"))));
|
|
774
775
|
commandEntries.forEach(([filename], i) => {
|
|
775
776
|
const outcome = outcomes[i];
|
|
776
777
|
if (outcome === "skipped") {
|
package/build/install-bridge.js
CHANGED
|
@@ -152,6 +152,7 @@ import { provisionHostTarget, createDefaultVendorProcessDeps, inspectBridgeApiPr
|
|
|
152
152
|
import { adaptBridgeEntryForHostTarget, } from "./mcp-host-entry-adapter.js";
|
|
153
153
|
import { MCP_SERVER_NAME, MCP_PACKAGE_NAME, resolveRegistrationKey, } from "./mcp-identity.js";
|
|
154
154
|
import { DUPLICATE_REGISTRATION_GUIDANCE } from "./launcher-config-inspection.js";
|
|
155
|
+
import { codexHome, configureBridgeCodexProfile, inspectBridgeCodexProfile } from "./codex-bridge-profile.js";
|
|
155
156
|
import { recordInstalledConductorCapability, recordInstalledExecutorServiceUnit, recordInstalledProjectArtifact, writeMcpInstallState, } from "./mcp-install-state.js";
|
|
156
157
|
// BAPI-1207: opt-in cross-platform agent notes (AGENTS.md / CLAUDE.md).
|
|
157
158
|
import { AGENT_GUIDANCE } from "./agent-guidance.generated.js";
|
|
@@ -517,6 +518,9 @@ export function getInstallBridgeUsage(baseUrl = DEFAULT_BAPI_BASE_URL) {
|
|
|
517
518
|
" manual continuation instead). --tools= (empty) is",
|
|
518
519
|
" an explicit empty selection: it writes nothing and",
|
|
519
520
|
" launches nothing.",
|
|
521
|
+
" --codex-profile on|off Opt in to Bridge workflow MCP approvals for",
|
|
522
|
+
" Codex workers, or explicitly decline. With a",
|
|
523
|
+
" Codex TTY selection, the installer asks.",
|
|
520
524
|
" --force Overwrite an existing real BAPI_API_KEY in a",
|
|
521
525
|
" host config (or in the credential store) without",
|
|
522
526
|
" prompting. It does NOT bypass the git-tracked",
|
|
@@ -530,7 +534,7 @@ export function getInstallBridgeUsage(baseUrl = DEFAULT_BAPI_BASE_URL) {
|
|
|
530
534
|
" prompting, or spawning anything. With --invite it",
|
|
531
535
|
" also never calls the exchange endpoint and never",
|
|
532
536
|
" generates or stores a secret.",
|
|
533
|
-
" --agent claude|cursor-agent
|
|
537
|
+
" --agent claude|cursor-agent|codex Explicit agent choice for post-install",
|
|
534
538
|
" session — it always wins, and there is NO Claude",
|
|
535
539
|
" default. Without it the launch tool is derived",
|
|
536
540
|
" from your selection: Claude Code opens `claude`.",
|
|
@@ -539,9 +543,11 @@ export function getInstallBridgeUsage(baseUrl = DEFAULT_BAPI_BASE_URL) {
|
|
|
539
543
|
" session); selecting Cursor writes .cursor/mcp.json",
|
|
540
544
|
" and prints how to finish by running /install-bridge",
|
|
541
545
|
" in a new Cursor session. A selection whose tools have",
|
|
542
|
-
" no
|
|
546
|
+
" no supported auto-launch path (e.g. Copilot) opens nothing",
|
|
543
547
|
" and prints how to finish configuring later. Passing",
|
|
544
|
-
" --agent cursor-agent still force-spawns it.",
|
|
548
|
+
" --agent cursor-agent still force-spawns it. Codex",
|
|
549
|
+
" is accepted only for manual continuation: neither",
|
|
550
|
+
" this bootstrap nor start-tickets launches it yet.",
|
|
545
551
|
" -h, --help Show this help.",
|
|
546
552
|
"",
|
|
547
553
|
"Subcommands:",
|
|
@@ -612,6 +618,7 @@ export function parseInstallBridgeArgs(argv) {
|
|
|
612
618
|
let invite;
|
|
613
619
|
let email;
|
|
614
620
|
let tools;
|
|
621
|
+
let codexProfile;
|
|
615
622
|
// Track SUPPLIED-ness separately from the values: `--invite` is legitimately
|
|
616
623
|
// valueless (prompt path) and `--api-key ""` is still a contradiction with it.
|
|
617
624
|
let inviteSupplied = false;
|
|
@@ -697,6 +704,16 @@ export function parseInstallBridgeArgs(argv) {
|
|
|
697
704
|
i = r.nextIndex;
|
|
698
705
|
continue;
|
|
699
706
|
}
|
|
707
|
+
if (arg === "--codex-profile" || arg.startsWith("--codex-profile=")) {
|
|
708
|
+
const r = readValue(arg, "--codex-profile", i);
|
|
709
|
+
if ("error" in r)
|
|
710
|
+
return { status: "error", message: r.error };
|
|
711
|
+
if (r.value !== "on" && r.value !== "off")
|
|
712
|
+
return { status: "error", message: "--codex-profile must be on or off." };
|
|
713
|
+
codexProfile = r.value;
|
|
714
|
+
i = r.nextIndex;
|
|
715
|
+
continue;
|
|
716
|
+
}
|
|
700
717
|
if (arg === "--agent" || arg.startsWith("--agent=")) {
|
|
701
718
|
const r = readValue(arg, "--agent", i);
|
|
702
719
|
if ("error" in r)
|
|
@@ -747,7 +764,7 @@ export function parseInstallBridgeArgs(argv) {
|
|
|
747
764
|
}
|
|
748
765
|
return {
|
|
749
766
|
status: "ok",
|
|
750
|
-
options: { apiKey, repo, force, dryRun, agentName, invite, inviteMode: inviteSupplied, email, tools },
|
|
767
|
+
options: { apiKey, repo, force, dryRun, agentName, invite, inviteMode: inviteSupplied, email, tools, codexProfile },
|
|
751
768
|
};
|
|
752
769
|
}
|
|
753
770
|
/**
|
|
@@ -2057,7 +2074,7 @@ async function resolveDryRunHostPlatforms(deps, options) {
|
|
|
2057
2074
|
* Launch agents install-bridge will NEVER auto-spawn from a host SELECTION, even
|
|
2058
2075
|
* though their CLI exists and the host's MCP config is still written normally.
|
|
2059
2076
|
*
|
|
2060
|
-
* `cursor-agent`
|
|
2077
|
+
* `cursor-agent` and `codex` are excluded. Cursor's FIRST-RUN workspace-trust handshake collapses
|
|
2061
2078
|
* under our osascript-spawned launch — the "Workspace Trust Required" dialog
|
|
2062
2079
|
* renders, then the process exits before a selection registers, so configuration
|
|
2063
2080
|
* never runs (reproduced on a pristine, never-trusted workspace; the identical
|
|
@@ -2065,16 +2082,20 @@ async function resolveDryRunHostPlatforms(deps, options) {
|
|
|
2065
2082
|
* cursor-agent's own behavior on an untrusted workspace and is not something our
|
|
2066
2083
|
* launch can drive, so we treat Cursor as a no-auto-launch host: selecting it
|
|
2067
2084
|
* still writes `.cursor/mcp.json`, then prints the manual `/install-bridge`
|
|
2068
|
-
* continuation
|
|
2085
|
+
* continuation. Codex does have an agentic CLI, but this workflow is a Claude
|
|
2086
|
+
* `/install-bridge` command and its native skill is not available until after
|
|
2087
|
+
* the bootstrap it would be asked to run completes.
|
|
2069
2088
|
* An explicit `--agent cursor-agent` override still spawns it — a deliberate,
|
|
2070
2089
|
* documented power-user opt-in that bypasses this selection guard.
|
|
2071
2090
|
*/
|
|
2072
|
-
const SELECTION_NON_LAUNCHABLE_AGENTS = new Set(["cursor-agent"]);
|
|
2091
|
+
const SELECTION_NON_LAUNCHABLE_AGENTS = new Set(["cursor-agent", "codex"]);
|
|
2092
|
+
/** Agents whose interactive command surface cannot run the post-install recipe yet. */
|
|
2093
|
+
const INSTALL_BRIDGE_UNSUPPORTED_AGENTS = new Set(["codex"]);
|
|
2073
2094
|
/**
|
|
2074
2095
|
* Resolve the post-install launch decision from the selected host platforms and an
|
|
2075
2096
|
* OPTIONAL explicit `--agent` override (BAPI-657). Pure and total:
|
|
2076
2097
|
*
|
|
2077
|
-
* - An explicit `--agent` is an ABSOLUTE override
|
|
2098
|
+
* - An explicit supported `--agent` is an ABSOLUTE override: a valid explicit
|
|
2078
2099
|
* agent always returns `spawn(agent)`, regardless of which tools were selected —
|
|
2079
2100
|
* the flag is honored even for a host outside the selection, and it bypasses the
|
|
2080
2101
|
* {@link SELECTION_NON_LAUNCHABLE_AGENTS} guard below.
|
|
@@ -2089,6 +2110,9 @@ const SELECTION_NON_LAUNCHABLE_AGENTS = new Set(["cursor-agent"]);
|
|
|
2089
2110
|
*/
|
|
2090
2111
|
export function resolveInstallBridgeLaunchDecision(selectedPlatforms, explicitAgent) {
|
|
2091
2112
|
if (explicitAgent) {
|
|
2113
|
+
if (INSTALL_BRIDGE_UNSUPPORTED_AGENTS.has(explicitAgent)) {
|
|
2114
|
+
return { kind: "manual", reason: "unsupported-agent-workflow" };
|
|
2115
|
+
}
|
|
2092
2116
|
return { kind: "spawn", agent: explicitAgent };
|
|
2093
2117
|
}
|
|
2094
2118
|
if (selectedPlatforms.length === 0) {
|
|
@@ -3871,7 +3895,9 @@ function describePlannedLaunchAgent(launch) {
|
|
|
3871
3895
|
}
|
|
3872
3896
|
return launch.reason === "empty-selection"
|
|
3873
3897
|
? "none — no tools selected"
|
|
3874
|
-
:
|
|
3898
|
+
: launch.reason === "unsupported-agent-workflow"
|
|
3899
|
+
? "none — selected agent cannot run the install-bridge workflow; manual continuation is printed"
|
|
3900
|
+
: "none — no launchable tool selected; manual continuation is printed";
|
|
3875
3901
|
}
|
|
3876
3902
|
/**
|
|
3877
3903
|
* The Step 5 preview lines, shared by both previews so the launch description
|
|
@@ -3923,7 +3949,9 @@ function buildLaunchStepPreview(launch) {
|
|
|
3923
3949
|
...githubLines,
|
|
3924
3950
|
launch.reason === "empty-selection"
|
|
3925
3951
|
? "Step 5 — no agent session: no tools were selected, so nothing is configured or opened; re-run and select at least one tool."
|
|
3926
|
-
:
|
|
3952
|
+
: launch.reason === "unsupported-agent-workflow"
|
|
3953
|
+
? "Step 5 — no automatic launch: the selected agent cannot run the install-bridge workflow. The deterministic setup completes and manual continuation is printed."
|
|
3954
|
+
: "Step 5 — no automatic launch: no selected tool can auto-launch this workflow. The deterministic setup completes and copy-pasteable /install-bridge continuation is printed (your Bridge MCP tools stay limited until configured).",
|
|
3927
3955
|
];
|
|
3928
3956
|
}
|
|
3929
3957
|
/**
|
|
@@ -4919,6 +4947,15 @@ export async function runInstallBridgeCli(argv, overrides = {}) {
|
|
|
4919
4947
|
// global (Codex) or manual (Windsurf) target is provisioned by the
|
|
4920
4948
|
// registry-driven emitter after the connectivity check.
|
|
4921
4949
|
const selectedPlatforms = await resolveSelectedHostPlatforms(deps, options);
|
|
4950
|
+
if (options.codexProfile && !selectedPlatforms.includes("codex")) {
|
|
4951
|
+
errorLog("Error: --codex-profile requires Codex in --tools or the interactive selection.");
|
|
4952
|
+
return 1;
|
|
4953
|
+
}
|
|
4954
|
+
let codexProfileChoice = options.codexProfile;
|
|
4955
|
+
if (selectedPlatforms.includes("codex") && !options.dryRun && !codexProfileChoice && deps.isTTY && deps.promptLine) {
|
|
4956
|
+
const answer = (await deps.promptLine("Install the opt-in Bridge Codex approval profile for spawned workers? (y/N) ")).trim().toLowerCase();
|
|
4957
|
+
codexProfileChoice = answer === "y" || answer === "yes" ? "on" : "off";
|
|
4958
|
+
}
|
|
4922
4959
|
const targets = hostConfigTargetsForPlatforms(selectedPlatforms);
|
|
4923
4960
|
// Read-only detection (safe in dry-run) of global-config editors we can't write.
|
|
4924
4961
|
const manualEditors = await detectManualEditors(deps);
|
|
@@ -5699,6 +5736,28 @@ export async function runInstallBridgeCli(argv, overrides = {}) {
|
|
|
5699
5736
|
errorLog(" That host was left untouched. Re-run install-bridge once one entry is removed.");
|
|
5700
5737
|
return 1;
|
|
5701
5738
|
}
|
|
5739
|
+
if (selectedPlatforms.includes("codex")) {
|
|
5740
|
+
const home = codexHome(deps.env, deps.homedir());
|
|
5741
|
+
try {
|
|
5742
|
+
const profileDeps = {
|
|
5743
|
+
readFile: deps.readFile,
|
|
5744
|
+
writeFile: (p, data) => deps.writeFile(p, data, { encoding: "utf-8", mode: 0o600 }),
|
|
5745
|
+
mkdir: deps.mkdir,
|
|
5746
|
+
};
|
|
5747
|
+
const result = codexProfileChoice
|
|
5748
|
+
? await configureBridgeCodexProfile(home, codexProfileChoice === "on" ? "enable" : "decline", profileDeps)
|
|
5749
|
+
: await inspectBridgeCodexProfile(home, deps.readFile);
|
|
5750
|
+
if (result.status === "active")
|
|
5751
|
+
log(" Codex Bridge approval profile installed; spawned workers use --profile bridge.");
|
|
5752
|
+
else if (result.status === "declined" || result.status === "missing")
|
|
5753
|
+
log(" Codex Bridge approval profile inactive; spawned workers use existing Codex approvals. Opt in with --codex-profile=on.");
|
|
5754
|
+
else
|
|
5755
|
+
log(` Codex Bridge approval profile ${result.status}; spawned workers will not use it. Inspect ${home}/bridge.config.toml and rerun with --codex-profile=on.`);
|
|
5756
|
+
}
|
|
5757
|
+
catch {
|
|
5758
|
+
log(" Codex Bridge approval profile could not be configured; spawned workers will not use it. Inspect CODEX_HOME and rerun with --codex-profile=on.");
|
|
5759
|
+
}
|
|
5760
|
+
}
|
|
5702
5761
|
// Legacy manual-editor instructions cover editors that are DETECTED but were
|
|
5703
5762
|
// NOT part of the selection (so the emitter above did not handle them). The two
|
|
5704
5763
|
// editors are suppressed INDEPENDENTLY: Codex is dropped when it was selected
|
package/build/mcp-host-config.js
CHANGED
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
* rather than reserialize unrelated content.
|
|
29
29
|
*/
|
|
30
30
|
import { VERSION } from "./version.generated.js";
|
|
31
|
+
import { codexHome } from "./codex-home.js";
|
|
31
32
|
import { refreshBridgeApiPackageSpec } from "./init.js";
|
|
32
33
|
import { hostAdapterForTarget, } from "./mcp-host-targets.js";
|
|
33
34
|
import { adaptBridgeEntryForHostTarget, } from "./mcp-host-entry-adapter.js";
|
|
@@ -56,6 +57,9 @@ function dirnameOf(p) {
|
|
|
56
57
|
}
|
|
57
58
|
/** Resolve a target's absolute path from injected cwd/homedir. */
|
|
58
59
|
export function resolveTargetAbsPath(target, ctx) {
|
|
60
|
+
if (target.id === "codex" && ctx.env?.CODEX_HOME) {
|
|
61
|
+
return `${codexHome(ctx.env, ctx.homedir)}/config.toml`;
|
|
62
|
+
}
|
|
59
63
|
if (target.scope === "project") {
|
|
60
64
|
if (!target.relPath)
|
|
61
65
|
throw new Error(`${target.id} missing relPath`);
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
* platform is a matter of adding one entry to {@link MCP_HOST_TARGETS} plus its
|
|
16
16
|
* `PlatformId` union member.
|
|
17
17
|
*/
|
|
18
|
+
import { codexHome } from "./codex-home.js";
|
|
18
19
|
// ---------------------------------------------------------------------------
|
|
19
20
|
// Path helpers (pure)
|
|
20
21
|
// ---------------------------------------------------------------------------
|
|
@@ -73,7 +74,7 @@ export const MCP_HOST_TARGETS = {
|
|
|
73
74
|
hostKind: "claude-code-json",
|
|
74
75
|
vendorCli: { bin: "claude", kind: "claude-add-json" },
|
|
75
76
|
launchAgent: "claude",
|
|
76
|
-
|
|
77
|
+
capabilities: { mcpConfiguration: true, customCommands: true, worktreeProvisioning: true, sessionSpawning: true },
|
|
77
78
|
writeStrategy: "vendor-first",
|
|
78
79
|
// Claude Code is always a candidate default.
|
|
79
80
|
detect: () => true,
|
|
@@ -86,7 +87,7 @@ export const MCP_HOST_TARGETS = {
|
|
|
86
87
|
displayPath: ".cursor/mcp.json",
|
|
87
88
|
hostKind: "cursor-json",
|
|
88
89
|
launchAgent: "cursor-agent",
|
|
89
|
-
|
|
90
|
+
capabilities: { mcpConfiguration: true, customCommands: true, worktreeProvisioning: true, sessionSpawning: true },
|
|
90
91
|
writeStrategy: "direct",
|
|
91
92
|
detect: (ctx) => ctx.exists(joinPath(ctx.cwd, ".cursor")) ||
|
|
92
93
|
typeof ctx.env.CURSOR_TRACE_DIR === "string" &&
|
|
@@ -99,7 +100,7 @@ export const MCP_HOST_TARGETS = {
|
|
|
99
100
|
relPath: ".vscode/mcp.json",
|
|
100
101
|
displayPath: ".vscode/mcp.json",
|
|
101
102
|
hostKind: "vscode-json",
|
|
102
|
-
|
|
103
|
+
capabilities: { mcpConfiguration: true, customCommands: true, worktreeProvisioning: false, sessionSpawning: false },
|
|
103
104
|
writeStrategy: "direct",
|
|
104
105
|
detect: (ctx) => ctx.exists(joinPath(ctx.cwd, ".vscode")),
|
|
105
106
|
},
|
|
@@ -111,7 +112,10 @@ export const MCP_HOST_TARGETS = {
|
|
|
111
112
|
displayPath: "~/.codex/config.toml",
|
|
112
113
|
hostKind: "codex-toml",
|
|
113
114
|
vendorCli: { bin: "codex", kind: "codex-add" },
|
|
114
|
-
|
|
115
|
+
launchAgent: "codex",
|
|
116
|
+
// The launcher injects a per-process, worktree-bound MCP table. The global
|
|
117
|
+
// registration remains the ordinary interactive default.
|
|
118
|
+
capabilities: { mcpConfiguration: true, customCommands: true, worktreeProvisioning: true, sessionSpawning: true },
|
|
115
119
|
writeStrategy: "vendor-first",
|
|
116
120
|
detect: (ctx) => ctx.exists(joinPath(ctx.homedir, ".codex")),
|
|
117
121
|
},
|
|
@@ -122,7 +126,7 @@ export const MCP_HOST_TARGETS = {
|
|
|
122
126
|
absPathResolver: (homedir) => joinPath(homedir, ".codeium/windsurf/mcp_config.json"),
|
|
123
127
|
displayPath: "~/.codeium/windsurf/mcp_config.json",
|
|
124
128
|
hostKind: "claude-code-json", // Windsurf uses the Claude-compatible JSON shape.
|
|
125
|
-
|
|
129
|
+
capabilities: { mcpConfiguration: true, customCommands: false, worktreeProvisioning: false, sessionSpawning: false },
|
|
126
130
|
// Preserve current behavior: never auto-modify the global Windsurf file.
|
|
127
131
|
writeStrategy: "manual-instructions",
|
|
128
132
|
detect: (ctx) => ctx.exists(joinPath(ctx.cwd, ".windsurf")) ||
|
|
@@ -153,18 +157,22 @@ export function getHostTarget(id) {
|
|
|
153
157
|
return isHostPlatformId(id) ? MCP_HOST_TARGETS[id] : undefined;
|
|
154
158
|
}
|
|
155
159
|
/**
|
|
156
|
-
* The centrally-registered
|
|
157
|
-
* when the platform has no
|
|
160
|
+
* The centrally-registered agent identity for a host platform, or `undefined`
|
|
161
|
+
* when the platform has no registered agent (Copilot / Windsurf).
|
|
158
162
|
* Pure projection of the registry's {@link HostTargetDefinition.launchAgent}
|
|
159
|
-
* metadata
|
|
160
|
-
* post-install configuration session (BAPI-657).
|
|
163
|
+
* metadata. Callers must check workflow-specific capabilities before launching.
|
|
161
164
|
*/
|
|
162
165
|
export function agentForPlatform(id) {
|
|
163
166
|
return MCP_HOST_TARGETS[id].launchAgent;
|
|
164
167
|
}
|
|
165
|
-
/**
|
|
168
|
+
/** Hosts whose declared workflow capability permits worktree provisioning. */
|
|
166
169
|
export function getWorktreeHostTargets() {
|
|
167
|
-
return allHostTargets().filter((t) => t.
|
|
170
|
+
return allHostTargets().filter((t) => t.capabilities.worktreeProvisioning);
|
|
171
|
+
}
|
|
172
|
+
/** True only when a host has every capability needed for a spawned workflow. */
|
|
173
|
+
export function isRunnableHostTarget(target) {
|
|
174
|
+
const c = target.capabilities;
|
|
175
|
+
return c.mcpConfiguration && c.customCommands && c.worktreeProvisioning && c.sessionSpawning && target.launchAgent !== undefined;
|
|
168
176
|
}
|
|
169
177
|
/** Project-scoped JSON targets (used by init, launcher-token merge, doctor). */
|
|
170
178
|
export function getProjectJsonTargets() {
|
|
@@ -183,6 +191,8 @@ export function getManualHostTargets() {
|
|
|
183
191
|
* Project targets resolve below `ctx.cwd`; global targets below `ctx.homedir`.
|
|
184
192
|
*/
|
|
185
193
|
export function resolveHostTargetPath(target, ctx) {
|
|
194
|
+
if (target.id === "codex" && ctx.env?.CODEX_HOME)
|
|
195
|
+
return `${codexHome(ctx.env, ctx.homedir)}/config.toml`;
|
|
186
196
|
if (target.scope === "project") {
|
|
187
197
|
if (!target.relPath) {
|
|
188
198
|
throw new Error(`project target ${target.id} is missing relPath`);
|
|
@@ -138,7 +138,7 @@ export function buildMcpServerEntriesForManifest(manifest, absoluteWorktreePath,
|
|
|
138
138
|
/** Both registration files written for every provisioned worktree. */
|
|
139
139
|
export function getWorktreeMcpRegistrationTargets(worktreePath, platform) {
|
|
140
140
|
const api = pathApiForProvisioningPlatform(platform);
|
|
141
|
-
return getWorktreeHostTargets().map((target) => ({
|
|
141
|
+
return getWorktreeHostTargets().filter((target) => target.scope === "project").map((target) => ({
|
|
142
142
|
filePath: api.join(worktreePath, target.relPath),
|
|
143
143
|
topLevelKey: hostAdapterForTarget(target).topLevelKey,
|
|
144
144
|
}));
|
|
@@ -104,7 +104,7 @@ export function isBridgeApiShimEntry(entry, worktreeRoot) {
|
|
|
104
104
|
* to validate.
|
|
105
105
|
*/
|
|
106
106
|
export async function probeWorktreeMcpRegistration(worktreeRoot, deps) {
|
|
107
|
-
const targets = getWorktreeHostTargets().map((target) => ({
|
|
107
|
+
const targets = getWorktreeHostTargets().filter((target) => target.scope === "project").map((target) => ({
|
|
108
108
|
filePath: path.join(worktreeRoot, target.relPath),
|
|
109
109
|
topLevelKey: hostAdapterForTarget(target).topLevelKey,
|
|
110
110
|
}));
|