@remodex/rmx 1.0.3 → 1.0.4
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 +20 -5
- package/gui/dist/assets/index-1SDbgh2-.css +1 -0
- package/gui/dist/assets/{index-Cy432rMC.js → index-D3MaPif3.js} +13 -13
- package/gui/dist/index.html +2 -2
- package/package.json +5 -5
- package/src/android-remote/cloudflare-tunnel.ts +30 -8
- package/src/cli/help.ts +19 -6
- package/src/cli/index.ts +13 -75
- package/src/cli/init.ts +7 -1
- package/src/cli/internal-dispatch.ts +0 -6
- package/src/cli/onboard.ts +599 -0
- package/src/cli/system-command.ts +1 -85
- package/src/codex/inject.ts +8 -1
- package/src/codex/sync.ts +3 -0
- package/src/server/management/android-remote-routes.ts +1 -1
- package/src/server/management/config-routes.ts +0 -80
- package/src/server/management/context.ts +0 -4
- package/src/tray/windows-tray.ps1 +109 -66
- package/src/tray/windows.ts +7 -1
- package/src/update/job.ts +54 -6
- package/src/update/notify.ts +2 -2
- package/gui/dist/assets/index-CZqebSPQ.css +0 -1
- package/src/update/desktop-release.ts +0 -1620
package/gui/dist/index.html
CHANGED
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
} catch (e) {}
|
|
17
17
|
})();
|
|
18
18
|
</script>
|
|
19
|
-
<script type="module" crossorigin src="/assets/index-
|
|
20
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
19
|
+
<script type="module" crossorigin src="/assets/index-D3MaPif3.js"></script>
|
|
20
|
+
<link rel="stylesheet" crossorigin href="/assets/index-1SDbgh2-.css">
|
|
21
21
|
</head>
|
|
22
22
|
<body>
|
|
23
23
|
<div id="root"></div>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remodex/rmx",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "Remodex universal provider proxy for OpenAI Codex & Claude Code — use any LLM with Codex CLI/App/SDK and Claude Code",
|
|
5
5
|
"displayName": "Remodex",
|
|
6
6
|
"type": "module",
|
|
@@ -13,10 +13,10 @@
|
|
|
13
13
|
"./package.json": "./package.json"
|
|
14
14
|
},
|
|
15
15
|
"bin": {
|
|
16
|
-
"rmx": "
|
|
17
|
-
"remodex": "
|
|
18
|
-
"opencodex": "
|
|
19
|
-
"ocx": "
|
|
16
|
+
"rmx": "bin/ocx.mjs",
|
|
17
|
+
"remodex": "bin/ocx.mjs",
|
|
18
|
+
"opencodex": "bin/ocx.mjs",
|
|
19
|
+
"ocx": "bin/ocx.mjs"
|
|
20
20
|
},
|
|
21
21
|
"files": [
|
|
22
22
|
"bin",
|
|
@@ -8,7 +8,23 @@ import { resolveCloudflared, type CloudflaredExecutable } from "./cloudflared";
|
|
|
8
8
|
const QUICK_TUNNEL_URL = /https:\/\/[a-z0-9-]+\.trycloudflare\.com/iu;
|
|
9
9
|
const QUICK_URL_TIMEOUT_MS = 30_000;
|
|
10
10
|
const VERIFY_TIMEOUT_MS = 5_000;
|
|
11
|
-
const
|
|
11
|
+
const PROCESS_RETRY_DELAYS_MS = [1_000, 2_500, 5_000, 10_000, 30_000] as const;
|
|
12
|
+
// A freshly-created Quick Tunnel URL and a newly-written Named Tunnel DNS route
|
|
13
|
+
// can be visible in cloudflared output before Cloudflare's edge can serve it.
|
|
14
|
+
// Keep that expected propagation neutral in the UI for almost two minutes. If
|
|
15
|
+
// it still is not reachable, expose the failure but continue probing the same
|
|
16
|
+
// child and URL so late propagation can recover without generating a new URL.
|
|
17
|
+
const VERIFY_PROPAGATION_DELAYS_MS = [
|
|
18
|
+
1_000,
|
|
19
|
+
2_000,
|
|
20
|
+
3_000,
|
|
21
|
+
5_000,
|
|
22
|
+
8_000,
|
|
23
|
+
13_000,
|
|
24
|
+
20_000,
|
|
25
|
+
30_000,
|
|
26
|
+
30_000,
|
|
27
|
+
] as const;
|
|
12
28
|
|
|
13
29
|
export type AndroidRemoteCloudflareFailure =
|
|
14
30
|
| "cloudflared_unavailable"
|
|
@@ -175,8 +191,8 @@ async function verifiedPublicGateway(
|
|
|
175
191
|
try {
|
|
176
192
|
const signal = AbortSignal.timeout(VERIFY_TIMEOUT_MS);
|
|
177
193
|
const [healthResponse, descriptorResponse] = await Promise.all([
|
|
178
|
-
fetchImpl(new URL("/healthz", baseUrl), { signal }),
|
|
179
|
-
fetchImpl(new URL("/.well-known/t3/environment", baseUrl), { signal }),
|
|
194
|
+
fetchImpl(new URL("/healthz", baseUrl), { signal, cache: "no-store" }),
|
|
195
|
+
fetchImpl(new URL("/.well-known/t3/environment", baseUrl), { signal, cache: "no-store" }),
|
|
180
196
|
]);
|
|
181
197
|
if (!healthResponse.ok || !descriptorResponse.ok) return false;
|
|
182
198
|
const health = await healthResponse.json() as Record<string, unknown>;
|
|
@@ -218,7 +234,9 @@ export class ManagedAndroidRemoteCloudflareTunnel implements AndroidRemoteCloudf
|
|
|
218
234
|
}
|
|
219
235
|
return {
|
|
220
236
|
mode: settings.tunnelMode,
|
|
221
|
-
...(settings.
|
|
237
|
+
...(settings.tunnelMode === "named" && settings.namedTunnelHostname
|
|
238
|
+
? { namedHostname: settings.namedTunnelHostname }
|
|
239
|
+
: {}),
|
|
222
240
|
hasNamedTunnelToken: this.hasNamedTunnelToken,
|
|
223
241
|
};
|
|
224
242
|
}
|
|
@@ -322,7 +340,7 @@ export class ManagedAndroidRemoteCloudflareTunnel implements AndroidRemoteCloudf
|
|
|
322
340
|
publicUrl: null,
|
|
323
341
|
error: result,
|
|
324
342
|
});
|
|
325
|
-
const delay =
|
|
343
|
+
const delay = PROCESS_RETRY_DELAYS_MS[Math.min(attempt, PROCESS_RETRY_DELAYS_MS.length - 1)]!;
|
|
326
344
|
attempt += 1;
|
|
327
345
|
await this.deps.sleep(delay);
|
|
328
346
|
}
|
|
@@ -444,7 +462,7 @@ export class ManagedAndroidRemoteCloudflareTunnel implements AndroidRemoteCloudf
|
|
|
444
462
|
return "tunnel_failed";
|
|
445
463
|
}
|
|
446
464
|
verificationFailures += 1;
|
|
447
|
-
if (verificationFailures
|
|
465
|
+
if (verificationFailures > VERIFY_PROPAGATION_DELAYS_MS.length) {
|
|
448
466
|
this.publish({
|
|
449
467
|
mode,
|
|
450
468
|
status: "error",
|
|
@@ -452,7 +470,9 @@ export class ManagedAndroidRemoteCloudflareTunnel implements AndroidRemoteCloudf
|
|
|
452
470
|
error: "verification_failed",
|
|
453
471
|
});
|
|
454
472
|
}
|
|
455
|
-
const delay =
|
|
473
|
+
const delay = VERIFY_PROPAGATION_DELAYS_MS[
|
|
474
|
+
Math.min(verificationFailures - 1, VERIFY_PROPAGATION_DELAYS_MS.length - 1)
|
|
475
|
+
]!;
|
|
456
476
|
const wait = await Promise.race([
|
|
457
477
|
this.deps.sleep(delay).then(() => "retry" as const),
|
|
458
478
|
child.exited.then(() => "exit" as const),
|
|
@@ -473,7 +493,9 @@ export class DisabledAndroidRemoteCloudflareTunnel implements AndroidRemoteCloud
|
|
|
473
493
|
async configuration(settings: AndroidRemoteSettings): Promise<AndroidRemoteCloudflareConfiguration> {
|
|
474
494
|
return {
|
|
475
495
|
mode: settings.tunnelMode,
|
|
476
|
-
...(settings.
|
|
496
|
+
...(settings.tunnelMode === "named" && settings.namedTunnelHostname
|
|
497
|
+
? { namedHostname: settings.namedTunnelHostname }
|
|
498
|
+
: {}),
|
|
477
499
|
hasNamedTunnelToken: false,
|
|
478
500
|
};
|
|
479
501
|
}
|
package/src/cli/help.ts
CHANGED
|
@@ -20,6 +20,15 @@ function canonicalCommand(value: string): string {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
const helpEntries: Record<string, HelpEntry> = {
|
|
23
|
+
onboard: {
|
|
24
|
+
usage: "rmx onboard [--verbose] [--json] [--no-open]",
|
|
25
|
+
summary: "Configure Codex, Android Remote, the background service, and a verified phone link.",
|
|
26
|
+
details: [
|
|
27
|
+
"Safe to rerun: existing providers and custom-domain tunnels are preserved.",
|
|
28
|
+
"Fresh users get Quick Tunnel; Windows also installs the status tray.",
|
|
29
|
+
"--verbose shows inner command diagnostics; --json implies --no-open.",
|
|
30
|
+
],
|
|
31
|
+
},
|
|
23
32
|
init: { usage: "rmx init", summary: "Interactive setup for providers and Codex config injection." },
|
|
24
33
|
setup: { usage: "rmx setup", summary: "Interactive setup for providers and Codex config injection (alias of init)." },
|
|
25
34
|
start: { usage: "rmx start [--port <port>]", summary: "Start the proxy server and sync models to Codex." },
|
|
@@ -104,7 +113,10 @@ const helpEntries: Record<string, HelpEntry> = {
|
|
|
104
113
|
},
|
|
105
114
|
login: { usage: "rmx login <provider>", summary: "OAuth or API-key login for a provider." },
|
|
106
115
|
logout: { usage: "rmx logout <provider>", summary: "Remove a stored provider login." },
|
|
107
|
-
gui: {
|
|
116
|
+
gui: {
|
|
117
|
+
usage: "rmx gui [--update]",
|
|
118
|
+
summary: "Open the Remodex dashboard; --update opens the npm package updater.",
|
|
119
|
+
},
|
|
108
120
|
update: {
|
|
109
121
|
usage: "rmx update [--tag latest|preview]",
|
|
110
122
|
summary: "Update Remodex. Preview installs stay on the preview tag unless overridden.",
|
|
@@ -198,16 +210,15 @@ const helpEntries: Record<string, HelpEntry> = {
|
|
|
198
210
|
grok: { usage: "rmx grok <status|exclude|include|set|clear|apply> ...", summary: "Manage and apply the Grok Build model fence." },
|
|
199
211
|
integration: { usage: "rmx integration <claude|grok|client> ...", summary: "Manage supported client integrations." },
|
|
200
212
|
system: {
|
|
201
|
-
usage: "rmx system <status|settings|startup|diagnostics|sync|update
|
|
213
|
+
usage: "rmx system <status|settings|startup|diagnostics|sync|update> ...",
|
|
202
214
|
summary: "Manage headless runtime settings, startup, sync, diagnostics, and updates.",
|
|
203
215
|
details: [
|
|
216
|
+
"update check [--channel latest|preview] Check the @remodex/rmx package on npm.",
|
|
217
|
+
"update run [--channel latest|preview] --yes Install the npm package update.",
|
|
204
218
|
"update auto on [--channel latest|preview] Enable the daily unattended package updater (enabled by default for global installs).",
|
|
205
219
|
"update auto off Disable unattended package updates.",
|
|
206
220
|
"update auto status Show scheduler, last result, and rollback information.",
|
|
207
|
-
"
|
|
208
|
-
"desktop-update run [--channel latest|preview] Download and verify a native desktop update.",
|
|
209
|
-
"desktop-update status Show shared tray/dashboard update state.",
|
|
210
|
-
"Headless commands never install a native package; installation requires the desktop shell.",
|
|
221
|
+
"Changelogs come from the matching GitHub Release (v<version>).",
|
|
211
222
|
],
|
|
212
223
|
},
|
|
213
224
|
config: {
|
|
@@ -303,6 +314,7 @@ export function printUsage(): void {
|
|
|
303
314
|
|
|
304
315
|
Usage:
|
|
305
316
|
rmx Install/update and start the background service
|
|
317
|
+
rmx onboard Complete first-time setup and open the phone pairing QR
|
|
306
318
|
rmx setup Interactive setup (alias: init)
|
|
307
319
|
rmx start [--port <port>] Start the proxy server (auto-syncs models to Codex)
|
|
308
320
|
rmx stop Stop the proxy AND restore native Codex (plain codex works again)
|
|
@@ -349,6 +361,7 @@ Usage:
|
|
|
349
361
|
|
|
350
362
|
Examples:
|
|
351
363
|
rmx Install/update and start the background service
|
|
364
|
+
rmx onboard Set up Codex, the service, and Android Remote
|
|
352
365
|
rmx init Set up provider and inject into Codex
|
|
353
366
|
rmx start Start on default port (10100)
|
|
354
367
|
rmx start --port 8080 Start on custom port
|
package/src/cli/index.ts
CHANGED
|
@@ -59,15 +59,6 @@ import { maybeShowUpdatePrompt } from "../update/notify";
|
|
|
59
59
|
import { syncModelsToCodex } from "../codex/sync";
|
|
60
60
|
import { setIntegrationEnabled, shouldSyncCodexOnStart, shouldSyncGrokOnStart, syncCodexOnStartIfEnabled } from "../codex/desired-state";
|
|
61
61
|
import { normalizeUpdateChannel, runGuiUpdateWorker } from "../update/job";
|
|
62
|
-
import { currentVersion } from "../update/index";
|
|
63
|
-
import {
|
|
64
|
-
desktopUpdateInstallAction,
|
|
65
|
-
readDesktopUpdateState,
|
|
66
|
-
runAutomaticDesktopUpdateCheck,
|
|
67
|
-
runDesktopUpdateWorker,
|
|
68
|
-
startDesktopUpdateJob,
|
|
69
|
-
type DesktopReleaseChannel,
|
|
70
|
-
} from "../update/desktop-release";
|
|
71
62
|
import { collectOrcaCodexHomeDiagnostic } from "../codex/home";
|
|
72
63
|
import { removeOwnedConfigState } from "../lib/config-ownership";
|
|
73
64
|
import { withProcessRuntimeProvenance } from "../lib/bun-runtime";
|
|
@@ -663,56 +654,6 @@ async function handleTrayProxyRestart(): Promise<void> {
|
|
|
663
654
|
await handleProxyRestart(() => handleTrayProxyStart(false));
|
|
664
655
|
}
|
|
665
656
|
|
|
666
|
-
/**
|
|
667
|
-
* Fixed desktop-shell action used by the tray. A first click checks and
|
|
668
|
-
* downloads a verified artifact; once the tray shows "ready", the next click
|
|
669
|
-
* hands it to the platform installer. No caller-selected command or path is
|
|
670
|
-
* accepted here.
|
|
671
|
-
*/
|
|
672
|
-
async function handleDesktopUpdateRequest(requestArgs: string[] = []): Promise<void> {
|
|
673
|
-
let expectedReady: { id: string; channel: DesktopReleaseChannel } | undefined;
|
|
674
|
-
if (requestArgs.length > 0) {
|
|
675
|
-
const [mode, id, channel] = requestArgs;
|
|
676
|
-
if (
|
|
677
|
-
requestArgs.length !== 3
|
|
678
|
-
|| mode !== "--install-ready"
|
|
679
|
-
|| !id
|
|
680
|
-
|| !/^desktop-\d+-[a-z0-9]{1,32}$/.test(id)
|
|
681
|
-
|| (channel !== "latest" && channel !== "preview")
|
|
682
|
-
) {
|
|
683
|
-
console.error("Invalid desktop update request.");
|
|
684
|
-
process.exitCode = 64;
|
|
685
|
-
return;
|
|
686
|
-
}
|
|
687
|
-
expectedReady = { id, channel };
|
|
688
|
-
}
|
|
689
|
-
const previous = readDesktopUpdateState();
|
|
690
|
-
const install = expectedReady !== undefined || desktopUpdateInstallAction(previous);
|
|
691
|
-
const channel: DesktopReleaseChannel = expectedReady?.channel
|
|
692
|
-
?? previous?.channel
|
|
693
|
-
?? (currentVersion().includes("-") ? "preview" : "latest");
|
|
694
|
-
try {
|
|
695
|
-
const job = startDesktopUpdateJob(channel, {
|
|
696
|
-
install,
|
|
697
|
-
...(expectedReady ? { expectedReady } : {}),
|
|
698
|
-
});
|
|
699
|
-
console.log(
|
|
700
|
-
install
|
|
701
|
-
? `Desktop update installation started (${job.latestVersion ?? "latest"}).`
|
|
702
|
-
: "Desktop update check started.",
|
|
703
|
-
);
|
|
704
|
-
} catch (error) {
|
|
705
|
-
console.error(error instanceof Error ? error.message : "Desktop update could not start.");
|
|
706
|
-
process.exitCode = 1;
|
|
707
|
-
}
|
|
708
|
-
}
|
|
709
|
-
|
|
710
|
-
async function handleAutomaticDesktopUpdateCheck(): Promise<void> {
|
|
711
|
-
const channel: DesktopReleaseChannel = currentVersion().includes("-") ? "preview" : "latest";
|
|
712
|
-
const result = await runAutomaticDesktopUpdateCheck(channel);
|
|
713
|
-
console.log(JSON.stringify(result));
|
|
714
|
-
}
|
|
715
|
-
|
|
716
657
|
async function handleRestartStartWhenStopped(): Promise<boolean | "skipped"> {
|
|
717
658
|
if (!codexAutoStartEnabled(loadConfig())) {
|
|
718
659
|
console.log("Codex autostart is disabled; no proxy was started.");
|
|
@@ -1080,6 +1021,11 @@ async function handleReady(args: ReadyArgs): Promise<never> {
|
|
|
1080
1021
|
}
|
|
1081
1022
|
|
|
1082
1023
|
switch (command) {
|
|
1024
|
+
case "onboard": {
|
|
1025
|
+
const { runOnboardCommand } = await import("./onboard");
|
|
1026
|
+
process.exitCode = await runOnboardCommand(args.slice(1));
|
|
1027
|
+
break;
|
|
1028
|
+
}
|
|
1083
1029
|
case "init":
|
|
1084
1030
|
case "setup": {
|
|
1085
1031
|
const { runInit } = await import("./init");
|
|
@@ -1272,6 +1218,13 @@ switch (command) {
|
|
|
1272
1218
|
break;
|
|
1273
1219
|
}
|
|
1274
1220
|
case "gui": {
|
|
1221
|
+
const guiArgs = args.slice(1);
|
|
1222
|
+
const openUpdate = guiArgs.length === 1 && guiArgs[0] === "--update";
|
|
1223
|
+
if (guiArgs.length > (openUpdate ? 1 : 0)) {
|
|
1224
|
+
console.error("Usage: rmx gui [--update]");
|
|
1225
|
+
process.exitCode = 64;
|
|
1226
|
+
break;
|
|
1227
|
+
}
|
|
1275
1228
|
const cfg = await import("../config");
|
|
1276
1229
|
const config = cfg.loadConfig();
|
|
1277
1230
|
// Identity-checked liveness (not the pid file + a fixed sleep): finds a fallback-port
|
|
@@ -1295,7 +1248,7 @@ switch (command) {
|
|
|
1295
1248
|
// Open the host the proxy actually binds — `localhost` only answers for
|
|
1296
1249
|
// loopback/wildcard binds, not a concrete LAN/IPv6 hostname.
|
|
1297
1250
|
const guiHost = probeHostname(live?.hostname ?? config.hostname);
|
|
1298
|
-
const guiUrl = `http://${guiHost === "127.0.0.1" ? "localhost" : guiHost}:${live?.port ?? config.port}`;
|
|
1251
|
+
const guiUrl = `http://${guiHost === "127.0.0.1" ? "localhost" : guiHost}:${live?.port ?? config.port}${openUpdate ? "/#dashboard/update" : ""}`;
|
|
1299
1252
|
console.log(`Opening ${guiUrl}`);
|
|
1300
1253
|
const { openUrl } = await import("../lib/open-url");
|
|
1301
1254
|
openUrl(guiUrl);
|
|
@@ -1370,19 +1323,6 @@ switch (command) {
|
|
|
1370
1323
|
if (!result.ok) process.exitCode = 1;
|
|
1371
1324
|
break;
|
|
1372
1325
|
}
|
|
1373
|
-
case "__desktop-update-worker": {
|
|
1374
|
-
const id = args[1];
|
|
1375
|
-
const mode = args[2];
|
|
1376
|
-
if (!id || !/^desktop-\d+-[a-z0-9]+$/.test(id) || (mode !== "download" && mode !== "install")) {
|
|
1377
|
-
console.error("Invalid desktop update worker arguments.");
|
|
1378
|
-
process.exitCode = 64;
|
|
1379
|
-
break;
|
|
1380
|
-
}
|
|
1381
|
-
await runDesktopUpdateWorker(id, mode === "install");
|
|
1382
|
-
break;
|
|
1383
|
-
}
|
|
1384
|
-
case "__desktop-update":
|
|
1385
|
-
case "__desktop-auto-update-check":
|
|
1386
1326
|
case "__tray-start":
|
|
1387
1327
|
case "__tray-restart":
|
|
1388
1328
|
case "__startup-health":
|
|
@@ -1391,8 +1331,6 @@ switch (command) {
|
|
|
1391
1331
|
await dispatchInternalCliCommand(command as InternalCliCommand, {
|
|
1392
1332
|
trayStart: async () => { await handleTrayProxyStart(); },
|
|
1393
1333
|
trayRestart: handleTrayProxyRestart,
|
|
1394
|
-
desktopUpdate: () => handleDesktopUpdateRequest(args.slice(1)),
|
|
1395
|
-
desktopAutoUpdateCheck: handleAutomaticDesktopUpdateCheck,
|
|
1396
1334
|
startupHealth: async () => {
|
|
1397
1335
|
const { collectStartupHealth } = await import("../codex/autostart-health");
|
|
1398
1336
|
console.log(JSON.stringify(collectStartupHealth(loadConfig())));
|
package/src/cli/init.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as readline from "node:readline";
|
|
2
2
|
import { constants as fsConstants, copyFileSync, existsSync, readFileSync, unlinkSync } from "node:fs";
|
|
3
3
|
import { injectCodexConfig } from "../codex/inject";
|
|
4
|
+
import { CODEX_CONFIG_PATH } from "../codex/paths";
|
|
4
5
|
import { classifyOpenAiTierBackup, getConfigPath, getDefaultConfig, isValidProviderName, saveConfig } from "../config";
|
|
5
6
|
import { enrichProviderFromCatalog } from "../oauth/key-providers";
|
|
6
7
|
import { deriveInitProviders } from "../providers/derive";
|
|
@@ -189,13 +190,18 @@ export async function runInit(): Promise<void> {
|
|
|
189
190
|
// preserved by renaming it out of the collision path (sol review 260722).
|
|
190
191
|
cleanupOpenAiTierBackupAfterInit();
|
|
191
192
|
console.log(`\n✅ Config saved to ${getConfigPath()}`);
|
|
193
|
+
console.log(` Codex config target: ${CODEX_CONFIG_PATH}`);
|
|
192
194
|
if (oauthHint) console.log(`🔐 Authenticate this provider with: rmx login ${providerName}`);
|
|
193
195
|
|
|
194
196
|
const injectAnswer = await prompt.ask("Inject into Codex config.toml? [Y/n]: ");
|
|
195
197
|
if (injectAnswer.trim().toLowerCase() !== "n") {
|
|
196
198
|
console.log("Fetching available models from provider...");
|
|
197
199
|
const result = await injectCodexConfig(port, config);
|
|
198
|
-
|
|
200
|
+
const routed = result.success && result.routingApplied !== false;
|
|
201
|
+
console.log(routed ? `✅ ${result.message}` : `⚠️ ${result.message}`);
|
|
202
|
+
if (!routed) {
|
|
203
|
+
console.log(` Remodex did not take ownership of plain Codex routing. Review the reason above, then run 'rmx sync'.`);
|
|
204
|
+
}
|
|
199
205
|
}
|
|
200
206
|
|
|
201
207
|
const shimAnswer = await prompt.ask("Install Codex autostart shim? [Y/n]: ");
|
|
@@ -2,8 +2,6 @@ export type InternalCliCommand =
|
|
|
2
2
|
| "__tray-start"
|
|
3
3
|
| "__tray-restart"
|
|
4
4
|
| "__startup-health"
|
|
5
|
-
| "__desktop-update"
|
|
6
|
-
| "__desktop-auto-update-check"
|
|
7
5
|
| "__desktop-restart-codex"
|
|
8
6
|
| "__desktop-restart-client";
|
|
9
7
|
|
|
@@ -11,8 +9,6 @@ export interface InternalCliHandlers {
|
|
|
11
9
|
trayStart: () => void | Promise<void>;
|
|
12
10
|
trayRestart: () => void | Promise<void>;
|
|
13
11
|
startupHealth: () => void | Promise<void>;
|
|
14
|
-
desktopUpdate: () => void | Promise<void>;
|
|
15
|
-
desktopAutoUpdateCheck: () => void | Promise<void>;
|
|
16
12
|
desktopRestartCodex: () => void | Promise<void>;
|
|
17
13
|
desktopRestartClient: () => void | Promise<void>;
|
|
18
14
|
}
|
|
@@ -26,8 +22,6 @@ export async function dispatchInternalCliCommand(
|
|
|
26
22
|
case "__tray-start": return void await handlers.trayStart();
|
|
27
23
|
case "__tray-restart": return void await handlers.trayRestart();
|
|
28
24
|
case "__startup-health": return void await handlers.startupHealth();
|
|
29
|
-
case "__desktop-update": return void await handlers.desktopUpdate();
|
|
30
|
-
case "__desktop-auto-update-check": return void await handlers.desktopAutoUpdateCheck();
|
|
31
25
|
case "__desktop-restart-codex": return void await handlers.desktopRestartCodex();
|
|
32
26
|
case "__desktop-restart-client": return void await handlers.desktopRestartClient();
|
|
33
27
|
default: throw new Error(`Unsupported internal CLI command: ${String(command)}`);
|