@camstack/agent 1.1.49 → 1.1.51

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/cli.js CHANGED
@@ -84,6 +84,7 @@ var require_dist = __commonJS({
84
84
  planBoot: () => planBoot,
85
85
  readDevUploadManifest: () => readDevUploadManifest,
86
86
  readRestartIntentMarker: () => readRestartIntentMarker,
87
+ readSeedVersion: () => readSeedVersion,
87
88
  readServerRootState: () => readServerRootState,
88
89
  registerActiveRootResolver: () => registerActiveRootResolver,
89
90
  restartIntentMarkerPath: () => restartIntentMarkerPath,
@@ -295,7 +296,34 @@ var require_dist = __commonJS({
295
296
  }
296
297
  return null;
297
298
  }
298
- function planBoot(state, isValidVersion, now) {
299
+ function parse(version) {
300
+ const dashIdx = version.indexOf("-");
301
+ const base = dashIdx === -1 ? version : version.slice(0, dashIdx);
302
+ const prerelease = dashIdx === -1 ? null : version.slice(dashIdx + 1);
303
+ const nums = base.split(".").map((seg) => {
304
+ const n = Number.parseInt(seg, 10);
305
+ return Number.isNaN(n) ? 0 : n;
306
+ });
307
+ return { nums, prerelease };
308
+ }
309
+ function compareSemver(a, b) {
310
+ const pa = parse(a);
311
+ const pb = parse(b);
312
+ const len = Math.max(pa.nums.length, pb.nums.length);
313
+ for (let i = 0; i < len; i++) {
314
+ const na = pa.nums[i] ?? 0;
315
+ const nb = pb.nums[i] ?? 0;
316
+ if (na < nb) return -1;
317
+ if (na > nb) return 1;
318
+ }
319
+ if (pa.prerelease === null && pb.prerelease === null) return 0;
320
+ if (pa.prerelease === null) return 1;
321
+ if (pb.prerelease === null) return -1;
322
+ if (pa.prerelease < pb.prerelease) return -1;
323
+ if (pa.prerelease > pb.prerelease) return 1;
324
+ return 0;
325
+ }
326
+ function planBoot(state, isValidVersion, now, seedVersion = null) {
299
327
  if (state === null) {
300
328
  return { kind: "baked", reason: "no server-root state", stateToWrite: null };
301
329
  }
@@ -341,6 +369,19 @@ var require_dist = __commonJS({
341
369
  }
342
370
  if (next.currentVersion !== null) {
343
371
  if (isValidVersion(next.currentVersion)) {
372
+ if (!changed && seedVersion !== null && compareSemver(seedVersion, next.currentVersion) > 0) {
373
+ return {
374
+ kind: "baked",
375
+ reason: `baked seed ${seedVersion} is newer than active data-root ${next.currentVersion} \u2014 adopting the image seed`,
376
+ stateToWrite: {
377
+ ...next,
378
+ currentVersion: null,
379
+ previousVersion: null,
380
+ pendingBoot: null,
381
+ rolledBack: null
382
+ }
383
+ };
384
+ }
344
385
  return {
345
386
  kind: "data-root",
346
387
  version: next.currentVersion,
@@ -389,33 +430,6 @@ var require_dist = __commonJS({
389
430
  stateToWrite: changed ? next : null
390
431
  };
391
432
  }
392
- function parse(version) {
393
- const dashIdx = version.indexOf("-");
394
- const base = dashIdx === -1 ? version : version.slice(0, dashIdx);
395
- const prerelease = dashIdx === -1 ? null : version.slice(dashIdx + 1);
396
- const nums = base.split(".").map((seg) => {
397
- const n = Number.parseInt(seg, 10);
398
- return Number.isNaN(n) ? 0 : n;
399
- });
400
- return { nums, prerelease };
401
- }
402
- function compareSemver(a, b) {
403
- const pa = parse(a);
404
- const pb = parse(b);
405
- const len = Math.max(pa.nums.length, pb.nums.length);
406
- for (let i = 0; i < len; i++) {
407
- const na = pa.nums[i] ?? 0;
408
- const nb = pb.nums[i] ?? 0;
409
- if (na < nb) return -1;
410
- if (na > nb) return 1;
411
- }
412
- if (pa.prerelease === null && pb.prerelease === null) return 0;
413
- if (pa.prerelease === null) return 1;
414
- if (pb.prerelease === null) return -1;
415
- if (pa.prerelease < pb.prerelease) return -1;
416
- if (pa.prerelease > pb.prerelease) return 1;
417
- return 0;
418
- }
419
433
  var fs32 = __toESM2(require("fs"));
420
434
  var path32 = __toESM2(require("path"));
421
435
  function detectWorkspaceRoot(fromDir) {
@@ -434,6 +448,7 @@ var require_dist = __commonJS({
434
448
  dir = parent;
435
449
  }
436
450
  }
451
+ var fs42 = __toESM2(require("fs"));
437
452
  var path42 = __toESM2(require("path"));
438
453
  var import_node_url = require("url");
439
454
  var HOST_EXTERNAL_SPECIFIERS = [
@@ -477,6 +492,19 @@ var require_dist = __commonJS({
477
492
  };
478
493
  registerHooks(hooks);
479
494
  }
495
+ function readSeedVersion(seedEntry) {
496
+ try {
497
+ const pkgJsonPath = path42.join(path42.dirname(seedEntry), "..", "package.json");
498
+ const raw = JSON.parse(fs42.readFileSync(pkgJsonPath, "utf-8"));
499
+ if (typeof raw === "object" && raw !== null) {
500
+ const version = raw["version"];
501
+ if (typeof version === "string") return version;
502
+ }
503
+ return null;
504
+ } catch {
505
+ return null;
506
+ }
507
+ }
480
508
  function runNodeStarter(options) {
481
509
  const env = options.env ?? process.env;
482
510
  const now = options.now ?? Date.now;
@@ -505,7 +533,8 @@ var require_dist = __commonJS({
505
533
  if (reason !== null) console.warn(`[starter] version ${version} invalid: ${reason}`);
506
534
  return reason === null;
507
535
  };
508
- const plan = planBoot(state, isValidVersion, now);
536
+ const seedVersion = readSeedVersion(options.seedEntry);
537
+ const plan = planBoot(state, isValidVersion, now, seedVersion);
509
538
  if (plan.stateToWrite !== null) {
510
539
  try {
511
540
  writeServerRootState(rootDir, plan.stateToWrite);
@@ -540,7 +569,7 @@ var require_dist = __commonJS({
540
569
  options.loadEntry(options.seedEntry);
541
570
  }
542
571
  var import_node_child_process = require("child_process");
543
- var fs42 = __toESM2(require("fs"));
572
+ var fs52 = __toESM2(require("fs"));
544
573
  var path52 = __toESM2(require("path"));
545
574
  var import_node_util = require("util");
546
575
  var execFileAsync = (0, import_node_util.promisify)(import_node_child_process.execFile);
@@ -553,7 +582,7 @@ var require_dist = __commonJS({
553
582
  var RESTART_REASON_PREFIX = "server-update";
554
583
  function readPackageVersion(pkgJsonPath) {
555
584
  try {
556
- const raw = JSON.parse(fs42.readFileSync(pkgJsonPath, "utf-8"));
585
+ const raw = JSON.parse(fs52.readFileSync(pkgJsonPath, "utf-8"));
557
586
  if (typeof raw === "object" && raw !== null) {
558
587
  const version = raw["version"];
559
588
  if (typeof version === "string") return version;
@@ -627,7 +656,7 @@ var require_dist = __commonJS({
627
656
  const rootDir = this.rootDir();
628
657
  const raw = readServerRootState(rootDir);
629
658
  if (raw !== null) return { state: raw, corrupt: false };
630
- return { state: emptyServerRootState(), corrupt: fs42.existsSync(stateFilePath(rootDir)) };
659
+ return { state: emptyServerRootState(), corrupt: fs52.existsSync(stateFilePath(rootDir)) };
631
660
  }
632
661
  updateState(state) {
633
662
  if (this.inFlight === "checking") return "checking";
@@ -769,7 +798,7 @@ var require_dist = __commonJS({
769
798
  }
770
799
  if (isDevChannelVersion(target)) {
771
800
  const uploadsDir = devUploadVersionDir(this.rootDir(), target);
772
- if (!fs42.existsSync(uploadsDir)) {
801
+ if (!fs52.existsSync(uploadsDir)) {
773
802
  return {
774
803
  accepted: false,
775
804
  targetVersion: target,
@@ -824,15 +853,15 @@ var require_dist = __commonJS({
824
853
  async stageAndActivate(target) {
825
854
  const rootDir = this.rootDir();
826
855
  const vDir = versionsDir(rootDir);
827
- fs42.mkdirSync(vDir, { recursive: true });
856
+ fs52.mkdirSync(vDir, { recursive: true });
828
857
  const stagingDir = path52.join(vDir, `.staging-${target}-${process.pid}-${this.now()}`);
829
- fs42.mkdirSync(stagingDir, { recursive: true });
858
+ fs52.mkdirSync(stagingDir, { recursive: true });
830
859
  try {
831
860
  const devDir = devUploadVersionDir(rootDir, target);
832
861
  const registry = this.env["CAMSTACK_NPM_REGISTRY"];
833
862
  const installArgs = ["install", "--omit=dev", "--no-audit", "--no-fund", "--loglevel=error"];
834
- if (fs42.existsSync(devDir)) {
835
- fs42.writeFileSync(
863
+ if (fs52.existsSync(devDir)) {
864
+ fs52.writeFileSync(
836
865
  path52.join(stagingDir, "package.json"),
837
866
  JSON.stringify(this.buildDevUploadsPackageJson(devDir, target), null, 2),
838
867
  "utf-8"
@@ -842,7 +871,7 @@ var require_dist = __commonJS({
842
871
  timeoutMs: NPM_INSTALL_TIMEOUT_MS
843
872
  });
844
873
  } else {
845
- fs42.writeFileSync(
874
+ fs52.writeFileSync(
846
875
  path52.join(stagingDir, "package.json"),
847
876
  JSON.stringify({ name: "camstack-node-root", private: true }, null, 2),
848
877
  "utf-8"
@@ -853,7 +882,7 @@ var require_dist = __commonJS({
853
882
  );
854
883
  }
855
884
  const entry = rootEntryPath(stagingDir, this.spec);
856
- if (!fs42.existsSync(entry)) {
885
+ if (!fs52.existsSync(entry)) {
857
886
  throw new Error(`staged closure is missing the root entry (${entry})`);
858
887
  }
859
888
  const stagedVersion = readPackageVersion(
@@ -865,14 +894,14 @@ var require_dist = __commonJS({
865
894
  );
866
895
  }
867
896
  const dest = versionDir(rootDir, target);
868
- if (fs42.existsSync(dest)) {
897
+ if (fs52.existsSync(dest)) {
869
898
  const aside = `${dest}.evicted-${this.now()}`;
870
- await fs42.promises.rename(dest, aside);
871
- await fs42.promises.rm(aside, { recursive: true, force: true }).catch(() => void 0);
899
+ await fs52.promises.rename(dest, aside);
900
+ await fs52.promises.rm(aside, { recursive: true, force: true }).catch(() => void 0);
872
901
  }
873
- await fs42.promises.rename(stagingDir, dest);
902
+ await fs52.promises.rename(stagingDir, dest);
874
903
  } catch (err) {
875
- await fs42.promises.rm(stagingDir, { recursive: true, force: true }).catch(() => void 0);
904
+ await fs52.promises.rm(stagingDir, { recursive: true, force: true }).catch(() => void 0);
876
905
  throw err;
877
906
  }
878
907
  }
@@ -903,7 +932,7 @@ var require_dist = __commonJS({
903
932
  }
904
933
  const fileRef = (filename) => {
905
934
  const abs = path52.join(devDir, filename);
906
- if (!fs42.existsSync(abs)) {
935
+ if (!fs52.existsSync(abs)) {
907
936
  throw new Error(`dev-uploads tarball listed in the manifest is missing: ${abs}`);
908
937
  }
909
938
  return `file:${abs}`;
@@ -1073,7 +1102,7 @@ var require_dist = __commonJS({
1073
1102
  const vDir = versionsDir(this.rootDir());
1074
1103
  let entries;
1075
1104
  try {
1076
- entries = fs42.readdirSync(vDir);
1105
+ entries = fs52.readdirSync(vDir);
1077
1106
  } catch {
1078
1107
  return;
1079
1108
  }
@@ -1082,14 +1111,14 @@ var require_dist = __commonJS({
1082
1111
  const full = path52.join(vDir, entry);
1083
1112
  if (entry.startsWith(".")) {
1084
1113
  try {
1085
- const ageMs = this.now() - fs42.statSync(full).mtimeMs;
1114
+ const ageMs = this.now() - fs52.statSync(full).mtimeMs;
1086
1115
  if (ageMs < _RootUpdateService.STALE_TRANSIENT_MS) continue;
1087
1116
  } catch {
1088
1117
  continue;
1089
1118
  }
1090
1119
  }
1091
1120
  try {
1092
- fs42.rmSync(full, { recursive: true, force: true });
1121
+ fs52.rmSync(full, { recursive: true, force: true });
1093
1122
  this.logger.debug("pruned server-root version dir", { meta: { entry } });
1094
1123
  } catch (err) {
1095
1124
  this.logger.warn("failed to prune server-root version dir", {
@@ -1110,15 +1139,15 @@ var require_dist = __commonJS({
1110
1139
  const dir = devUploadsDir(this.rootDir());
1111
1140
  let entries;
1112
1141
  try {
1113
- entries = fs42.readdirSync(dir);
1142
+ entries = fs52.readdirSync(dir);
1114
1143
  } catch {
1115
1144
  return;
1116
1145
  }
1117
1146
  const graveyard = path52.join(dir, ".sweeping");
1118
1147
  try {
1119
- for (const residue of fs42.readdirSync(graveyard)) {
1148
+ for (const residue of fs52.readdirSync(graveyard)) {
1120
1149
  try {
1121
- fs42.rmSync(path52.join(graveyard, residue), { recursive: true, force: true });
1150
+ fs52.rmSync(path52.join(graveyard, residue), { recursive: true, force: true });
1122
1151
  } catch {
1123
1152
  }
1124
1153
  }
@@ -1130,11 +1159,11 @@ var require_dist = __commonJS({
1130
1159
  );
1131
1160
  const doomed = byNewestFirst.slice(keepCount);
1132
1161
  if (doomed.length === 0) return;
1133
- fs42.mkdirSync(graveyard, { recursive: true });
1162
+ fs52.mkdirSync(graveyard, { recursive: true });
1134
1163
  for (const entry of doomed) {
1135
1164
  const aside = path52.join(graveyard, `${entry}-${this.now()}`);
1136
1165
  try {
1137
- fs42.renameSync(path52.join(dir, entry), aside);
1166
+ fs52.renameSync(path52.join(dir, entry), aside);
1138
1167
  } catch (err) {
1139
1168
  this.logger.warn("failed to move dev-uploads entry aside for sweep", {
1140
1169
  meta: { entry, error: err instanceof Error ? err.message : String(err) }
@@ -1142,7 +1171,7 @@ var require_dist = __commonJS({
1142
1171
  continue;
1143
1172
  }
1144
1173
  try {
1145
- fs42.rmSync(aside, { recursive: true, force: true });
1174
+ fs52.rmSync(aside, { recursive: true, force: true });
1146
1175
  this.logger.debug("swept dev-uploads entry", { meta: { entry } });
1147
1176
  } catch {
1148
1177
  }
@@ -1812,8 +1841,8 @@ function getLocalIps() {
1812
1841
  }
1813
1842
  async function withTimeout(p, ms, fallback) {
1814
1843
  let timer;
1815
- const timeout = new Promise((resolve7) => {
1816
- timer = setTimeout(() => resolve7(fallback), ms);
1844
+ const timeout = new Promise((resolve6) => {
1845
+ timer = setTimeout(() => resolve6(fallback), ms);
1817
1846
  });
1818
1847
  try {
1819
1848
  return await Promise.race([p, timeout]);
@@ -3301,23 +3330,35 @@ if (args.statusPort && !process.env["CAMSTACK_STATUS_PORT"]) {
3301
3330
  process.env["CAMSTACK_STATUS_PORT"] = args.statusPort;
3302
3331
  }
3303
3332
  if (!process.env["CAMSTACK_FRAMEWORK_DIR"]) {
3304
- const scriptPath = process.argv[1];
3305
- if (scriptPath) {
3306
- const frameworkDir = path8.resolve(path8.dirname(scriptPath), "..", "..");
3333
+ const isFrameworkDir = (dir) => (0, import_node_fs.existsSync)(path8.join(dir, "node_modules", "@camstack", "shm-ring")) && (0, import_node_fs.existsSync)(path8.join(dir, "node_modules", "@camstack", "system"));
3334
+ const discoverFrameworkDir = () => {
3335
+ const activeRoot = process.env["CAMSTACK_AGENT_ACTIVE_ROOT"];
3336
+ if (activeRoot && isFrameworkDir(activeRoot)) return activeRoot;
3337
+ const scriptPath = process.argv[1];
3338
+ if (!scriptPath) return null;
3339
+ let dir = path8.dirname(scriptPath);
3340
+ for (let depth = 0; depth < 8; depth++) {
3341
+ if (isFrameworkDir(dir)) return dir;
3342
+ const parent = path8.dirname(dir);
3343
+ if (parent === dir) break;
3344
+ dir = parent;
3345
+ }
3346
+ return null;
3347
+ };
3348
+ const frameworkDir = discoverFrameworkDir();
3349
+ if (frameworkDir) {
3307
3350
  const frameworkModules = path8.join(frameworkDir, "node_modules");
3308
- if ((0, import_node_fs.existsSync)(path8.join(frameworkModules, "@camstack", "shm-ring"))) {
3309
- process.env["CAMSTACK_FRAMEWORK_DIR"] = frameworkDir;
3310
- const existingNodePath = process.env["NODE_PATH"];
3311
- process.env["NODE_PATH"] = existingNodePath ? `${frameworkModules}${path8.delimiter}${existingNodePath}` : frameworkModules;
3312
- import_node_module.Module._initPaths();
3313
- console.log(
3314
- `[Agent] Self-contained framework detected \u2014 CAMSTACK_FRAMEWORK_DIR=${frameworkDir}`
3315
- );
3316
- if (!process.env["CAMSTACK_BUNDLED_ADDONS_DIR"]) {
3317
- const bundledAddons = path8.join(frameworkDir, "addons");
3318
- if ((0, import_node_fs.existsSync)(bundledAddons)) {
3319
- process.env["CAMSTACK_BUNDLED_ADDONS_DIR"] = bundledAddons;
3320
- }
3351
+ process.env["CAMSTACK_FRAMEWORK_DIR"] = frameworkDir;
3352
+ const existingNodePath = process.env["NODE_PATH"];
3353
+ process.env["NODE_PATH"] = existingNodePath ? `${frameworkModules}${path8.delimiter}${existingNodePath}` : frameworkModules;
3354
+ import_node_module.Module._initPaths();
3355
+ console.log(
3356
+ `[Agent] Self-contained framework detected \u2014 CAMSTACK_FRAMEWORK_DIR=${frameworkDir}`
3357
+ );
3358
+ if (!process.env["CAMSTACK_BUNDLED_ADDONS_DIR"]) {
3359
+ const bundledAddons = path8.join(frameworkDir, "addons");
3360
+ if ((0, import_node_fs.existsSync)(bundledAddons)) {
3361
+ process.env["CAMSTACK_BUNDLED_ADDONS_DIR"] = bundledAddons;
3321
3362
  }
3322
3363
  }
3323
3364
  }