@contextecf/guardian-cli 0.1.1 → 0.1.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.
|
@@ -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.
|
|
16278
|
+
var GUARDIAN_CLI_VERSION = "0.1.3";
|
|
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}`;
|
|
@@ -17286,6 +17286,15 @@ async function statusGuardian(flags, options) {
|
|
|
17286
17286
|
const releaseEvidence = await buildGuardianReleaseEvidenceStatus(home);
|
|
17287
17287
|
const serviceSupervision = await buildGuardianServiceSupervisionStatus(home);
|
|
17288
17288
|
const osKeyStorage = await buildGuardianOsKeyStorageStatus(home);
|
|
17289
|
+
const privacy = {
|
|
17290
|
+
rawContentCaptureEnabled: profile?.privacy.raw_content_capture_enabled ?? false,
|
|
17291
|
+
cloudSyncEnabled: profile?.privacy.cloud_sync_enabled ?? false,
|
|
17292
|
+
localAppAutopilotEnabled: profile?.privacy.local_app_autopilot_enabled ?? false
|
|
17293
|
+
};
|
|
17294
|
+
const nextCommands = buildGuardianStatusNextCommands({
|
|
17295
|
+
installed: profile !== void 0,
|
|
17296
|
+
daemonStatus: daemonHealth.daemon.status
|
|
17297
|
+
});
|
|
17289
17298
|
const result = {
|
|
17290
17299
|
schema_version: "contextecf/project-guardian-status/v1",
|
|
17291
17300
|
cli_version: GUARDIAN_CLI_VERSION,
|
|
@@ -17299,11 +17308,7 @@ async function statusGuardian(flags, options) {
|
|
|
17299
17308
|
controlTowerUrl: daemonHealth.controlTowerUrl,
|
|
17300
17309
|
controlTowerUrlSource: profile?.control_tower?.source ?? "default_loopback",
|
|
17301
17310
|
daemon: daemonHealth.daemon,
|
|
17302
|
-
privacy
|
|
17303
|
-
rawContentCaptureEnabled: profile?.privacy.raw_content_capture_enabled ?? false,
|
|
17304
|
-
cloudSyncEnabled: profile?.privacy.cloud_sync_enabled ?? false,
|
|
17305
|
-
localAppAutopilotEnabled: profile?.privacy.local_app_autopilot_enabled ?? false
|
|
17306
|
-
},
|
|
17311
|
+
privacy,
|
|
17307
17312
|
preferences: {
|
|
17308
17313
|
promptCoachMode: profile?.prompt_coach_mode ?? "not_installed",
|
|
17309
17314
|
learningGraphEnabled: profile?.learning_graph.enabled ?? false
|
|
@@ -17322,7 +17327,8 @@ async function statusGuardian(flags, options) {
|
|
|
17322
17327
|
releaseEvidence,
|
|
17323
17328
|
serviceSupervision,
|
|
17324
17329
|
osKeyStorage,
|
|
17325
|
-
notProvenProductionGates: GUARDIAN_NOT_PROVEN_PRODUCTION_GATES
|
|
17330
|
+
notProvenProductionGates: GUARDIAN_NOT_PROVEN_PRODUCTION_GATES,
|
|
17331
|
+
nextCommands
|
|
17326
17332
|
};
|
|
17327
17333
|
if (flags.has("json")) {
|
|
17328
17334
|
return `${JSON.stringify(result, null, 2)}
|
|
@@ -17345,11 +17351,36 @@ async function statusGuardian(flags, options) {
|
|
|
17345
17351
|
`Service supervision: ${result.serviceSupervision.status}`,
|
|
17346
17352
|
`OS key storage: ${result.osKeyStorage.status}`,
|
|
17347
17353
|
`Not-proven production gates: ${result.notProvenProductionGates.length}`,
|
|
17348
|
-
|
|
17349
|
-
|
|
17354
|
+
formatGuardianPrivacyStatus(result.privacy),
|
|
17355
|
+
`Next: ${result.nextCommands.join("; ")}`
|
|
17350
17356
|
].filter(Boolean).join("\n")}
|
|
17351
17357
|
`;
|
|
17352
17358
|
}
|
|
17359
|
+
function buildGuardianStatusNextCommands(input) {
|
|
17360
|
+
if (!input.installed) {
|
|
17361
|
+
return ["guardian install"];
|
|
17362
|
+
}
|
|
17363
|
+
if (input.daemonStatus === "reachable") {
|
|
17364
|
+
return ["guardian open", "guardian readiness", "guardian extension open-setup"];
|
|
17365
|
+
}
|
|
17366
|
+
if (input.daemonStatus === "unauthorized") {
|
|
17367
|
+
return ["guardian stop", "guardian launch --port=4322", "guardian status"];
|
|
17368
|
+
}
|
|
17369
|
+
if (input.daemonStatus === "token_missing" || input.daemonStatus === "invalid_control_tower_url") {
|
|
17370
|
+
return ["guardian setup", "guardian launch", "guardian status"];
|
|
17371
|
+
}
|
|
17372
|
+
return ["guardian launch", "guardian status"];
|
|
17373
|
+
}
|
|
17374
|
+
function formatGuardianPrivacyStatus(input) {
|
|
17375
|
+
return [
|
|
17376
|
+
`Privacy: raw capture ${formatOnOff(input.rawContentCaptureEnabled)}`,
|
|
17377
|
+
`cloud sync ${formatOnOff(input.cloudSyncEnabled)}`,
|
|
17378
|
+
`local app autopilot ${formatOnOff(input.localAppAutopilotEnabled)}`
|
|
17379
|
+
].join(", ");
|
|
17380
|
+
}
|
|
17381
|
+
function formatOnOff(enabled) {
|
|
17382
|
+
return enabled ? "on" : "off";
|
|
17383
|
+
}
|
|
17353
17384
|
async function runControlTowerOpenCommand(flags, options) {
|
|
17354
17385
|
const stdout = options.stdout ?? process.stdout;
|
|
17355
17386
|
const stderr = options.stderr ?? process.stderr;
|
|
@@ -17436,7 +17467,7 @@ async function runStartCommand(flags, options) {
|
|
|
17436
17467
|
const home = resolveGuardianHome(options.env, options.platform);
|
|
17437
17468
|
const profile = await readProfile(home);
|
|
17438
17469
|
if (!profile) {
|
|
17439
|
-
write(stderr, "Guardian is not installed. Run guardian
|
|
17470
|
+
write(stderr, "Guardian is not installed. Run guardian setup first.\n");
|
|
17440
17471
|
return 1;
|
|
17441
17472
|
}
|
|
17442
17473
|
const host = stringFlag(flags, "host") ?? "127.0.0.1";
|
|
@@ -17444,10 +17475,8 @@ async function runStartCommand(flags, options) {
|
|
|
17444
17475
|
write(stderr, "Guardian start only accepts loopback hosts: 127.0.0.1, localhost, or ::1.\n");
|
|
17445
17476
|
return 1;
|
|
17446
17477
|
}
|
|
17447
|
-
const
|
|
17448
|
-
const
|
|
17449
|
-
const requestedControlTowerUrl = `${requestedDaemonUrl}/control-tower`;
|
|
17450
|
-
const controlTowerSource = host === "127.0.0.1" && port === 4317 ? "default_loopback" : "env_or_flag";
|
|
17478
|
+
const explicitPort = numberFlag(flags, "port");
|
|
17479
|
+
const port = explicitPort ?? 4317;
|
|
17451
17480
|
let token;
|
|
17452
17481
|
try {
|
|
17453
17482
|
token = await readRuntimeToken(home);
|
|
@@ -17459,14 +17488,66 @@ async function runStartCommand(flags, options) {
|
|
|
17459
17488
|
);
|
|
17460
17489
|
return 1;
|
|
17461
17490
|
}
|
|
17462
|
-
const
|
|
17463
|
-
|
|
17464
|
-
|
|
17491
|
+
const healthChecker = options.healthDaemon ?? requestGuardianDaemonHealth;
|
|
17492
|
+
const candidates = explicitPort ? [explicitPort] : Array.from({ length: 8 }, (_, index) => port + index);
|
|
17493
|
+
let selected;
|
|
17494
|
+
let firstTokenMismatch;
|
|
17495
|
+
for (const candidatePort of candidates) {
|
|
17496
|
+
const requestedDaemonUrl2 = formatDaemonBaseUrl(host, candidatePort);
|
|
17497
|
+
const requestedControlTowerUrl2 = `${requestedDaemonUrl2}/control-tower`;
|
|
17498
|
+
const controlTowerSource2 = host === "127.0.0.1" && candidatePort === 4317 ? "default_loopback" : "env_or_flag";
|
|
17499
|
+
const healthUrl2 = resolveDaemonHealthUrl(requestedControlTowerUrl2);
|
|
17500
|
+
if (!healthUrl2.ok) {
|
|
17501
|
+
write(stderr, `${healthUrl2.error}
|
|
17465
17502
|
`);
|
|
17503
|
+
return 1;
|
|
17504
|
+
}
|
|
17505
|
+
const existing2 = await healthChecker({ url: healthUrl2.url, token });
|
|
17506
|
+
if (existing2.ok && existing2.reachable) {
|
|
17507
|
+
selected = {
|
|
17508
|
+
port: candidatePort,
|
|
17509
|
+
requestedDaemonUrl: requestedDaemonUrl2,
|
|
17510
|
+
requestedControlTowerUrl: requestedControlTowerUrl2,
|
|
17511
|
+
healthUrl: healthUrl2.url,
|
|
17512
|
+
controlTowerSource: controlTowerSource2,
|
|
17513
|
+
existing: existing2
|
|
17514
|
+
};
|
|
17515
|
+
break;
|
|
17516
|
+
}
|
|
17517
|
+
if (existing2.statusCode === 401) {
|
|
17518
|
+
firstTokenMismatch ??= {
|
|
17519
|
+
requestedDaemonUrl: requestedDaemonUrl2,
|
|
17520
|
+
port: candidatePort,
|
|
17521
|
+
healthUrl: healthUrl2.url,
|
|
17522
|
+
existing: existing2
|
|
17523
|
+
};
|
|
17524
|
+
if (explicitPort) {
|
|
17525
|
+
write(stderr, renderDaemonTokenMismatchMessage(requestedDaemonUrl2, candidatePort));
|
|
17526
|
+
return 1;
|
|
17527
|
+
}
|
|
17528
|
+
continue;
|
|
17529
|
+
}
|
|
17530
|
+
selected = {
|
|
17531
|
+
port: candidatePort,
|
|
17532
|
+
requestedDaemonUrl: requestedDaemonUrl2,
|
|
17533
|
+
requestedControlTowerUrl: requestedControlTowerUrl2,
|
|
17534
|
+
healthUrl: healthUrl2.url,
|
|
17535
|
+
controlTowerSource: controlTowerSource2,
|
|
17536
|
+
existing: existing2
|
|
17537
|
+
};
|
|
17538
|
+
break;
|
|
17539
|
+
}
|
|
17540
|
+
if (!selected) {
|
|
17541
|
+
const mismatch = firstTokenMismatch ?? {
|
|
17542
|
+
requestedDaemonUrl: formatDaemonBaseUrl(host, port),
|
|
17543
|
+
port,
|
|
17544
|
+
healthUrl: `${formatDaemonBaseUrl(host, port)}/v1/guardian/admin/health`,
|
|
17545
|
+
existing: { ok: false, reachable: false, statusCode: 401, error: "unauthorized" }
|
|
17546
|
+
};
|
|
17547
|
+
write(stderr, renderDaemonTokenMismatchMessage(mismatch.requestedDaemonUrl, mismatch.port));
|
|
17466
17548
|
return 1;
|
|
17467
17549
|
}
|
|
17468
|
-
const
|
|
17469
|
-
const existing = await healthChecker({ url: healthUrl.url, token });
|
|
17550
|
+
const { requestedDaemonUrl, requestedControlTowerUrl, healthUrl, controlTowerSource, existing } = selected;
|
|
17470
17551
|
if (existing.ok && existing.reachable) {
|
|
17471
17552
|
profile.runtime.daemon_status = "start_requested";
|
|
17472
17553
|
profile.control_tower = {
|
|
@@ -17480,7 +17561,7 @@ async function runStartCommand(flags, options) {
|
|
|
17480
17561
|
daemonStatus: profile.runtime.daemon_status,
|
|
17481
17562
|
daemonUrl: requestedDaemonUrl,
|
|
17482
17563
|
controlTowerUrl: requestedControlTowerUrl,
|
|
17483
|
-
healthUrl
|
|
17564
|
+
healthUrl,
|
|
17484
17565
|
healthStatus: "reachable",
|
|
17485
17566
|
nextCommands: ["guardian open", "guardian status", "guardian daemon pair --json"]
|
|
17486
17567
|
};
|
|
@@ -17497,20 +17578,12 @@ async function runStartCommand(flags, options) {
|
|
|
17497
17578
|
);
|
|
17498
17579
|
return 0;
|
|
17499
17580
|
}
|
|
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
17581
|
if (!options.startDetachedDaemon) {
|
|
17509
17582
|
write(stderr, "Guardian detached daemon launcher is unavailable in this runtime.\n");
|
|
17510
17583
|
return 1;
|
|
17511
17584
|
}
|
|
17512
|
-
const started = await options.startDetachedDaemon({ home, host, port });
|
|
17513
|
-
const daemonUrl = normalizeDaemonBaseUrl(started.url, host, port);
|
|
17585
|
+
const started = await options.startDetachedDaemon({ home, host, port: selected.port });
|
|
17586
|
+
const daemonUrl = normalizeDaemonBaseUrl(started.url, host, selected.port);
|
|
17514
17587
|
const controlTowerUrl = `${daemonUrl}/control-tower`;
|
|
17515
17588
|
profile.runtime.daemon_status = "start_requested";
|
|
17516
17589
|
profile.control_tower = {
|
|
@@ -17525,7 +17598,7 @@ async function runStartCommand(flags, options) {
|
|
|
17525
17598
|
daemonUrl,
|
|
17526
17599
|
controlTowerUrl,
|
|
17527
17600
|
pid: started.pid,
|
|
17528
|
-
healthUrl
|
|
17601
|
+
healthUrl,
|
|
17529
17602
|
healthStatus: existing.error ? "unreachable" : "not_reachable",
|
|
17530
17603
|
nextCommands: ["guardian open", "guardian status", "guardian daemon pair --json"]
|
|
17531
17604
|
};
|
|
@@ -17543,6 +17616,15 @@ async function runStartCommand(flags, options) {
|
|
|
17543
17616
|
);
|
|
17544
17617
|
return 0;
|
|
17545
17618
|
}
|
|
17619
|
+
function renderDaemonTokenMismatchMessage(requestedDaemonUrl, port) {
|
|
17620
|
+
return [
|
|
17621
|
+
`Guardian found another daemon or container at ${requestedDaemonUrl}, but it rejected this profile's local runtime token.`,
|
|
17622
|
+
"This usually means an older Guardian daemon or Docker demo is still using the port.",
|
|
17623
|
+
`Recovery: stop the other process/container, or run Guardian on a different port with guardian launch --port=${port + 1}.`,
|
|
17624
|
+
`Diagnostics: guardian status; docker ps --filter publish=${port}`,
|
|
17625
|
+
""
|
|
17626
|
+
].join("\n");
|
|
17627
|
+
}
|
|
17546
17628
|
async function runStopCommand(flags, options) {
|
|
17547
17629
|
const stdout = options.stdout ?? process.stdout;
|
|
17548
17630
|
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.
|
|
4
|
+
export declare const GUARDIAN_CLI_VERSION = "0.1.3";
|
|
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.
|
|
3
|
+
"version": "0.1.3",
|
|
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": ">=
|
|
10
|
+
"node": ">=20.20.0"
|
|
11
11
|
},
|
|
12
12
|
"files": [
|
|
13
13
|
"dist/packages/guardian-cli/src/bin.d.ts",
|