@contextecf/guardian-cli 0.1.1 → 0.1.2

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.
@@ -16275,7 +16275,7 @@ function cloneList(values) {
16275
16275
  }
16276
16276
 
16277
16277
  // packages/guardian-cli/src/runtime.ts
16278
- var GUARDIAN_CLI_VERSION = "0.1.1";
16278
+ var GUARDIAN_CLI_VERSION = "0.1.2";
16279
16279
  var GUARDIAN_PROFILE_SCHEMA_VERSION = "contextecf/project-guardian-profile/v1";
16280
16280
  var GUARDIAN_NPM_PACKAGE_NAME = "@contextecf/guardian-cli";
16281
16281
  var GUARDIAN_GLOBAL_INSTALL_COMMAND = `npm install -g ${GUARDIAN_NPM_PACKAGE_NAME}`;
@@ -17436,7 +17436,7 @@ async function runStartCommand(flags, options) {
17436
17436
  const home = resolveGuardianHome(options.env, options.platform);
17437
17437
  const profile = await readProfile(home);
17438
17438
  if (!profile) {
17439
- write(stderr, "Guardian is not installed. Run guardian install first.\n");
17439
+ write(stderr, "Guardian is not installed. Run guardian setup first.\n");
17440
17440
  return 1;
17441
17441
  }
17442
17442
  const host = stringFlag(flags, "host") ?? "127.0.0.1";
@@ -17444,10 +17444,8 @@ async function runStartCommand(flags, options) {
17444
17444
  write(stderr, "Guardian start only accepts loopback hosts: 127.0.0.1, localhost, or ::1.\n");
17445
17445
  return 1;
17446
17446
  }
17447
- const port = numberFlag(flags, "port") ?? 4317;
17448
- const requestedDaemonUrl = formatDaemonBaseUrl(host, port);
17449
- const requestedControlTowerUrl = `${requestedDaemonUrl}/control-tower`;
17450
- const controlTowerSource = host === "127.0.0.1" && port === 4317 ? "default_loopback" : "env_or_flag";
17447
+ const explicitPort = numberFlag(flags, "port");
17448
+ const port = explicitPort ?? 4317;
17451
17449
  let token;
17452
17450
  try {
17453
17451
  token = await readRuntimeToken(home);
@@ -17459,14 +17457,66 @@ async function runStartCommand(flags, options) {
17459
17457
  );
17460
17458
  return 1;
17461
17459
  }
17462
- const healthUrl = resolveDaemonHealthUrl(requestedControlTowerUrl);
17463
- if (!healthUrl.ok) {
17464
- write(stderr, `${healthUrl.error}
17460
+ const healthChecker = options.healthDaemon ?? requestGuardianDaemonHealth;
17461
+ const candidates = explicitPort ? [explicitPort] : Array.from({ length: 8 }, (_, index) => port + index);
17462
+ let selected;
17463
+ let firstTokenMismatch;
17464
+ for (const candidatePort of candidates) {
17465
+ const requestedDaemonUrl2 = formatDaemonBaseUrl(host, candidatePort);
17466
+ const requestedControlTowerUrl2 = `${requestedDaemonUrl2}/control-tower`;
17467
+ const controlTowerSource2 = host === "127.0.0.1" && candidatePort === 4317 ? "default_loopback" : "env_or_flag";
17468
+ const healthUrl2 = resolveDaemonHealthUrl(requestedControlTowerUrl2);
17469
+ if (!healthUrl2.ok) {
17470
+ write(stderr, `${healthUrl2.error}
17465
17471
  `);
17472
+ return 1;
17473
+ }
17474
+ const existing2 = await healthChecker({ url: healthUrl2.url, token });
17475
+ if (existing2.ok && existing2.reachable) {
17476
+ selected = {
17477
+ port: candidatePort,
17478
+ requestedDaemonUrl: requestedDaemonUrl2,
17479
+ requestedControlTowerUrl: requestedControlTowerUrl2,
17480
+ healthUrl: healthUrl2.url,
17481
+ controlTowerSource: controlTowerSource2,
17482
+ existing: existing2
17483
+ };
17484
+ break;
17485
+ }
17486
+ if (existing2.statusCode === 401) {
17487
+ firstTokenMismatch ??= {
17488
+ requestedDaemonUrl: requestedDaemonUrl2,
17489
+ port: candidatePort,
17490
+ healthUrl: healthUrl2.url,
17491
+ existing: existing2
17492
+ };
17493
+ if (explicitPort) {
17494
+ write(stderr, renderDaemonTokenMismatchMessage(requestedDaemonUrl2, candidatePort));
17495
+ return 1;
17496
+ }
17497
+ continue;
17498
+ }
17499
+ selected = {
17500
+ port: candidatePort,
17501
+ requestedDaemonUrl: requestedDaemonUrl2,
17502
+ requestedControlTowerUrl: requestedControlTowerUrl2,
17503
+ healthUrl: healthUrl2.url,
17504
+ controlTowerSource: controlTowerSource2,
17505
+ existing: existing2
17506
+ };
17507
+ break;
17508
+ }
17509
+ if (!selected) {
17510
+ const mismatch = firstTokenMismatch ?? {
17511
+ requestedDaemonUrl: formatDaemonBaseUrl(host, port),
17512
+ port,
17513
+ healthUrl: `${formatDaemonBaseUrl(host, port)}/v1/guardian/admin/health`,
17514
+ existing: { ok: false, reachable: false, statusCode: 401, error: "unauthorized" }
17515
+ };
17516
+ write(stderr, renderDaemonTokenMismatchMessage(mismatch.requestedDaemonUrl, mismatch.port));
17466
17517
  return 1;
17467
17518
  }
17468
- const healthChecker = options.healthDaemon ?? requestGuardianDaemonHealth;
17469
- const existing = await healthChecker({ url: healthUrl.url, token });
17519
+ const { requestedDaemonUrl, requestedControlTowerUrl, healthUrl, controlTowerSource, existing } = selected;
17470
17520
  if (existing.ok && existing.reachable) {
17471
17521
  profile.runtime.daemon_status = "start_requested";
17472
17522
  profile.control_tower = {
@@ -17480,7 +17530,7 @@ async function runStartCommand(flags, options) {
17480
17530
  daemonStatus: profile.runtime.daemon_status,
17481
17531
  daemonUrl: requestedDaemonUrl,
17482
17532
  controlTowerUrl: requestedControlTowerUrl,
17483
- healthUrl: healthUrl.url,
17533
+ healthUrl,
17484
17534
  healthStatus: "reachable",
17485
17535
  nextCommands: ["guardian open", "guardian status", "guardian daemon pair --json"]
17486
17536
  };
@@ -17497,20 +17547,12 @@ async function runStartCommand(flags, options) {
17497
17547
  );
17498
17548
  return 0;
17499
17549
  }
17500
- if (existing.statusCode === 401) {
17501
- write(
17502
- stderr,
17503
- `Guardian daemon at ${requestedDaemonUrl} rejected the local runtime token. Run guardian status or guardian stop before starting another daemon.
17504
- `
17505
- );
17506
- return 1;
17507
- }
17508
17550
  if (!options.startDetachedDaemon) {
17509
17551
  write(stderr, "Guardian detached daemon launcher is unavailable in this runtime.\n");
17510
17552
  return 1;
17511
17553
  }
17512
- const started = await options.startDetachedDaemon({ home, host, port });
17513
- const daemonUrl = normalizeDaemonBaseUrl(started.url, host, port);
17554
+ const started = await options.startDetachedDaemon({ home, host, port: selected.port });
17555
+ const daemonUrl = normalizeDaemonBaseUrl(started.url, host, selected.port);
17514
17556
  const controlTowerUrl = `${daemonUrl}/control-tower`;
17515
17557
  profile.runtime.daemon_status = "start_requested";
17516
17558
  profile.control_tower = {
@@ -17525,7 +17567,7 @@ async function runStartCommand(flags, options) {
17525
17567
  daemonUrl,
17526
17568
  controlTowerUrl,
17527
17569
  pid: started.pid,
17528
- healthUrl: healthUrl.url,
17570
+ healthUrl,
17529
17571
  healthStatus: existing.error ? "unreachable" : "not_reachable",
17530
17572
  nextCommands: ["guardian open", "guardian status", "guardian daemon pair --json"]
17531
17573
  };
@@ -17543,6 +17585,15 @@ async function runStartCommand(flags, options) {
17543
17585
  );
17544
17586
  return 0;
17545
17587
  }
17588
+ function renderDaemonTokenMismatchMessage(requestedDaemonUrl, port) {
17589
+ return [
17590
+ `Guardian found another daemon or container at ${requestedDaemonUrl}, but it rejected this profile's local runtime token.`,
17591
+ "This usually means an older Guardian daemon or Docker demo is still using the port.",
17592
+ `Recovery: stop the other process/container, or run Guardian on a different port with guardian launch --port=${port + 1}.`,
17593
+ `Diagnostics: guardian status; docker ps --filter publish=${port}`,
17594
+ ""
17595
+ ].join("\n");
17596
+ }
17546
17597
  async function runStopCommand(flags, options) {
17547
17598
  const stdout = options.stdout ?? process.stdout;
17548
17599
  const stderr = options.stderr ?? process.stderr;
@@ -1,7 +1,7 @@
1
1
  import type { Writable } from 'node:stream';
2
2
  import { type PolicyPackMarketplaceManifest } from '@contextecf/personal-fabric-contracts';
3
3
  import { SQLitePersonalFabricStore, type PersonalFabricDataImportResult, type PersonalFabricMutableDataDeleteResult, type SQLitePersonalFabricBackupResult } from '@contextecf/personal-fabric-store';
4
- export declare const GUARDIAN_CLI_VERSION = "0.1.1";
4
+ export declare const GUARDIAN_CLI_VERSION = "0.1.2";
5
5
  export declare const GUARDIAN_PROFILE_SCHEMA_VERSION = "contextecf/project-guardian-profile/v1";
6
6
  export declare const GUARDIAN_NPM_PACKAGE_NAME = "@contextecf/guardian-cli";
7
7
  export declare const GUARDIAN_GLOBAL_INSTALL_COMMAND = "npm install -g @contextecf/guardian-cli";
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@contextecf/guardian-cli",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Project Guardian local-first Personal Context Fabric CLI",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
7
7
  "main": "dist/packages/guardian-cli/src/index.js",
8
8
  "types": "dist/packages/guardian-cli/src/index.d.ts",
9
9
  "engines": {
10
- "node": ">=22"
10
+ "node": ">=20.20.0"
11
11
  },
12
12
  "files": [
13
13
  "dist/packages/guardian-cli/src/bin.d.ts",