@remodex/rmx 1.0.2 → 1.0.3
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 +15 -8
- package/bin/ocx.mjs +73 -14
- package/gui/dist/assets/{index-CkETtt7P.js → index-Cy432rMC.js} +1 -1
- package/gui/dist/index.html +1 -1
- package/package.json +1 -1
- package/src/cli/help.ts +9 -0
- package/src/cli/index.ts +36 -1
- package/src/cli/system-command.ts +37 -0
- package/src/lib/config-ownership.ts +5 -0
- package/src/lib/remodex-home.ts +5 -0
- package/src/update/auto-scheduler.ts +1671 -0
- package/src/update/job.ts +18 -7
package/gui/dist/index.html
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
} catch (e) {}
|
|
17
17
|
})();
|
|
18
18
|
</script>
|
|
19
|
-
<script type="module" crossorigin src="/assets/index-
|
|
19
|
+
<script type="module" crossorigin src="/assets/index-Cy432rMC.js"></script>
|
|
20
20
|
<link rel="stylesheet" crossorigin href="/assets/index-CZqebSPQ.css">
|
|
21
21
|
</head>
|
|
22
22
|
<body>
|
package/package.json
CHANGED
package/src/cli/help.ts
CHANGED
|
@@ -108,6 +108,10 @@ const helpEntries: Record<string, HelpEntry> = {
|
|
|
108
108
|
update: {
|
|
109
109
|
usage: "rmx update [--tag latest|preview]",
|
|
110
110
|
summary: "Update Remodex. Preview installs stay on the preview tag unless overridden.",
|
|
111
|
+
details: [
|
|
112
|
+
"Automatic updates are enabled by default for global installs.",
|
|
113
|
+
"Use `rmx system update auto off` to disable them, or `rmx system update auto status` to inspect the scheduler.",
|
|
114
|
+
],
|
|
111
115
|
},
|
|
112
116
|
provider: {
|
|
113
117
|
usage: "rmx provider <list|add|edit|test|remove|show|set-default|selected|quota|presets|account-mode>",
|
|
@@ -197,6 +201,9 @@ const helpEntries: Record<string, HelpEntry> = {
|
|
|
197
201
|
usage: "rmx system <status|settings|startup|diagnostics|sync|update|desktop-update> ...",
|
|
198
202
|
summary: "Manage headless runtime settings, startup, sync, diagnostics, and updates.",
|
|
199
203
|
details: [
|
|
204
|
+
"update auto on [--channel latest|preview] Enable the daily unattended package updater (enabled by default for global installs).",
|
|
205
|
+
"update auto off Disable unattended package updates.",
|
|
206
|
+
"update auto status Show scheduler, last result, and rollback information.",
|
|
200
207
|
"desktop-update check [--channel latest|preview] Check the native desktop release manifest.",
|
|
201
208
|
"desktop-update run [--channel latest|preview] Download and verify a native desktop update.",
|
|
202
209
|
"desktop-update status Show shared tray/dashboard update state.",
|
|
@@ -295,6 +302,7 @@ export function printUsage(): void {
|
|
|
295
302
|
const canonical = `Remodex (rmx) — Universal provider proxy for Codex
|
|
296
303
|
|
|
297
304
|
Usage:
|
|
305
|
+
rmx Install/update and start the background service
|
|
298
306
|
rmx setup Interactive setup (alias: init)
|
|
299
307
|
rmx start [--port <port>] Start the proxy server (auto-syncs models to Codex)
|
|
300
308
|
rmx stop Stop the proxy AND restore native Codex (plain codex works again)
|
|
@@ -340,6 +348,7 @@ Usage:
|
|
|
340
348
|
rmx --version | -v Print version
|
|
341
349
|
|
|
342
350
|
Examples:
|
|
351
|
+
rmx Install/update and start the background service
|
|
343
352
|
rmx init Set up provider and inject into Codex
|
|
344
353
|
rmx start Start on default port (10100)
|
|
345
354
|
rmx start --port 8080 Start on custom port
|
package/src/cli/index.ts
CHANGED
|
@@ -460,6 +460,10 @@ async function handleStart(options: { block?: boolean } = {}) {
|
|
|
460
460
|
// to explain it. Name the failure and the one command that repairs it.
|
|
461
461
|
console.error(`⚠️ ${grokSyncFailureMessage(err)}`);
|
|
462
462
|
}
|
|
463
|
+
try {
|
|
464
|
+
const { ensureDefaultAutoUpdateScheduler } = await import("../update/auto-scheduler");
|
|
465
|
+
ensureDefaultAutoUpdateScheduler();
|
|
466
|
+
} catch { /* default updater provisioning must never block proxy startup */ }
|
|
463
467
|
if (options.block ?? true) {
|
|
464
468
|
setInterval(() => {}, 60_000);
|
|
465
469
|
await new Promise<void>(() => {});
|
|
@@ -477,6 +481,12 @@ function detachedStartEnvironment(): NodeJS.ProcessEnv {
|
|
|
477
481
|
async function handleEnsure(options: { existingIsSuccess?: boolean } = {}): Promise<boolean> {
|
|
478
482
|
if (!currentExternalCodexModelProvider()) reconcileJournal();
|
|
479
483
|
const config = loadConfig();
|
|
484
|
+
// Provision the daily updater for global installs during the first normal
|
|
485
|
+
// bootstrap. The helper skips service children and the updater worker itself.
|
|
486
|
+
try {
|
|
487
|
+
const { ensureDefaultAutoUpdateScheduler } = await import("../update/auto-scheduler");
|
|
488
|
+
ensureDefaultAutoUpdateScheduler();
|
|
489
|
+
} catch { /* automatic updates must never block proxy startup */ }
|
|
480
490
|
if (!codexAutoStartEnabled(config)) {
|
|
481
491
|
console.log("Codex autostart is disabled.");
|
|
482
492
|
return false;
|
|
@@ -872,6 +882,17 @@ async function handleUninstall() {
|
|
|
872
882
|
}
|
|
873
883
|
};
|
|
874
884
|
|
|
885
|
+
await runStep("automatic updater removed", async () => {
|
|
886
|
+
const {
|
|
887
|
+
disableAutoUpdates,
|
|
888
|
+
readAutoUpdateStatus,
|
|
889
|
+
} = await import("../update/auto-scheduler");
|
|
890
|
+
const status = readAutoUpdateStatus();
|
|
891
|
+
if (status.scheduler === "absent" && !status.state) return false;
|
|
892
|
+
disableAutoUpdates();
|
|
893
|
+
return true;
|
|
894
|
+
});
|
|
895
|
+
|
|
875
896
|
await runStep("service stopped", () => stopServiceIfInstalled());
|
|
876
897
|
|
|
877
898
|
await runStep("proxy stopped", async () => {
|
|
@@ -1280,9 +1301,17 @@ switch (command) {
|
|
|
1280
1301
|
openUrl(guiUrl);
|
|
1281
1302
|
break;
|
|
1282
1303
|
}
|
|
1283
|
-
case "service":
|
|
1304
|
+
case "service": {
|
|
1305
|
+
const serviceSubcommand = args[1] ?? "install";
|
|
1284
1306
|
await serviceCommand(...args.slice(1));
|
|
1307
|
+
if (!["status", "stop", "uninstall", "remove"].includes(serviceSubcommand)) {
|
|
1308
|
+
try {
|
|
1309
|
+
const { ensureDefaultAutoUpdateScheduler } = await import("../update/auto-scheduler");
|
|
1310
|
+
ensureDefaultAutoUpdateScheduler();
|
|
1311
|
+
} catch { /* default updater provisioning must not block service commands */ }
|
|
1312
|
+
}
|
|
1285
1313
|
break;
|
|
1314
|
+
}
|
|
1286
1315
|
case "tray": {
|
|
1287
1316
|
const { windowsTrayCommand } = await import("../tray/windows");
|
|
1288
1317
|
await windowsTrayCommand(args.slice(1));
|
|
@@ -1335,6 +1364,12 @@ switch (command) {
|
|
|
1335
1364
|
await refreshVersionCache(channel);
|
|
1336
1365
|
break;
|
|
1337
1366
|
}
|
|
1367
|
+
case "__auto-update": {
|
|
1368
|
+
const { runAutomaticUpdateWorker } = await import("../update/auto-scheduler");
|
|
1369
|
+
const result = await runAutomaticUpdateWorker();
|
|
1370
|
+
if (!result.ok) process.exitCode = 1;
|
|
1371
|
+
break;
|
|
1372
|
+
}
|
|
1338
1373
|
case "__desktop-update-worker": {
|
|
1339
1374
|
const id = args[1];
|
|
1340
1375
|
const mode = args[2];
|
|
@@ -20,6 +20,7 @@ const USAGE = `Usage:
|
|
|
20
20
|
rmx system update check [--channel <latest|preview>] [--json]
|
|
21
21
|
rmx system update run [--channel <latest|preview>] [--restart <on|off>] --yes [--json]
|
|
22
22
|
rmx system update status <job-id> [--json]
|
|
23
|
+
rmx system update auto <on|off|status> [--channel <latest|preview>] [--json]
|
|
23
24
|
rmx system desktop-update check [--channel <latest|preview>] [--json]
|
|
24
25
|
rmx system desktop-update run [--channel <latest|preview>] [--json]
|
|
25
26
|
rmx system desktop-update status [--json]`;
|
|
@@ -72,6 +73,42 @@ async function update(argv: string[], deps: RuntimeApiDeps): Promise<void> {
|
|
|
72
73
|
const args = [...argv];
|
|
73
74
|
const action = (args.shift() ?? "check").toLowerCase();
|
|
74
75
|
const wantsJson = takeFlag(args, "--json");
|
|
76
|
+
if (action === "auto") {
|
|
77
|
+
const autoAction = (args.shift() ?? "status").toLowerCase();
|
|
78
|
+
const channel = takeOption(args, "--channel");
|
|
79
|
+
if (channel !== undefined && channel !== "latest" && channel !== "preview") {
|
|
80
|
+
throw new CliUsageError("--channel must be latest or preview", USAGE);
|
|
81
|
+
}
|
|
82
|
+
rejectArgs(args, USAGE);
|
|
83
|
+
const {
|
|
84
|
+
disableAutoUpdates,
|
|
85
|
+
enableAutoUpdates,
|
|
86
|
+
formatAutoUpdateStatus,
|
|
87
|
+
readAutoUpdateStatus,
|
|
88
|
+
} = await import("../update/auto-scheduler");
|
|
89
|
+
if (autoAction === "status") {
|
|
90
|
+
if (channel !== undefined) throw new CliUsageError("--channel applies to `auto on` only", USAGE);
|
|
91
|
+
const result = readAutoUpdateStatus();
|
|
92
|
+
printData(result, wantsJson, formatAutoUpdateStatus(result));
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
if (autoAction === "on") {
|
|
96
|
+
const state = enableAutoUpdates(channel as "latest" | "preview" | undefined);
|
|
97
|
+
printData(
|
|
98
|
+
state,
|
|
99
|
+
wantsJson,
|
|
100
|
+
[`Automatic updates enabled (${state.channel}; daily at ${String(state.schedule.hour).padStart(2, "0")}:${String(state.schedule.minute).padStart(2, "0")} local time).`],
|
|
101
|
+
);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
if (autoAction === "off") {
|
|
105
|
+
if (channel !== undefined) throw new CliUsageError("--channel applies to `auto on` only", USAGE);
|
|
106
|
+
const state = disableAutoUpdates();
|
|
107
|
+
printData(state, wantsJson, ["Automatic updates disabled."]);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
throw new CliUsageError(`unknown automatic-update action ${autoAction}`, USAGE);
|
|
111
|
+
}
|
|
75
112
|
if (action === "status") {
|
|
76
113
|
const jobId = args.shift();
|
|
77
114
|
if (!jobId) throw new CliUsageError("update job id is required", USAGE);
|
|
@@ -41,6 +41,11 @@ const INITIAL_OWNED_PATHS = [
|
|
|
41
41
|
"artifacts",
|
|
42
42
|
"auth.json",
|
|
43
43
|
"auth.store.lock",
|
|
44
|
+
"auto-update.cmd",
|
|
45
|
+
"auto-update-task.xml",
|
|
46
|
+
"auto-update.json",
|
|
47
|
+
"auto-update.lock",
|
|
48
|
+
"auto-update.log",
|
|
44
49
|
"catalog-backup.json",
|
|
45
50
|
"claude-env.sh",
|
|
46
51
|
"codex-accounts.json",
|
package/src/lib/remodex-home.ts
CHANGED
|
@@ -23,6 +23,11 @@ export const REMODEX_STATE_EVIDENCE_FILES = [
|
|
|
23
23
|
".opencodex-uninstall.json",
|
|
24
24
|
"admin-api-token",
|
|
25
25
|
"android-remote.json",
|
|
26
|
+
"auto-update.cmd",
|
|
27
|
+
"auto-update-task.xml",
|
|
28
|
+
"auto-update.json",
|
|
29
|
+
"auto-update.lock",
|
|
30
|
+
"auto-update.log",
|
|
26
31
|
"catalog-backup.json",
|
|
27
32
|
"codex-runtime-clamp.json",
|
|
28
33
|
"codex-runtime.json",
|