@minhspark/codex-mcp-bridge 1.26.4 → 1.26.6
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/.codex-plugin/plugin.json +1 -1
- package/CHANGELOG.md +29 -0
- package/README.md +51 -735
- package/docs/new-macos-setup.md +16 -12
- package/docs/new-windows-setup.md +22 -9
- package/docs/project-onboarding.md +11 -7
- package/package.json +1 -1
- package/plugin.json +1 -1
- package/scripts/install-native-relay.mjs +1 -1
- package/scripts/update.mjs +44 -23
- package/src/background-relay-service.mjs +12 -6
- package/src/claude-bridge.mjs +1 -1
- package/src/codex-bridge-launcher.mjs +35 -7
- package/src/index.mjs +1 -1
- package/src/native-relay-companion.mjs +1 -1
- package/src/setup.mjs +1 -1
package/docs/new-macos-setup.md
CHANGED
|
@@ -15,25 +15,30 @@ separately authenticated provider CLIs and do not require open Desktop apps.
|
|
|
15
15
|
Use the same command for a fresh installation and every update:
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
|
-
|
|
18
|
+
npx -y @minhspark/codex-mcp-bridge@latest
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
version globally
|
|
24
|
-
and verifies the global version and configuration. No second installation or
|
|
21
|
+
Run this directly in an interactive terminal. The bare npm package launch
|
|
22
|
+
selects the complete updater. The updater installs its exact resolved
|
|
23
|
+
version globally with lifecycle scripts disabled, runs managed setup directly
|
|
24
|
+
using Node and verifies the global version and configuration. No second installation or
|
|
25
25
|
setup command is required. Existing disabled choices, authentication and custom
|
|
26
26
|
project grants are preserved; the updater does not open apps or chats or kill
|
|
27
27
|
processes. A pending service migration is reported instead of interrupting work.
|
|
28
28
|
|
|
29
|
+
For scripts or redirected input/output, use
|
|
30
|
+
`npx -y --ignore-scripts -p @minhspark/codex-mcp-bridge@latest codex-bridge-update`.
|
|
31
|
+
MCP clients keep using the normal stdio launch; piped launches do not select
|
|
32
|
+
the terminal updater.
|
|
33
|
+
|
|
29
34
|
Setup registers the local bridges, adds native pipe forwarding, and bootstraps
|
|
30
35
|
the relay executor. It reuses an available Codex CLI or installs a pinned
|
|
31
36
|
official package under `~/.config/GptClaudeBridge/tools` (or
|
|
32
37
|
`XDG_CONFIG_HOME/GptClaudeBridge/tools`). No separate Codex CLI install command
|
|
33
38
|
is required. Run the install under the account that uses the apps, without `sudo`.
|
|
34
39
|
If setup or update exits nonzero, inspect the reported component and installed
|
|
35
|
-
version, correct the cause, and rerun the same updater command.
|
|
36
|
-
package
|
|
40
|
+
version, correct the cause, and rerun the same updater command. A completed
|
|
41
|
+
package installation is preserved when managed setup fails.
|
|
37
42
|
|
|
38
43
|
The command also installs an independent per-user LaunchAgent for separate
|
|
39
44
|
Claude, Codex and Antigravity CLI workers and updates its managed settings on
|
|
@@ -101,14 +106,13 @@ a nonzero exit status while configuration is incomplete.
|
|
|
101
106
|
|
|
102
107
|
Local `npm install` and `npm ci` do not change app settings. For a deliberate
|
|
103
108
|
package-only installation, a direct global npm install can use
|
|
104
|
-
`CODEX_BRIDGE_SKIP_SETUP=1` or `--ignore-scripts`;
|
|
105
|
-
|
|
109
|
+
`CODEX_BRIDGE_SKIP_SETUP=1` or `--ignore-scripts`; the complete updater runs
|
|
110
|
+
managed setup directly after package installation. For Homebrew, run
|
|
106
111
|
`codex-bridge-setup` after installing the formula. A pinned source checkout can
|
|
107
112
|
use `node scripts/setup.mjs`.
|
|
108
113
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
available for selective configuration. `codex-bridge-code-install --install`
|
|
114
|
+
See [project onboarding](project-onboarding.md) for shared authorization and
|
|
115
|
+
selective configuration. `codex-bridge-code-install --install`
|
|
112
116
|
can create a missing user-level Code entry; its existing policy migration mode
|
|
113
117
|
is described in [project onboarding](project-onboarding.md). Use intended
|
|
114
118
|
project paths when setting explicit `CODEX_BRIDGE_ALLOWED_ROOTS`; macOS
|
|
@@ -7,15 +7,28 @@ does not require the Desktop apps to be open. Use this one PowerShell command
|
|
|
7
7
|
for a fresh installation or an update, including from 1.26.0 or 1.26.1:
|
|
8
8
|
|
|
9
9
|
```powershell
|
|
10
|
-
|
|
10
|
+
npx.cmd -y @minhspark/codex-mcp-bridge@latest
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
Run this directly in an interactive terminal. The bare npm package launch
|
|
14
|
+
selects the complete updater and defaults to `%APPDATA%\npm` on Windows instead
|
|
15
|
+
of a protected Node installation directory such as `Program Files`;
|
|
16
|
+
administrator rights are not required. The updater installs its exact resolved
|
|
17
|
+
version globally with lifecycle scripts disabled, then runs managed setup
|
|
18
|
+
directly using Node. It displays progress and verifies the global version,
|
|
19
|
+
saved settings and relay activation.
|
|
17
20
|
No second installation or setup command is required.
|
|
18
21
|
|
|
22
|
+
For scripts or redirected input/output, select the updater explicitly:
|
|
23
|
+
|
|
24
|
+
```powershell
|
|
25
|
+
npx.cmd -y --ignore-scripts -p @minhspark/codex-mcp-bridge@latest codex-bridge-update --user
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
MCP clients keep using the package's normal stdio launch. Piped launches do not
|
|
29
|
+
select the terminal updater. An installed package also accepts
|
|
30
|
+
`codex-mcp-bridge.cmd update` for an explicit update from that package version.
|
|
31
|
+
|
|
19
32
|
An older Windows background service can keep the global npm package directory
|
|
20
33
|
locked as its working directory. Before replacing the package, the updater
|
|
21
34
|
moves only this package's owned legacy service to newer code using private relay
|
|
@@ -33,8 +46,8 @@ official package in the current user's `.config\GptClaudeBridge\tools`
|
|
|
33
46
|
directory. It also configures native pipe forwarding and bootstraps the relay
|
|
34
47
|
executor. A failed component is reported as incomplete rather than ready. If
|
|
35
48
|
setup or update exits nonzero, inspect the reported component and installed
|
|
36
|
-
version, correct the cause, and rerun the same updater command.
|
|
37
|
-
package
|
|
49
|
+
version, correct the cause, and rerun the same updater command. A completed
|
|
50
|
+
package installation is preserved when managed setup fails.
|
|
38
51
|
|
|
39
52
|
The same command installs the independent worker relay as a hidden per-user
|
|
40
53
|
scheduled task and applies its managed settings on every update. It registers
|
|
@@ -104,8 +117,8 @@ attempting delivery.
|
|
|
104
117
|
Local `npm install` and `npm ci` do not configure apps. For a deliberate
|
|
105
118
|
package-only installation, a direct global npm install can use
|
|
106
119
|
`CODEX_BRIDGE_SKIP_SETUP=1` or `--ignore-scripts`. This differs from the
|
|
107
|
-
recommended updater command, which
|
|
108
|
-
|
|
120
|
+
recommended updater command, which disables lifecycle scripts and runs managed
|
|
121
|
+
setup directly after the final global installation. A direct install skips the
|
|
109
122
|
updater's migration of legacy Windows services that can lock the package.
|
|
110
123
|
The optional card extension, hosted ChatGPT pairing, and VS Code preview have
|
|
111
124
|
separate installation steps.
|
|
@@ -4,15 +4,19 @@ One command installs or updates the global package, registers the bridges and
|
|
|
4
4
|
configures the independent worker relay automatically:
|
|
5
5
|
|
|
6
6
|
```sh
|
|
7
|
-
|
|
7
|
+
npx -y @minhspark/codex-mcp-bridge@latest
|
|
8
8
|
```
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
Run it directly in an interactive terminal. In Windows PowerShell use
|
|
11
|
+
`npx.cmd -y @minhspark/codex-mcp-bridge@latest`; it selects the per-user npm
|
|
12
|
+
prefix without administrator rights. For scripts or redirected terminals, use
|
|
13
|
+
the explicit updater in the [Windows](new-windows-setup.md) or
|
|
14
|
+
[macOS](new-macos-setup.md) guide. Normal MCP client launches keep serving stdio.
|
|
15
|
+
The updater moves an owned legacy service to
|
|
12
16
|
newer code using private relay storage as its working directory when needed,
|
|
13
17
|
temporarily using the downloaded updater package. It waits for active work to
|
|
14
|
-
drain, then installs its exact resolved version globally with
|
|
15
|
-
|
|
18
|
+
drain, then installs its exact resolved version globally with lifecycle scripts
|
|
19
|
+
disabled and runs managed setup directly using Node. It verifies the global installation and managed settings. No second
|
|
16
20
|
installation command is required. It does not open apps or chats or kill
|
|
17
21
|
processes. The setup creates
|
|
18
22
|
`codex-bridge` for Claude Code and the separate `codex-bridge-desktop` shared
|
|
@@ -37,10 +41,10 @@ setup after correcting an incomplete component. Add `.cmd` on Windows and
|
|
|
37
41
|
`--json` for structured output. Local package installs do not run setup.
|
|
38
42
|
For a deliberate package-only direct global installation,
|
|
39
43
|
`CODEX_BRIDGE_SKIP_SETUP=1` or npm `--ignore-scripts` opts out of setup; this is
|
|
40
|
-
separate from the
|
|
44
|
+
separate from the complete updater, which runs managed setup directly after installation.
|
|
41
45
|
Failed setup or update returns a nonzero exit. Inspect the reported component
|
|
42
46
|
and installed version, correct the cause, then rerun the same updater command.
|
|
43
|
-
|
|
47
|
+
A completed package installation is preserved when managed setup fails.
|
|
44
48
|
Explicit setup and `--check` also return a nonzero status until the saved
|
|
45
49
|
configuration passes verification.
|
|
46
50
|
|
package/package.json
CHANGED
package/plugin.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
|
|
3
3
|
"name": "codex-mcp-bridge",
|
|
4
|
-
"version": "1.26.
|
|
4
|
+
"version": "1.26.6",
|
|
5
5
|
"description": "Connect ChatGPT to your own Codex Desktop projects and conversations.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Bui Dang Minh",
|
|
@@ -25,7 +25,7 @@ import { removeRelayFile } from "../src/native-relay-files.mjs";
|
|
|
25
25
|
|
|
26
26
|
exitForVersionRequest(import.meta.url);
|
|
27
27
|
|
|
28
|
-
const VERSION = "1.26.
|
|
28
|
+
const VERSION = "1.26.6";
|
|
29
29
|
const root = stableInstallPath(path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."));
|
|
30
30
|
const entry = path.join(root, "src", "mcp-supervisor.mjs");
|
|
31
31
|
const entryArgs = ["native-relay-companion.mjs"];
|
package/scripts/update.mjs
CHANGED
|
@@ -87,11 +87,19 @@ function neutralDirectory(roots, env) {
|
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
function childFailure(result, phase) {
|
|
90
|
-
const match = /npm\s+(?:ERR!|error)\s+code\s+([A-Z][A-Z0-9_]{0,79})\b/.exec(String(result?.stderr ?? ""));
|
|
91
|
-
const
|
|
90
|
+
const match = /npm\s+(?:ERR!|error)\s+code\s+([A-Z][A-Z0-9_]{0,79}|\d{1,10})\b/.exec(String(result?.stderr ?? ""));
|
|
91
|
+
const signal = result?.error?.signal ?? result?.signal;
|
|
92
|
+
const value = match?.[1] ?? result?.error?.code ?? (signal ? null : result?.status ?? result?.exitCode);
|
|
93
|
+
const timedOut = value === "ETIMEDOUT" || result?.error?.killed === true && signal === "SIGTERM";
|
|
94
|
+
const code = timedOut ? "ETIMEDOUT" : /^\d{1,10}$/.test(String(value)) ? `EXIT_${value}`
|
|
95
|
+
: /^[A-Z][A-Z0-9_]{0,79}$/.test(value ?? "") ? value
|
|
96
|
+
: /^SIG[A-Z0-9]{1,20}$/.test(signal ?? "") ? `SIGNAL_${signal}` : null;
|
|
92
97
|
const cause = code ? Object.assign(new Error("The child command reported a failure."), { code }) : undefined;
|
|
93
|
-
|
|
94
|
-
|
|
98
|
+
const permissionDenied = phase === "installation" && ["EPERM", "EACCES"].includes(code);
|
|
99
|
+
return failure(permissionDenied ? "UPDATE_INSTALL_PERMISSION" : code === "EBUSY" ? "UPDATE_PACKAGE_BUSY" : timedOut ? "UPDATE_COMMAND_TIMEOUT" : phase === "verification" ? "UPDATE_SETUP_INCOMPLETE" : "UPDATE_NPM_FAILED",
|
|
100
|
+
permissionDenied ? "npm could not write to the installation directory. Run codex-bridge-update --user to install and configure the bridge in your user account without administrator rights. Existing work and receipts were preserved."
|
|
101
|
+
: timedOut ? `The update command exceeded its deadline. ${RETRY}`
|
|
102
|
+
: code === "EBUSY" ? `The installed package is still held open by another process. No process was stopped. ${RETRY}`
|
|
95
103
|
: `The ${phase === "verification" ? "installed setup verification" : "npm command"} did not complete. ${RETRY}`, phase, cause);
|
|
96
104
|
}
|
|
97
105
|
|
|
@@ -114,28 +122,35 @@ function serviceQuiescent(config) {
|
|
|
114
122
|
export async function runUpdate({ args = [], env = process.env, platform = process.platform, root = ROOT, run = execute,
|
|
115
123
|
installService = installBackgroundRelay, readConfig = readRelayConfiguration, readRuntime = readRelayServiceRuntime,
|
|
116
124
|
quiescent = serviceQuiescent, now = Date.now, sleep = pause, waitMs = 120000, onProgress = () => {} } = {}) {
|
|
117
|
-
if (args.some(arg => !["--help", "--json"].includes(arg))) throw failure("UPDATE_ARGUMENT_INVALID", "Usage: codex-bridge-update [--json] [--help]", "preflight");
|
|
118
|
-
if (args.includes("--help")) return { help: "Usage: codex-bridge-update [--json]\nSafely update the global bridge and all managed settings. Legacy Windows relays migrate when existing work finishes; pending migrations can be retried with the same command." };
|
|
125
|
+
if (args.some(arg => !["--help", "--json", "--user"].includes(arg))) throw failure("UPDATE_ARGUMENT_INVALID", "Usage: codex-bridge-update [--user] [--json] [--help]", "preflight");
|
|
126
|
+
if (args.includes("--help")) return { help: "Usage: codex-bridge-update [--user] [--json]\nSafely update the global bridge and all managed settings. --user selects the per-user npm prefix (Windows: AppData/Roaming/npm; macOS/Linux: ~/.local) without administrator rights. Legacy Windows relays migrate when existing work finishes; pending migrations can be retried with the same command." };
|
|
119
127
|
if (env.CODEX_BRIDGE_SKIP_SETUP === "1") throw failure("UPDATE_SETUP_DISABLED", "CODEX_BRIDGE_SKIP_SETUP=1 disables managed setup. Remove that explicit opt-out before requesting this complete update.", "preflight");
|
|
120
128
|
if (!Number.isSafeInteger(waitMs) || waitMs < 1 || waitMs > 600000) throw failure("UPDATE_ARGUMENT_INVALID", "The update readiness deadline is invalid.", "preflight");
|
|
121
129
|
root = fs.realpathSync.native(root);
|
|
122
130
|
const version = packageVersion(root);
|
|
123
131
|
const npm = resolveUpdateNpm(env);
|
|
132
|
+
const userPrefix = args.includes("--user") ? platform === "win32"
|
|
133
|
+
? path.join(env.APPDATA || path.join(env.USERPROFILE || os.homedir(), "AppData", "Roaming"), "npm")
|
|
134
|
+
: path.join(env.HOME || os.homedir(), ".local") : null;
|
|
135
|
+
if (userPrefix && (!path.isAbsolute(userPrefix) || /[\u0000-\u001f\u007f]/.test(userPrefix))) {
|
|
136
|
+
throw failure("UPDATE_GLOBAL_ROOT_INVALID", "The per-user installation directory is invalid.", "preflight");
|
|
137
|
+
}
|
|
138
|
+
const prefixArgs = userPrefix ? ["--prefix", userPrefix] : [];
|
|
124
139
|
let cwd = neutralDirectory([root], env);
|
|
125
140
|
let childEnv = Object.fromEntries(Object.entries(env).filter(([name]) => !/^AGENT_RELAY_(?!DIRECTORY$)/i.test(name)));
|
|
126
|
-
const command = async (arguments_, phase, timeout = 600000) => {
|
|
141
|
+
const command = async (arguments_, phase, timeout = 600000, environment = childEnv) => {
|
|
127
142
|
let result;
|
|
128
143
|
try {
|
|
129
|
-
result = await run(process.execPath, arguments_, { env:
|
|
144
|
+
result = await run(process.execPath, arguments_, { env: environment, cwd, encoding: "utf8", windowsHide: true,
|
|
130
145
|
shell: false, timeout, maxBuffer: 8 * 1024 * 1024, stdio: ["ignore", "pipe", "pipe"] });
|
|
131
146
|
} catch (error) { throw childFailure({ error, stderr: error.stderr }, phase); }
|
|
132
147
|
if (result?.error || (result?.status ?? result?.exitCode ?? 0) !== 0) throw childFailure(result, phase);
|
|
133
148
|
return String(result?.stdout ?? "");
|
|
134
149
|
};
|
|
135
|
-
const modules = (await command([npm, "root", "--global"], "preflight", 30000)).trim();
|
|
150
|
+
const modules = (await command([npm, "root", "--global", ...prefixArgs], "preflight", 30000)).trim();
|
|
136
151
|
if (!path.isAbsolute(modules) || /[\u0000-\u001f\u007f]/.test(modules)) throw failure("UPDATE_GLOBAL_ROOT_INVALID", "npm returned an invalid global installation directory.", "preflight");
|
|
137
|
-
const prefix = (await command([npm, "prefix", "--global"], "preflight", 30000)).trim();
|
|
138
|
-
if (!path.isAbsolute(prefix) || /[\u0000-\u001f\u007f]/.test(prefix)
|
|
152
|
+
const prefix = (await command([npm, "prefix", "--global", ...prefixArgs], "preflight", 30000)).trim();
|
|
153
|
+
if (!path.isAbsolute(prefix) || /[\u0000-\u001f\u007f]/.test(prefix) || userPrefix && path.relative(userPrefix, prefix) !== ""
|
|
139
154
|
|| path.relative(modules, path.join(prefix, ...(platform === "win32" ? [] : ["lib"]), "node_modules")) !== "") {
|
|
140
155
|
throw failure("UPDATE_GLOBAL_ROOT_INVALID", "npm returned inconsistent global prefix and installation directories.", "preflight");
|
|
141
156
|
}
|
|
@@ -146,7 +161,7 @@ export async function runUpdate({ args = [], env = process.env, platform = proce
|
|
|
146
161
|
const config = readConfig({ env: childEnv, platform, missing: true });
|
|
147
162
|
let runtime;
|
|
148
163
|
if (config) {
|
|
149
|
-
runtime = readRuntime(config.paths.root, { root: globalRoot, nodeExecutable: process.execPath });
|
|
164
|
+
runtime = readRuntime(config.paths.root, { root: globalRoot, nodeExecutable: process.execPath, allowMissingFiles: true });
|
|
150
165
|
if (runtime.packageVersion && newerVersion(runtime.packageVersion, version)) throw failure("UPDATE_DOWNGRADE_REFUSED", "The owned relay runtime is newer than this updater. Run the update command with the latest published package.", "preflight");
|
|
151
166
|
if (runtime.environment !== undefined) childEnv = { ...Object.fromEntries(Object.entries(childEnv).filter(([name]) => !MANAGED_ENV.has(name.toUpperCase()))), ...runtime.environment };
|
|
152
167
|
childEnv.AGENT_RELAY_DIRECTORY = config.paths.root;
|
|
@@ -176,26 +191,27 @@ export async function runUpdate({ args = [], env = process.env, platform = proce
|
|
|
176
191
|
if (!quiescent(config)) throw Object.assign(failure("UPDATE_RELAY_PENDING", `The disabled relay still has an owned process whose release could not be verified. ${RETRY}`, "migration"), { pending: true });
|
|
177
192
|
} else {
|
|
178
193
|
onProgress("Waiting for the legacy relay to finish existing work and activate the update runtime.");
|
|
179
|
-
const staged = runtime.packageVersion && !legacy(runtime.packageVersion) && !newerVersion("1.26.2", runtime.packageVersion);
|
|
194
|
+
const staged = runtime.filesAvailable !== false && runtime.packageVersion && !legacy(runtime.packageVersion) && !newerVersion("1.26.2", runtime.packageVersion);
|
|
180
195
|
const service = await awaitService(staged ? runtime.packageRoot : root, !staged, "migration", staged ? runtime.packageVersion : version);
|
|
181
196
|
migrated = !staged && service.enabled;
|
|
182
197
|
}
|
|
183
198
|
}
|
|
184
|
-
onProgress(`Installing bridge ${version}
|
|
185
|
-
await command([npm, "install", "--global", "--prefix", prefix, `${PACKAGE}@${version}`, "--ignore-scripts
|
|
199
|
+
onProgress(`Installing bridge ${version}.`);
|
|
200
|
+
await command([npm, "install", "--global", "--prefix", prefix, `${PACKAGE}@${version}`, "--ignore-scripts"],
|
|
201
|
+
"installation", 600000, { ...childEnv, CODEX_BRIDGE_SKIP_SETUP: "1" });
|
|
186
202
|
if (packageVersion(globalRoot) !== version) throw failure("UPDATE_VERSION_MISMATCH", "The global package version does not match the updater version. Rerun the same update command.", "verification");
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
203
|
+
for (const check of [false, true]) {
|
|
204
|
+
onProgress(check ? "Verifying the global bridge settings and owned relay runtime." : "Applying managed settings from the installed bridge.");
|
|
205
|
+
let setup;
|
|
206
|
+
try { setup = JSON.parse(await command([path.join(globalRoot, "scripts", "setup.mjs"), ...(check ? ["--check"] : []), "--json"], "verification")); }
|
|
207
|
+
catch (error) { if (error?.code) throw error; throw failure("UPDATE_SETUP_INCOMPLETE", `Global setup did not return a verifiable result. ${RETRY}`, "verification"); }
|
|
208
|
+
if (setup?.configured !== true) throw failure("UPDATE_SETUP_INCOMPLETE", `The global bridge settings are incomplete. ${RETRY}`, "verification");
|
|
209
|
+
}
|
|
192
210
|
const service = await awaitService(globalRoot, false, "verification");
|
|
193
211
|
return { updated: true, configured: true, version, previousVersion, migrated, service, opensApps: false, opensChats: false };
|
|
194
212
|
}
|
|
195
213
|
|
|
196
|
-
|
|
197
|
-
exitForVersionRequest(import.meta.url);
|
|
198
|
-
const args = process.argv.slice(2);
|
|
214
|
+
export async function runUpdateCli(args = process.argv.slice(2)) {
|
|
199
215
|
try {
|
|
200
216
|
process.chdir(neutralDirectory([ROOT], process.env));
|
|
201
217
|
const result = await runUpdate({ args, onProgress: message => process.stderr.write(`${message}\n`) });
|
|
@@ -208,3 +224,8 @@ if (isMainModule(process.argv[1], import.meta.url)) {
|
|
|
208
224
|
process.exitCode = 1;
|
|
209
225
|
}
|
|
210
226
|
}
|
|
227
|
+
|
|
228
|
+
if (isMainModule(process.argv[1], import.meta.url)) {
|
|
229
|
+
exitForVersionRequest(import.meta.url);
|
|
230
|
+
await runUpdateCli();
|
|
231
|
+
}
|
|
@@ -66,7 +66,7 @@ export function relayServiceRuntimeId(runtime) {
|
|
|
66
66
|
return createHash("sha256").update(JSON.stringify([runtime.packageRoot, runtime.nodeExecutable, runtime.packageVersion ?? null, runtime.environment ?? {}])).digest("hex");
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
export function readRelayServiceRuntime(directory, { root = ROOT, nodeExecutable = stableNodeBin() } = {}) {
|
|
69
|
+
export function readRelayServiceRuntime(directory, { root = ROOT, nodeExecutable = stableNodeBin(), allowMissingFiles = false } = {}) {
|
|
70
70
|
let text;
|
|
71
71
|
try { text = readRegularConfigFile(path.join(directory, "service-runtime.json"), { missing: true, maxBytes: 64 * 1024 }); }
|
|
72
72
|
catch { throw serviceFailure("SERVICE_RUNTIME_INVALID"); }
|
|
@@ -78,11 +78,17 @@ export function readRelayServiceRuntime(directory, { root = ROOT, nodeExecutable
|
|
|
78
78
|
|| ![value.packageRoot, value.nodeExecutable].every((entry) => typeof entry === "string" && path.isAbsolute(entry) && !/[\u0000-\u001f\u007f]/.test(entry))
|
|
79
79
|
|| value.environment !== undefined && (!value.environment || typeof value.environment !== "object" || Array.isArray(value.environment)
|
|
80
80
|
|| Object.entries(value.environment).some(([name, entry]) => !["HOME", "PATH", "CODEX_HOME", "CLAUDE_CONFIG_DIR", "XDG_CONFIG_HOME"].includes(name)
|
|
81
|
-
|| typeof entry !== "string" || !entry || /[\u0000-\u001f\u007f]/.test(entry)))
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
81
|
+
|| typeof entry !== "string" || !entry || /[\u0000-\u001f\u007f]/.test(entry)))) throw serviceFailure("SERVICE_RUNTIME_INVALID");
|
|
82
|
+
let filesAvailable = true;
|
|
83
|
+
for (const entry of [path.join(value.packageRoot, "src", "background-relay-service.mjs"), path.join(value.packageRoot, "src", "background-relay-daemon.mjs"), value.nodeExecutable]) {
|
|
84
|
+
try {
|
|
85
|
+
if (!fs.statSync(entry).isFile()) throw serviceFailure("SERVICE_RUNTIME_INVALID");
|
|
86
|
+
} catch (error) {
|
|
87
|
+
if (!allowMissingFiles || error.code !== "ENOENT") throw serviceFailure("SERVICE_RUNTIME_INVALID");
|
|
88
|
+
filesAvailable = false;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return allowMissingFiles ? { ...value, filesAvailable } : value;
|
|
86
92
|
}
|
|
87
93
|
|
|
88
94
|
export function acquireRelayServiceLock(root, { pid = process.pid, isAlive = alive, identity = processIdentity } = {}) {
|
package/src/claude-bridge.mjs
CHANGED
|
@@ -31,7 +31,7 @@ import { BACKGROUND_WORKER_GUIDANCE, registerBackgroundTools } from "./backgroun
|
|
|
31
31
|
|
|
32
32
|
exitForVersionRequest(import.meta.url);
|
|
33
33
|
|
|
34
|
-
const VERSION = "1.26.
|
|
34
|
+
const VERSION = "1.26.6";
|
|
35
35
|
void import("./telemetry.mjs").then(({ startUsageReporting }) => startUsageReporting({ version: VERSION })).catch(() => {});
|
|
36
36
|
const FORWARD_MIN_INTERVAL_MS = 5000;
|
|
37
37
|
const FORWARD_MAX_PER_SESSION = 50;
|
|
@@ -1,11 +1,39 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { runSupervisor } from "./mcp-supervisor.mjs";
|
|
3
3
|
import { handleTelemetryCommand } from "./telemetry.mjs";
|
|
4
|
-
|
|
4
|
+
import { exitForVersionRequest } from "./cli-version.mjs";
|
|
5
|
+
import { isMainModule } from "./install-paths.mjs";
|
|
6
|
+
|
|
7
|
+
async function applySetup(args) {
|
|
5
8
|
const { runSetup, printSetup } = await import("./setup.mjs");
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
const result = runSetup({ args });
|
|
10
|
+
printSetup(result, { json: args.includes("--json") });
|
|
11
|
+
return result;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export async function runLauncher({ args = process.argv.slice(2), env = process.env, platform = process.platform,
|
|
15
|
+
input = process.stdin, output = process.stdout, errorOutput = process.stderr, supervise = runSupervisor,
|
|
16
|
+
telemetry = handleTelemetryCommand, setup = applySetup,
|
|
17
|
+
updateCli = async args => (await import("../scripts/update.mjs")).runUpdateCli(args) } = {}) {
|
|
18
|
+
const terminalUpdate = args.length === 0 && env.npm_command === "exec" && input.isTTY === true && output.isTTY === true;
|
|
19
|
+
if (terminalUpdate || args[0] === "update") {
|
|
20
|
+
const updateArgs = terminalUpdate ? [] : args.slice(1);
|
|
21
|
+
return updateCli(platform === "win32" && !updateArgs.includes("--user") ? ["--user", ...updateArgs] : updateArgs);
|
|
22
|
+
}
|
|
23
|
+
if (args[0] === "setup") {
|
|
24
|
+
try {
|
|
25
|
+
const result = await setup(args.slice(1));
|
|
26
|
+
return result.configured === false && !result.dryRun ? 1 : 0;
|
|
27
|
+
} catch (error) {
|
|
28
|
+
errorOutput.write(`Bridge setup: ${error.message}\n`);
|
|
29
|
+
return 1;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (!await telemetry(args)) return supervise("index.mjs");
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (isMainModule(process.argv[1], import.meta.url)) {
|
|
36
|
+
exitForVersionRequest(import.meta.url);
|
|
37
|
+
const exitCode = await runLauncher();
|
|
38
|
+
if (Number.isInteger(exitCode)) process.exitCode = exitCode;
|
|
39
|
+
}
|
package/src/index.mjs
CHANGED
|
@@ -44,7 +44,7 @@ import { BACKGROUND_WORKER_GUIDANCE, registerBackgroundTools } from "./backgroun
|
|
|
44
44
|
|
|
45
45
|
exitForVersionRequest(import.meta.url);
|
|
46
46
|
|
|
47
|
-
const VERSION = "1.26.
|
|
47
|
+
const VERSION = "1.26.6";
|
|
48
48
|
void import("./telemetry.mjs").then(({ startUsageReporting }) => startUsageReporting({ version: VERSION })).catch(() => {});
|
|
49
49
|
const log = (msg) => process.stderr.write(`[codex-mcp-bridge] ${msg}\n`);
|
|
50
50
|
|
|
@@ -43,7 +43,7 @@ import { remoteCodexSocketPath, remoteNativeAdapter, remoteRequestResponse } fro
|
|
|
43
43
|
|
|
44
44
|
exitForVersionRequest(import.meta.url);
|
|
45
45
|
|
|
46
|
-
const VERSION = "1.26.
|
|
46
|
+
const VERSION = "1.26.6";
|
|
47
47
|
const log = (msg) => process.stderr.write(`[native-relay] ${msg}\n`);
|
|
48
48
|
|
|
49
49
|
function errorResponse(code, message, sent, details) {
|
package/src/setup.mjs
CHANGED
|
@@ -179,7 +179,7 @@ export function checkSetup({ env = process.env, platform = process.platform, roo
|
|
|
179
179
|
|
|
180
180
|
export function runSetup({ args = [], env = process.env, platform = process.platform, root = ROOT, run = execute, resolve = resolveCodexBin } = {}) {
|
|
181
181
|
const options = setupArguments(args);
|
|
182
|
-
if (options.help) return { help:
|
|
182
|
+
if (options.help) return { help: `Usage: codex-bridge-setup [--check|--dry-run] [--json] [--no-download]\nUpdate the package and apply managed settings in an interactive terminal with: ${platform === "win32" ? "npx.cmd" : "npx"} -y @minhspark/codex-mcp-bridge@latest\nThe updater installs the package with lifecycle scripts disabled, then directly configures Claude Desktop, Claude Code, Codex, Antigravity and the independent worker relay. CODEX_BRIDGE_SKIP_SETUP=1 opts out. Saved configuration, background relay health and loaded native app connections are verified separately.` };
|
|
183
183
|
if (options.postinstall && !automaticSetupEnabled(env)) return { skipped: true, reason: "Automatic configuration runs only for a global npm install; use codex-bridge-setup for manual setup." };
|
|
184
184
|
if (options.check) return checkSetup({ env, platform, root, run, resolve });
|
|
185
185
|
const native = platform === "win32" || platform === "darwin";
|