@camstack/agent 1.1.50 → 1.1.52
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/dist/{chunk-P6AJ6S7H.mjs → chunk-67UOSAWB.mjs} +2 -2
- package/dist/{chunk-Y6BUFOWG.mjs → chunk-KPUXW5YX.mjs} +84 -55
- package/dist/chunk-KPUXW5YX.mjs.map +1 -0
- package/dist/cli.js +113 -72
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +30 -18
- package/dist/cli.mjs.map +1 -1
- package/dist/index.js +83 -54
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/starter.js +83 -54
- package/dist/starter.js.map +1 -1
- package/dist/starter.mjs +1 -1
- package/package.json +8 -8
- package/dist/chunk-Y6BUFOWG.mjs.map +0 -1
- /package/dist/{chunk-P6AJ6S7H.mjs.map → chunk-67UOSAWB.mjs.map} +0 -0
package/dist/cli.mjs
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import { createRequire as __cr } from 'node:module'; const require = globalThis.require ?? __cr(import.meta.url);
|
|
3
3
|
import {
|
|
4
4
|
startAgent
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-67UOSAWB.mjs";
|
|
6
|
+
import "./chunk-KPUXW5YX.mjs";
|
|
7
7
|
|
|
8
8
|
// src/cli.ts
|
|
9
9
|
import { existsSync } from "fs";
|
|
@@ -122,23 +122,35 @@ if (args.statusPort && !process.env["CAMSTACK_STATUS_PORT"]) {
|
|
|
122
122
|
process.env["CAMSTACK_STATUS_PORT"] = args.statusPort;
|
|
123
123
|
}
|
|
124
124
|
if (!process.env["CAMSTACK_FRAMEWORK_DIR"]) {
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
const
|
|
125
|
+
const isFrameworkDir = (dir) => existsSync(path.join(dir, "node_modules", "@camstack", "shm-ring")) && existsSync(path.join(dir, "node_modules", "@camstack", "system"));
|
|
126
|
+
const discoverFrameworkDir = () => {
|
|
127
|
+
const activeRoot = process.env["CAMSTACK_AGENT_ACTIVE_ROOT"];
|
|
128
|
+
if (activeRoot && isFrameworkDir(activeRoot)) return activeRoot;
|
|
129
|
+
const scriptPath = process.argv[1];
|
|
130
|
+
if (!scriptPath) return null;
|
|
131
|
+
let dir = path.dirname(scriptPath);
|
|
132
|
+
for (let depth = 0; depth < 8; depth++) {
|
|
133
|
+
if (isFrameworkDir(dir)) return dir;
|
|
134
|
+
const parent = path.dirname(dir);
|
|
135
|
+
if (parent === dir) break;
|
|
136
|
+
dir = parent;
|
|
137
|
+
}
|
|
138
|
+
return null;
|
|
139
|
+
};
|
|
140
|
+
const frameworkDir = discoverFrameworkDir();
|
|
141
|
+
if (frameworkDir) {
|
|
128
142
|
const frameworkModules = path.join(frameworkDir, "node_modules");
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
process.env["CAMSTACK_BUNDLED_ADDONS_DIR"] = bundledAddons;
|
|
141
|
-
}
|
|
143
|
+
process.env["CAMSTACK_FRAMEWORK_DIR"] = frameworkDir;
|
|
144
|
+
const existingNodePath = process.env["NODE_PATH"];
|
|
145
|
+
process.env["NODE_PATH"] = existingNodePath ? `${frameworkModules}${path.delimiter}${existingNodePath}` : frameworkModules;
|
|
146
|
+
nodeModule._initPaths();
|
|
147
|
+
console.log(
|
|
148
|
+
`[Agent] Self-contained framework detected \u2014 CAMSTACK_FRAMEWORK_DIR=${frameworkDir}`
|
|
149
|
+
);
|
|
150
|
+
if (!process.env["CAMSTACK_BUNDLED_ADDONS_DIR"]) {
|
|
151
|
+
const bundledAddons = path.join(frameworkDir, "addons");
|
|
152
|
+
if (existsSync(bundledAddons)) {
|
|
153
|
+
process.env["CAMSTACK_BUNDLED_ADDONS_DIR"] = bundledAddons;
|
|
142
154
|
}
|
|
143
155
|
}
|
|
144
156
|
}
|
package/dist/cli.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * CamStack Agent CLI — starts a remote agent node that connects to a hub.\n *\n * Usage:\n * camstack-agent --hub 192.168.1.100\n * camstack-agent --hub 192.168.1.100 --name gpu-box --data ./agent-data\n * CAMSTACK_HUB_ADDRESS=192.168.1.100 camstack-agent\n */\nimport { existsSync } from 'node:fs'\nimport { Module as nodeModule } from 'node:module'\nimport * as os from 'node:os'\nimport * as path from 'node:path'\nimport { startAgent } from './agent-bootstrap.js'\n\n// `Module._initPaths()` re-derives the CJS search paths from a NODE_PATH set\n// after process start. It's a stable Node internal backing NODE_PATH support\n// but is absent from @types/node — declare it via merging (no cast).\ndeclare module 'node:module' {\n // eslint-disable-next-line @typescript-eslint/no-namespace\n namespace Module {\n function _initPaths(): void\n }\n}\n\ninterface CliArgs {\n hub?: string\n name?: string\n data?: string\n logLevel?: string\n secret?: string\n statusPort?: string\n help?: boolean\n}\n\nfunction parseArgs(argv: readonly string[]): CliArgs {\n const args: CliArgs = {}\n for (let i = 2; i < argv.length; i++) {\n const arg = argv[i]!\n const next = argv[i + 1]\n switch (arg) {\n case '--hub':\n case '-h':\n if (arg === '-h' && !next?.match(/^[\\d.]+/)) {\n args.help = true\n break\n }\n args.hub = next\n i++\n break\n case '--name':\n case '-n':\n args.name = next\n i++\n break\n case '--data':\n case '-d':\n args.data = next\n i++\n break\n case '--log-level':\n case '-l':\n args.logLevel = next\n i++\n break\n case '--secret':\n case '-s':\n args.secret = next\n i++\n break\n case '--status-port':\n case '-p':\n args.statusPort = next\n i++\n break\n case '--help':\n args.help = true\n break\n default:\n if (!arg.startsWith('-') && !args.hub) {\n args.hub = arg\n break\n }\n console.error(`Unknown argument: ${arg}`)\n args.help = true\n }\n }\n return args\n}\n\nfunction printHelp(): void {\n console.log(\n `\ncamstack-agent — CamStack remote agent node\n\nUsage:\n camstack-agent --hub <hub-address> [options]\n camstack-agent <hub-address> [options]\n\nOptions:\n --hub, -h <address> Hub address (IP or hostname, e.g. 192.168.1.100)\n --name, -n <name> Node name (default: hostname)\n --data, -d <path> Data directory (default: ./camstack-data)\n --log-level, -l <level> Log level: trace|debug|info|warn|error (default: info)\n --secret, -s <secret> Cluster secret (nodes must share the same secret)\n --help Show this help\n\nEnvironment variables (override CLI args):\n CAMSTACK_NODE_ID Node identifier\n CAMSTACK_HUB_ADDRESS Hub address\n CAMSTACK_DATA_DIR Data directory path\n CAMSTACK_LOG_LEVEL Log level\n CAMSTACK_CLUSTER_SECRET Cluster secret\n CAMSTACK_HUB_URL Derived automatically from the hub address; set\n only to override the cross-node stream/recording\n pull host\n\nExamples:\n camstack-agent --hub 192.168.1.100\n camstack-agent --hub 192.168.1.100 --name gpu-box --log-level debug\n CAMSTACK_HUB_ADDRESS=192.168.1.100 camstack-agent\n`.trim(),\n )\n}\n\nconst args = parseArgs(process.argv)\n\nif (args.help) {\n printHelp()\n process.exit(0)\n}\n\n// CLI args → env vars (env vars set externally take precedence via agent-config.ts)\nif (args.hub && !process.env['CAMSTACK_HUB_ADDRESS']) {\n process.env['CAMSTACK_HUB_ADDRESS'] = args.hub\n}\nif (args.name && !process.env['CAMSTACK_NODE_ID']) {\n process.env['CAMSTACK_NODE_ID'] = args.name\n}\nif (args.data && !process.env['CAMSTACK_DATA_DIR']) {\n process.env['CAMSTACK_DATA_DIR'] = args.data\n}\nif (args.logLevel && !process.env['CAMSTACK_LOG_LEVEL']) {\n process.env['CAMSTACK_LOG_LEVEL'] = args.logLevel\n}\nif (args.secret && !process.env['CAMSTACK_CLUSTER_SECRET']) {\n process.env['CAMSTACK_CLUSTER_SECRET'] = args.secret\n}\nif (args.statusPort && !process.env['CAMSTACK_STATUS_PORT']) {\n process.env['CAMSTACK_STATUS_PORT'] = args.statusPort\n}\n\n// Packaged-app framework resolution. In a self-contained build (e.g. the\n// Electron `.app`, where this CLI lives at `<root>/agent/dist/cli.js` and the\n// host-provided package closure at `<root>/node_modules`), addons installed\n// under the data dir cannot walk up to the framework's node_modules. Mirror the\n// Docker image's setup: point the addon-runner's resolver hook at the framework\n// (CAMSTACK_FRAMEWORK_DIR, for ESM imports) AND seed NODE_PATH (for CJS\n// `require`) so host externals (@camstack/shm-ring, sharp, node-av, …) resolve.\n// No-op in dev (workspace symlinks resolve the framework) and when an operator\n// or the Docker image has already set CAMSTACK_FRAMEWORK_DIR.\nif (!process.env['CAMSTACK_FRAMEWORK_DIR']) {\n const scriptPath = process.argv[1]\n if (scriptPath) {\n const frameworkDir = path.resolve(path.dirname(scriptPath), '..', '..')\n const frameworkModules = path.join(frameworkDir, 'node_modules')\n // Sentinel: a host-provided native package present in the framework's\n // node_modules confirms the self-contained layout (absent in dev).\n if (existsSync(path.join(frameworkModules, '@camstack', 'shm-ring'))) {\n process.env['CAMSTACK_FRAMEWORK_DIR'] = frameworkDir\n const existingNodePath = process.env['NODE_PATH']\n process.env['NODE_PATH'] = existingNodePath\n ? `${frameworkModules}${path.delimiter}${existingNodePath}`\n : frameworkModules\n // Node reads NODE_PATH once at startup into the CJS module search paths;\n // setting it now (post-start) only reaches CHILD processes that inherit\n // it at spawn (the forked addon-runners). The agent's OWN main process —\n // where bootCoreAddons imports the in-process infra builtins (storage /\n // settings / metrics from @camstack/system) — must re-derive its search\n // paths or those addons' host-dep requires (@camstack/types, …) fail with\n // \"Cannot find module\" and the agent boots with NO infrastructure.\n nodeModule._initPaths()\n console.log(\n `[Agent] Self-contained framework detected — CAMSTACK_FRAMEWORK_DIR=${frameworkDir}`,\n )\n // Also point the bootstrap installer at the bundled addons so a fresh\n // (empty) data dir gets seeded with the agent's required packages\n // (@camstack/system — platform-probe/storage/settings/metrics builtins —\n // plus the bundled addons). Without this, bootCoreAddons finds no addon\n // packages and the agent runs with NO infrastructure (no platform-probe →\n // detection engine can't auto-pick the node's accelerator, no storage,\n // etc.). Mirrors the Docker image's CAMSTACK_BUNDLED_ADDONS_DIR.\n if (!process.env['CAMSTACK_BUNDLED_ADDONS_DIR']) {\n const bundledAddons = path.join(frameworkDir, 'addons')\n if (existsSync(bundledAddons)) {\n process.env['CAMSTACK_BUNDLED_ADDONS_DIR'] = bundledAddons\n }\n }\n }\n }\n}\n\n// Default node name to hostname if not set\nif (!process.env['CAMSTACK_NODE_ID']) {\n process.env['CAMSTACK_NODE_ID'] = os.hostname()\n}\n\n// Hub address is optional — agent starts in discovery mode without it.\n// The agent UI on :4444 lets the user configure the hub connection.\nif (!process.env['CAMSTACK_HUB_ADDRESS']) {\n console.log('[Agent] No hub address specified — starting in discovery mode')\n console.log('[Agent] Configure hub connection at http://localhost:4444')\n}\n\nstartAgent().catch((err: unknown) => {\n console.error('[Agent] Fatal error:', err)\n process.exit(1)\n})\n"],"mappings":"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","names":["args"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * CamStack Agent CLI — starts a remote agent node that connects to a hub.\n *\n * Usage:\n * camstack-agent --hub 192.168.1.100\n * camstack-agent --hub 192.168.1.100 --name gpu-box --data ./agent-data\n * CAMSTACK_HUB_ADDRESS=192.168.1.100 camstack-agent\n */\nimport { existsSync } from 'node:fs'\nimport { Module as nodeModule } from 'node:module'\nimport * as os from 'node:os'\nimport * as path from 'node:path'\nimport { startAgent } from './agent-bootstrap.js'\n\n// `Module._initPaths()` re-derives the CJS search paths from a NODE_PATH set\n// after process start. It's a stable Node internal backing NODE_PATH support\n// but is absent from @types/node — declare it via merging (no cast).\ndeclare module 'node:module' {\n // eslint-disable-next-line @typescript-eslint/no-namespace\n namespace Module {\n function _initPaths(): void\n }\n}\n\ninterface CliArgs {\n hub?: string\n name?: string\n data?: string\n logLevel?: string\n secret?: string\n statusPort?: string\n help?: boolean\n}\n\nfunction parseArgs(argv: readonly string[]): CliArgs {\n const args: CliArgs = {}\n for (let i = 2; i < argv.length; i++) {\n const arg = argv[i]!\n const next = argv[i + 1]\n switch (arg) {\n case '--hub':\n case '-h':\n if (arg === '-h' && !next?.match(/^[\\d.]+/)) {\n args.help = true\n break\n }\n args.hub = next\n i++\n break\n case '--name':\n case '-n':\n args.name = next\n i++\n break\n case '--data':\n case '-d':\n args.data = next\n i++\n break\n case '--log-level':\n case '-l':\n args.logLevel = next\n i++\n break\n case '--secret':\n case '-s':\n args.secret = next\n i++\n break\n case '--status-port':\n case '-p':\n args.statusPort = next\n i++\n break\n case '--help':\n args.help = true\n break\n default:\n if (!arg.startsWith('-') && !args.hub) {\n args.hub = arg\n break\n }\n console.error(`Unknown argument: ${arg}`)\n args.help = true\n }\n }\n return args\n}\n\nfunction printHelp(): void {\n console.log(\n `\ncamstack-agent — CamStack remote agent node\n\nUsage:\n camstack-agent --hub <hub-address> [options]\n camstack-agent <hub-address> [options]\n\nOptions:\n --hub, -h <address> Hub address (IP or hostname, e.g. 192.168.1.100)\n --name, -n <name> Node name (default: hostname)\n --data, -d <path> Data directory (default: ./camstack-data)\n --log-level, -l <level> Log level: trace|debug|info|warn|error (default: info)\n --secret, -s <secret> Cluster secret (nodes must share the same secret)\n --help Show this help\n\nEnvironment variables (override CLI args):\n CAMSTACK_NODE_ID Node identifier\n CAMSTACK_HUB_ADDRESS Hub address\n CAMSTACK_DATA_DIR Data directory path\n CAMSTACK_LOG_LEVEL Log level\n CAMSTACK_CLUSTER_SECRET Cluster secret\n CAMSTACK_HUB_URL Derived automatically from the hub address; set\n only to override the cross-node stream/recording\n pull host\n\nExamples:\n camstack-agent --hub 192.168.1.100\n camstack-agent --hub 192.168.1.100 --name gpu-box --log-level debug\n CAMSTACK_HUB_ADDRESS=192.168.1.100 camstack-agent\n`.trim(),\n )\n}\n\nconst args = parseArgs(process.argv)\n\nif (args.help) {\n printHelp()\n process.exit(0)\n}\n\n// CLI args → env vars (env vars set externally take precedence via agent-config.ts)\nif (args.hub && !process.env['CAMSTACK_HUB_ADDRESS']) {\n process.env['CAMSTACK_HUB_ADDRESS'] = args.hub\n}\nif (args.name && !process.env['CAMSTACK_NODE_ID']) {\n process.env['CAMSTACK_NODE_ID'] = args.name\n}\nif (args.data && !process.env['CAMSTACK_DATA_DIR']) {\n process.env['CAMSTACK_DATA_DIR'] = args.data\n}\nif (args.logLevel && !process.env['CAMSTACK_LOG_LEVEL']) {\n process.env['CAMSTACK_LOG_LEVEL'] = args.logLevel\n}\nif (args.secret && !process.env['CAMSTACK_CLUSTER_SECRET']) {\n process.env['CAMSTACK_CLUSTER_SECRET'] = args.secret\n}\nif (args.statusPort && !process.env['CAMSTACK_STATUS_PORT']) {\n process.env['CAMSTACK_STATUS_PORT'] = args.statusPort\n}\n\n// Packaged-app framework resolution. In a self-contained build (e.g. the\n// Electron `.app`, where this CLI lives at `<root>/agent/dist/cli.js` and the\n// host-provided package closure at `<root>/node_modules`), addons installed\n// under the data dir cannot walk up to the framework's node_modules. Mirror the\n// Docker image's setup: point the addon-runner's resolver hook at the framework\n// (CAMSTACK_FRAMEWORK_DIR, for ESM imports) AND seed NODE_PATH (for CJS\n// `require`) so host externals (@camstack/shm-ring, sharp, node-av, …) resolve.\n// No-op in dev (workspace symlinks resolve the framework) and when an operator\n// or the Docker image has already set CAMSTACK_FRAMEWORK_DIR.\n//\n// Framework-dir discovery order:\n// 1. An active data-root (CAMSTACK_AGENT_ACTIVE_ROOT, set by the starter) —\n// its node_modules IS the closure the entry was loaded from.\n// 2. Bounded walk-up from the entry script. The old fixed `../..` only\n// matched the Docker layout (`<root>/agent/dist/cli.js`); npm-installed\n// layouts (the Electron seed: `<root>/node_modules/@camstack/agent/dist/\n// cli.js`) put the closure THREE levels further up, so every addon\n// needing a host external (@camstack/shm-ring, …) crashed at import and\n// the node dropped out of the placement pool (Mac mini, 2026-07-16).\nif (!process.env['CAMSTACK_FRAMEWORK_DIR']) {\n const isFrameworkDir = (dir: string): boolean =>\n existsSync(path.join(dir, 'node_modules', '@camstack', 'shm-ring')) &&\n existsSync(path.join(dir, 'node_modules', '@camstack', 'system'))\n const discoverFrameworkDir = (): string | null => {\n const activeRoot = process.env['CAMSTACK_AGENT_ACTIVE_ROOT']\n if (activeRoot && isFrameworkDir(activeRoot)) return activeRoot\n const scriptPath = process.argv[1]\n if (!scriptPath) return null\n let dir = path.dirname(scriptPath)\n for (let depth = 0; depth < 8; depth++) {\n if (isFrameworkDir(dir)) return dir\n const parent = path.dirname(dir)\n if (parent === dir) break\n dir = parent\n }\n return null\n }\n const frameworkDir = discoverFrameworkDir()\n if (frameworkDir) {\n const frameworkModules = path.join(frameworkDir, 'node_modules')\n process.env['CAMSTACK_FRAMEWORK_DIR'] = frameworkDir\n const existingNodePath = process.env['NODE_PATH']\n process.env['NODE_PATH'] = existingNodePath\n ? `${frameworkModules}${path.delimiter}${existingNodePath}`\n : frameworkModules\n // Node reads NODE_PATH once at startup into the CJS module search paths;\n // setting it now (post-start) only reaches CHILD processes that inherit\n // it at spawn (the forked addon-runners). The agent's OWN main process —\n // where bootCoreAddons imports the in-process infra builtins (storage /\n // settings / metrics from @camstack/system) — must re-derive its search\n // paths or those addons' host-dep requires (@camstack/types, …) fail with\n // \"Cannot find module\" and the agent boots with NO infrastructure.\n nodeModule._initPaths()\n console.log(\n `[Agent] Self-contained framework detected — CAMSTACK_FRAMEWORK_DIR=${frameworkDir}`,\n )\n // Also point the bootstrap installer at the bundled addons so a fresh\n // (empty) data dir gets seeded with the agent's required packages\n // (@camstack/system — platform-probe/storage/settings/metrics builtins —\n // plus the bundled addons). Without this, bootCoreAddons finds no addon\n // packages and the agent runs with NO infrastructure (no platform-probe →\n // detection engine can't auto-pick the node's accelerator, no storage,\n // etc.). Mirrors the Docker image's CAMSTACK_BUNDLED_ADDONS_DIR.\n if (!process.env['CAMSTACK_BUNDLED_ADDONS_DIR']) {\n const bundledAddons = path.join(frameworkDir, 'addons')\n if (existsSync(bundledAddons)) {\n process.env['CAMSTACK_BUNDLED_ADDONS_DIR'] = bundledAddons\n }\n }\n }\n}\n\n// Default node name to hostname if not set\nif (!process.env['CAMSTACK_NODE_ID']) {\n process.env['CAMSTACK_NODE_ID'] = os.hostname()\n}\n\n// Hub address is optional — agent starts in discovery mode without it.\n// The agent UI on :4444 lets the user configure the hub connection.\nif (!process.env['CAMSTACK_HUB_ADDRESS']) {\n console.log('[Agent] No hub address specified — starting in discovery mode')\n console.log('[Agent] Configure hub connection at http://localhost:4444')\n}\n\nstartAgent().catch((err: unknown) => {\n console.error('[Agent] Fatal error:', err)\n process.exit(1)\n})\n"],"mappings":"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","names":["args"]}
|
package/dist/index.js
CHANGED
|
@@ -88,6 +88,7 @@ var require_dist = __commonJS({
|
|
|
88
88
|
planBoot: () => planBoot,
|
|
89
89
|
readDevUploadManifest: () => readDevUploadManifest,
|
|
90
90
|
readRestartIntentMarker: () => readRestartIntentMarker,
|
|
91
|
+
readSeedVersion: () => readSeedVersion,
|
|
91
92
|
readServerRootState: () => readServerRootState,
|
|
92
93
|
registerActiveRootResolver: () => registerActiveRootResolver,
|
|
93
94
|
restartIntentMarkerPath: () => restartIntentMarkerPath,
|
|
@@ -299,7 +300,34 @@ var require_dist = __commonJS({
|
|
|
299
300
|
}
|
|
300
301
|
return null;
|
|
301
302
|
}
|
|
302
|
-
function
|
|
303
|
+
function parse(version) {
|
|
304
|
+
const dashIdx = version.indexOf("-");
|
|
305
|
+
const base = dashIdx === -1 ? version : version.slice(0, dashIdx);
|
|
306
|
+
const prerelease = dashIdx === -1 ? null : version.slice(dashIdx + 1);
|
|
307
|
+
const nums = base.split(".").map((seg) => {
|
|
308
|
+
const n = Number.parseInt(seg, 10);
|
|
309
|
+
return Number.isNaN(n) ? 0 : n;
|
|
310
|
+
});
|
|
311
|
+
return { nums, prerelease };
|
|
312
|
+
}
|
|
313
|
+
function compareSemver(a, b) {
|
|
314
|
+
const pa = parse(a);
|
|
315
|
+
const pb = parse(b);
|
|
316
|
+
const len = Math.max(pa.nums.length, pb.nums.length);
|
|
317
|
+
for (let i = 0; i < len; i++) {
|
|
318
|
+
const na = pa.nums[i] ?? 0;
|
|
319
|
+
const nb = pb.nums[i] ?? 0;
|
|
320
|
+
if (na < nb) return -1;
|
|
321
|
+
if (na > nb) return 1;
|
|
322
|
+
}
|
|
323
|
+
if (pa.prerelease === null && pb.prerelease === null) return 0;
|
|
324
|
+
if (pa.prerelease === null) return 1;
|
|
325
|
+
if (pb.prerelease === null) return -1;
|
|
326
|
+
if (pa.prerelease < pb.prerelease) return -1;
|
|
327
|
+
if (pa.prerelease > pb.prerelease) return 1;
|
|
328
|
+
return 0;
|
|
329
|
+
}
|
|
330
|
+
function planBoot(state, isValidVersion, now, seedVersion = null) {
|
|
303
331
|
if (state === null) {
|
|
304
332
|
return { kind: "baked", reason: "no server-root state", stateToWrite: null };
|
|
305
333
|
}
|
|
@@ -345,6 +373,19 @@ var require_dist = __commonJS({
|
|
|
345
373
|
}
|
|
346
374
|
if (next.currentVersion !== null) {
|
|
347
375
|
if (isValidVersion(next.currentVersion)) {
|
|
376
|
+
if (!changed && seedVersion !== null && compareSemver(seedVersion, next.currentVersion) > 0) {
|
|
377
|
+
return {
|
|
378
|
+
kind: "baked",
|
|
379
|
+
reason: `baked seed ${seedVersion} is newer than active data-root ${next.currentVersion} \u2014 adopting the image seed`,
|
|
380
|
+
stateToWrite: {
|
|
381
|
+
...next,
|
|
382
|
+
currentVersion: null,
|
|
383
|
+
previousVersion: null,
|
|
384
|
+
pendingBoot: null,
|
|
385
|
+
rolledBack: null
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
}
|
|
348
389
|
return {
|
|
349
390
|
kind: "data-root",
|
|
350
391
|
version: next.currentVersion,
|
|
@@ -393,33 +434,6 @@ var require_dist = __commonJS({
|
|
|
393
434
|
stateToWrite: changed ? next : null
|
|
394
435
|
};
|
|
395
436
|
}
|
|
396
|
-
function parse(version) {
|
|
397
|
-
const dashIdx = version.indexOf("-");
|
|
398
|
-
const base = dashIdx === -1 ? version : version.slice(0, dashIdx);
|
|
399
|
-
const prerelease = dashIdx === -1 ? null : version.slice(dashIdx + 1);
|
|
400
|
-
const nums = base.split(".").map((seg) => {
|
|
401
|
-
const n = Number.parseInt(seg, 10);
|
|
402
|
-
return Number.isNaN(n) ? 0 : n;
|
|
403
|
-
});
|
|
404
|
-
return { nums, prerelease };
|
|
405
|
-
}
|
|
406
|
-
function compareSemver(a, b) {
|
|
407
|
-
const pa = parse(a);
|
|
408
|
-
const pb = parse(b);
|
|
409
|
-
const len = Math.max(pa.nums.length, pb.nums.length);
|
|
410
|
-
for (let i = 0; i < len; i++) {
|
|
411
|
-
const na = pa.nums[i] ?? 0;
|
|
412
|
-
const nb = pb.nums[i] ?? 0;
|
|
413
|
-
if (na < nb) return -1;
|
|
414
|
-
if (na > nb) return 1;
|
|
415
|
-
}
|
|
416
|
-
if (pa.prerelease === null && pb.prerelease === null) return 0;
|
|
417
|
-
if (pa.prerelease === null) return 1;
|
|
418
|
-
if (pb.prerelease === null) return -1;
|
|
419
|
-
if (pa.prerelease < pb.prerelease) return -1;
|
|
420
|
-
if (pa.prerelease > pb.prerelease) return 1;
|
|
421
|
-
return 0;
|
|
422
|
-
}
|
|
423
437
|
var fs32 = __toESM2(require("fs"));
|
|
424
438
|
var path32 = __toESM2(require("path"));
|
|
425
439
|
function detectWorkspaceRoot(fromDir) {
|
|
@@ -438,6 +452,7 @@ var require_dist = __commonJS({
|
|
|
438
452
|
dir = parent;
|
|
439
453
|
}
|
|
440
454
|
}
|
|
455
|
+
var fs42 = __toESM2(require("fs"));
|
|
441
456
|
var path42 = __toESM2(require("path"));
|
|
442
457
|
var import_node_url = require("url");
|
|
443
458
|
var HOST_EXTERNAL_SPECIFIERS = [
|
|
@@ -481,6 +496,19 @@ var require_dist = __commonJS({
|
|
|
481
496
|
};
|
|
482
497
|
registerHooks(hooks);
|
|
483
498
|
}
|
|
499
|
+
function readSeedVersion(seedEntry) {
|
|
500
|
+
try {
|
|
501
|
+
const pkgJsonPath = path42.join(path42.dirname(seedEntry), "..", "package.json");
|
|
502
|
+
const raw = JSON.parse(fs42.readFileSync(pkgJsonPath, "utf-8"));
|
|
503
|
+
if (typeof raw === "object" && raw !== null) {
|
|
504
|
+
const version = raw["version"];
|
|
505
|
+
if (typeof version === "string") return version;
|
|
506
|
+
}
|
|
507
|
+
return null;
|
|
508
|
+
} catch {
|
|
509
|
+
return null;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
484
512
|
function runNodeStarter(options) {
|
|
485
513
|
const env = options.env ?? process.env;
|
|
486
514
|
const now = options.now ?? Date.now;
|
|
@@ -509,7 +537,8 @@ var require_dist = __commonJS({
|
|
|
509
537
|
if (reason !== null) console.warn(`[starter] version ${version} invalid: ${reason}`);
|
|
510
538
|
return reason === null;
|
|
511
539
|
};
|
|
512
|
-
const
|
|
540
|
+
const seedVersion = readSeedVersion(options.seedEntry);
|
|
541
|
+
const plan = planBoot(state, isValidVersion, now, seedVersion);
|
|
513
542
|
if (plan.stateToWrite !== null) {
|
|
514
543
|
try {
|
|
515
544
|
writeServerRootState(rootDir, plan.stateToWrite);
|
|
@@ -544,7 +573,7 @@ var require_dist = __commonJS({
|
|
|
544
573
|
options.loadEntry(options.seedEntry);
|
|
545
574
|
}
|
|
546
575
|
var import_node_child_process = require("child_process");
|
|
547
|
-
var
|
|
576
|
+
var fs52 = __toESM2(require("fs"));
|
|
548
577
|
var path52 = __toESM2(require("path"));
|
|
549
578
|
var import_node_util = require("util");
|
|
550
579
|
var execFileAsync = (0, import_node_util.promisify)(import_node_child_process.execFile);
|
|
@@ -557,7 +586,7 @@ var require_dist = __commonJS({
|
|
|
557
586
|
var RESTART_REASON_PREFIX = "server-update";
|
|
558
587
|
function readPackageVersion(pkgJsonPath) {
|
|
559
588
|
try {
|
|
560
|
-
const raw = JSON.parse(
|
|
589
|
+
const raw = JSON.parse(fs52.readFileSync(pkgJsonPath, "utf-8"));
|
|
561
590
|
if (typeof raw === "object" && raw !== null) {
|
|
562
591
|
const version = raw["version"];
|
|
563
592
|
if (typeof version === "string") return version;
|
|
@@ -631,7 +660,7 @@ var require_dist = __commonJS({
|
|
|
631
660
|
const rootDir = this.rootDir();
|
|
632
661
|
const raw = readServerRootState(rootDir);
|
|
633
662
|
if (raw !== null) return { state: raw, corrupt: false };
|
|
634
|
-
return { state: emptyServerRootState(), corrupt:
|
|
663
|
+
return { state: emptyServerRootState(), corrupt: fs52.existsSync(stateFilePath(rootDir)) };
|
|
635
664
|
}
|
|
636
665
|
updateState(state) {
|
|
637
666
|
if (this.inFlight === "checking") return "checking";
|
|
@@ -773,7 +802,7 @@ var require_dist = __commonJS({
|
|
|
773
802
|
}
|
|
774
803
|
if (isDevChannelVersion(target)) {
|
|
775
804
|
const uploadsDir = devUploadVersionDir(this.rootDir(), target);
|
|
776
|
-
if (!
|
|
805
|
+
if (!fs52.existsSync(uploadsDir)) {
|
|
777
806
|
return {
|
|
778
807
|
accepted: false,
|
|
779
808
|
targetVersion: target,
|
|
@@ -828,15 +857,15 @@ var require_dist = __commonJS({
|
|
|
828
857
|
async stageAndActivate(target) {
|
|
829
858
|
const rootDir = this.rootDir();
|
|
830
859
|
const vDir = versionsDir(rootDir);
|
|
831
|
-
|
|
860
|
+
fs52.mkdirSync(vDir, { recursive: true });
|
|
832
861
|
const stagingDir = path52.join(vDir, `.staging-${target}-${process.pid}-${this.now()}`);
|
|
833
|
-
|
|
862
|
+
fs52.mkdirSync(stagingDir, { recursive: true });
|
|
834
863
|
try {
|
|
835
864
|
const devDir = devUploadVersionDir(rootDir, target);
|
|
836
865
|
const registry = this.env["CAMSTACK_NPM_REGISTRY"];
|
|
837
866
|
const installArgs = ["install", "--omit=dev", "--no-audit", "--no-fund", "--loglevel=error"];
|
|
838
|
-
if (
|
|
839
|
-
|
|
867
|
+
if (fs52.existsSync(devDir)) {
|
|
868
|
+
fs52.writeFileSync(
|
|
840
869
|
path52.join(stagingDir, "package.json"),
|
|
841
870
|
JSON.stringify(this.buildDevUploadsPackageJson(devDir, target), null, 2),
|
|
842
871
|
"utf-8"
|
|
@@ -846,7 +875,7 @@ var require_dist = __commonJS({
|
|
|
846
875
|
timeoutMs: NPM_INSTALL_TIMEOUT_MS
|
|
847
876
|
});
|
|
848
877
|
} else {
|
|
849
|
-
|
|
878
|
+
fs52.writeFileSync(
|
|
850
879
|
path52.join(stagingDir, "package.json"),
|
|
851
880
|
JSON.stringify({ name: "camstack-node-root", private: true }, null, 2),
|
|
852
881
|
"utf-8"
|
|
@@ -857,7 +886,7 @@ var require_dist = __commonJS({
|
|
|
857
886
|
);
|
|
858
887
|
}
|
|
859
888
|
const entry = rootEntryPath(stagingDir, this.spec);
|
|
860
|
-
if (!
|
|
889
|
+
if (!fs52.existsSync(entry)) {
|
|
861
890
|
throw new Error(`staged closure is missing the root entry (${entry})`);
|
|
862
891
|
}
|
|
863
892
|
const stagedVersion = readPackageVersion(
|
|
@@ -869,14 +898,14 @@ var require_dist = __commonJS({
|
|
|
869
898
|
);
|
|
870
899
|
}
|
|
871
900
|
const dest = versionDir(rootDir, target);
|
|
872
|
-
if (
|
|
901
|
+
if (fs52.existsSync(dest)) {
|
|
873
902
|
const aside = `${dest}.evicted-${this.now()}`;
|
|
874
|
-
await
|
|
875
|
-
await
|
|
903
|
+
await fs52.promises.rename(dest, aside);
|
|
904
|
+
await fs52.promises.rm(aside, { recursive: true, force: true }).catch(() => void 0);
|
|
876
905
|
}
|
|
877
|
-
await
|
|
906
|
+
await fs52.promises.rename(stagingDir, dest);
|
|
878
907
|
} catch (err) {
|
|
879
|
-
await
|
|
908
|
+
await fs52.promises.rm(stagingDir, { recursive: true, force: true }).catch(() => void 0);
|
|
880
909
|
throw err;
|
|
881
910
|
}
|
|
882
911
|
}
|
|
@@ -907,7 +936,7 @@ var require_dist = __commonJS({
|
|
|
907
936
|
}
|
|
908
937
|
const fileRef = (filename) => {
|
|
909
938
|
const abs = path52.join(devDir, filename);
|
|
910
|
-
if (!
|
|
939
|
+
if (!fs52.existsSync(abs)) {
|
|
911
940
|
throw new Error(`dev-uploads tarball listed in the manifest is missing: ${abs}`);
|
|
912
941
|
}
|
|
913
942
|
return `file:${abs}`;
|
|
@@ -1077,7 +1106,7 @@ var require_dist = __commonJS({
|
|
|
1077
1106
|
const vDir = versionsDir(this.rootDir());
|
|
1078
1107
|
let entries;
|
|
1079
1108
|
try {
|
|
1080
|
-
entries =
|
|
1109
|
+
entries = fs52.readdirSync(vDir);
|
|
1081
1110
|
} catch {
|
|
1082
1111
|
return;
|
|
1083
1112
|
}
|
|
@@ -1086,14 +1115,14 @@ var require_dist = __commonJS({
|
|
|
1086
1115
|
const full = path52.join(vDir, entry);
|
|
1087
1116
|
if (entry.startsWith(".")) {
|
|
1088
1117
|
try {
|
|
1089
|
-
const ageMs = this.now() -
|
|
1118
|
+
const ageMs = this.now() - fs52.statSync(full).mtimeMs;
|
|
1090
1119
|
if (ageMs < _RootUpdateService.STALE_TRANSIENT_MS) continue;
|
|
1091
1120
|
} catch {
|
|
1092
1121
|
continue;
|
|
1093
1122
|
}
|
|
1094
1123
|
}
|
|
1095
1124
|
try {
|
|
1096
|
-
|
|
1125
|
+
fs52.rmSync(full, { recursive: true, force: true });
|
|
1097
1126
|
this.logger.debug("pruned server-root version dir", { meta: { entry } });
|
|
1098
1127
|
} catch (err) {
|
|
1099
1128
|
this.logger.warn("failed to prune server-root version dir", {
|
|
@@ -1114,15 +1143,15 @@ var require_dist = __commonJS({
|
|
|
1114
1143
|
const dir = devUploadsDir(this.rootDir());
|
|
1115
1144
|
let entries;
|
|
1116
1145
|
try {
|
|
1117
|
-
entries =
|
|
1146
|
+
entries = fs52.readdirSync(dir);
|
|
1118
1147
|
} catch {
|
|
1119
1148
|
return;
|
|
1120
1149
|
}
|
|
1121
1150
|
const graveyard = path52.join(dir, ".sweeping");
|
|
1122
1151
|
try {
|
|
1123
|
-
for (const residue of
|
|
1152
|
+
for (const residue of fs52.readdirSync(graveyard)) {
|
|
1124
1153
|
try {
|
|
1125
|
-
|
|
1154
|
+
fs52.rmSync(path52.join(graveyard, residue), { recursive: true, force: true });
|
|
1126
1155
|
} catch {
|
|
1127
1156
|
}
|
|
1128
1157
|
}
|
|
@@ -1134,11 +1163,11 @@ var require_dist = __commonJS({
|
|
|
1134
1163
|
);
|
|
1135
1164
|
const doomed = byNewestFirst.slice(keepCount);
|
|
1136
1165
|
if (doomed.length === 0) return;
|
|
1137
|
-
|
|
1166
|
+
fs52.mkdirSync(graveyard, { recursive: true });
|
|
1138
1167
|
for (const entry of doomed) {
|
|
1139
1168
|
const aside = path52.join(graveyard, `${entry}-${this.now()}`);
|
|
1140
1169
|
try {
|
|
1141
|
-
|
|
1170
|
+
fs52.renameSync(path52.join(dir, entry), aside);
|
|
1142
1171
|
} catch (err) {
|
|
1143
1172
|
this.logger.warn("failed to move dev-uploads entry aside for sweep", {
|
|
1144
1173
|
meta: { entry, error: err instanceof Error ? err.message : String(err) }
|
|
@@ -1146,7 +1175,7 @@ var require_dist = __commonJS({
|
|
|
1146
1175
|
continue;
|
|
1147
1176
|
}
|
|
1148
1177
|
try {
|
|
1149
|
-
|
|
1178
|
+
fs52.rmSync(aside, { recursive: true, force: true });
|
|
1150
1179
|
this.logger.debug("swept dev-uploads entry", { meta: { entry } });
|
|
1151
1180
|
} catch {
|
|
1152
1181
|
}
|