@corenel/cli 0.7.0 → 0.8.0
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/main.js +269 -59
- package/package.json +7 -7
package/dist/main.js
CHANGED
|
@@ -390,6 +390,19 @@ var init_fileService = __esm({
|
|
|
390
390
|
await this.assertReal(a);
|
|
391
391
|
await writeFileAtomic(a, bytes, { shownPath: path });
|
|
392
392
|
}
|
|
393
|
+
/** O_APPEND, NOT atomic-rename: the point is that another process appending
|
|
394
|
+
* to the same file at the same moment lands too, and a rename would replace
|
|
395
|
+
* whatever it wrote. Same confinement as write. */
|
|
396
|
+
async append(path, content) {
|
|
397
|
+
const a = await this.writeTarget(path);
|
|
398
|
+
await fs2.mkdir(dirname2(a), { recursive: true });
|
|
399
|
+
await this.assertReal(a);
|
|
400
|
+
try {
|
|
401
|
+
await fs2.appendFile(a, content, "utf8");
|
|
402
|
+
} catch (e) {
|
|
403
|
+
throw diskFullError(path, e) ?? e;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
393
406
|
async create(path, content = "") {
|
|
394
407
|
const a = await this.writeTarget(path);
|
|
395
408
|
await fs2.mkdir(dirname2(a), { recursive: true });
|
|
@@ -7878,7 +7891,7 @@ var require_public_api = __commonJS({
|
|
|
7878
7891
|
}
|
|
7879
7892
|
return doc;
|
|
7880
7893
|
}
|
|
7881
|
-
function
|
|
7894
|
+
function parse3(src, reviver, options) {
|
|
7882
7895
|
let _reviver = void 0;
|
|
7883
7896
|
if (typeof reviver === "function") {
|
|
7884
7897
|
_reviver = reviver;
|
|
@@ -7919,7 +7932,7 @@ var require_public_api = __commonJS({
|
|
|
7919
7932
|
return value.toString(options);
|
|
7920
7933
|
return new Document.Document(value, _replacer, options).toString(options);
|
|
7921
7934
|
}
|
|
7922
|
-
exports.parse =
|
|
7935
|
+
exports.parse = parse3;
|
|
7923
7936
|
exports.parseAllDocuments = parseAllDocuments;
|
|
7924
7937
|
exports.parseDocument = parseDocument;
|
|
7925
7938
|
exports.stringify = stringify2;
|
|
@@ -8445,7 +8458,7 @@ var require_parse = __commonJS({
|
|
|
8445
8458
|
"../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/parse.js"(exports, module) {
|
|
8446
8459
|
"use strict";
|
|
8447
8460
|
var SemVer = require_semver();
|
|
8448
|
-
var
|
|
8461
|
+
var parse3 = (version2, options, throwErrors = false) => {
|
|
8449
8462
|
if (version2 instanceof SemVer) {
|
|
8450
8463
|
return version2;
|
|
8451
8464
|
}
|
|
@@ -8458,7 +8471,7 @@ var require_parse = __commonJS({
|
|
|
8458
8471
|
throw er;
|
|
8459
8472
|
}
|
|
8460
8473
|
};
|
|
8461
|
-
module.exports =
|
|
8474
|
+
module.exports = parse3;
|
|
8462
8475
|
}
|
|
8463
8476
|
});
|
|
8464
8477
|
|
|
@@ -8466,9 +8479,9 @@ var require_parse = __commonJS({
|
|
|
8466
8479
|
var require_valid = __commonJS({
|
|
8467
8480
|
"../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/valid.js"(exports, module) {
|
|
8468
8481
|
"use strict";
|
|
8469
|
-
var
|
|
8482
|
+
var parse3 = require_parse();
|
|
8470
8483
|
var valid = (version2, options) => {
|
|
8471
|
-
const v =
|
|
8484
|
+
const v = parse3(version2, options);
|
|
8472
8485
|
return v ? v.version : null;
|
|
8473
8486
|
};
|
|
8474
8487
|
module.exports = valid;
|
|
@@ -8479,9 +8492,9 @@ var require_valid = __commonJS({
|
|
|
8479
8492
|
var require_clean = __commonJS({
|
|
8480
8493
|
"../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/clean.js"(exports, module) {
|
|
8481
8494
|
"use strict";
|
|
8482
|
-
var
|
|
8495
|
+
var parse3 = require_parse();
|
|
8483
8496
|
var clean = (version2, options) => {
|
|
8484
|
-
const s =
|
|
8497
|
+
const s = parse3(version2.trim().replace(/^[=v]+/, ""), options);
|
|
8485
8498
|
return s ? s.version : null;
|
|
8486
8499
|
};
|
|
8487
8500
|
module.exports = clean;
|
|
@@ -8516,10 +8529,10 @@ var require_inc = __commonJS({
|
|
|
8516
8529
|
var require_diff = __commonJS({
|
|
8517
8530
|
"../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/diff.js"(exports, module) {
|
|
8518
8531
|
"use strict";
|
|
8519
|
-
var
|
|
8532
|
+
var parse3 = require_parse();
|
|
8520
8533
|
var diff = (version1, version2) => {
|
|
8521
|
-
const v1 =
|
|
8522
|
-
const v2 =
|
|
8534
|
+
const v1 = parse3(version1, null, true);
|
|
8535
|
+
const v2 = parse3(version2, null, true);
|
|
8523
8536
|
const comparison = v1.compare(v2);
|
|
8524
8537
|
if (comparison === 0) {
|
|
8525
8538
|
return null;
|
|
@@ -8590,9 +8603,9 @@ var require_patch = __commonJS({
|
|
|
8590
8603
|
var require_prerelease = __commonJS({
|
|
8591
8604
|
"../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/prerelease.js"(exports, module) {
|
|
8592
8605
|
"use strict";
|
|
8593
|
-
var
|
|
8606
|
+
var parse3 = require_parse();
|
|
8594
8607
|
var prerelease = (version2, options) => {
|
|
8595
|
-
const parsed =
|
|
8608
|
+
const parsed = parse3(version2, options);
|
|
8596
8609
|
return parsed && parsed.prerelease.length ? parsed.prerelease : null;
|
|
8597
8610
|
};
|
|
8598
8611
|
module.exports = prerelease;
|
|
@@ -8778,7 +8791,7 @@ var require_coerce = __commonJS({
|
|
|
8778
8791
|
"../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/coerce.js"(exports, module) {
|
|
8779
8792
|
"use strict";
|
|
8780
8793
|
var SemVer = require_semver();
|
|
8781
|
-
var
|
|
8794
|
+
var parse3 = require_parse();
|
|
8782
8795
|
var { safeRe: re, t } = require_re();
|
|
8783
8796
|
var coerce = (version2, options) => {
|
|
8784
8797
|
if (version2 instanceof SemVer) {
|
|
@@ -8813,7 +8826,7 @@ var require_coerce = __commonJS({
|
|
|
8813
8826
|
const patch = match[4] || "0";
|
|
8814
8827
|
const prerelease = options.includePrerelease && match[5] ? `-${match[5]}` : "";
|
|
8815
8828
|
const build = options.includePrerelease && match[6] ? `+${match[6]}` : "";
|
|
8816
|
-
return
|
|
8829
|
+
return parse3(`${major}.${minor}.${patch}${prerelease}${build}`, options);
|
|
8817
8830
|
};
|
|
8818
8831
|
module.exports = coerce;
|
|
8819
8832
|
}
|
|
@@ -8823,7 +8836,7 @@ var require_coerce = __commonJS({
|
|
|
8823
8836
|
var require_truncate = __commonJS({
|
|
8824
8837
|
"../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/truncate.js"(exports, module) {
|
|
8825
8838
|
"use strict";
|
|
8826
|
-
var
|
|
8839
|
+
var parse3 = require_parse();
|
|
8827
8840
|
var constants2 = require_constants();
|
|
8828
8841
|
var SemVer = require_semver();
|
|
8829
8842
|
var truncate2 = (version2, truncation, options) => {
|
|
@@ -8835,7 +8848,7 @@ var require_truncate = __commonJS({
|
|
|
8835
8848
|
};
|
|
8836
8849
|
var cloneInputVersion = (version2, options) => {
|
|
8837
8850
|
const versionStringToParse = version2 instanceof SemVer ? version2.version : version2;
|
|
8838
|
-
return
|
|
8851
|
+
return parse3(versionStringToParse, options);
|
|
8839
8852
|
};
|
|
8840
8853
|
var doTruncation = (version2, truncation) => {
|
|
8841
8854
|
if (isPrerelease(truncation)) {
|
|
@@ -9877,7 +9890,7 @@ var require_semver2 = __commonJS({
|
|
|
9877
9890
|
var constants2 = require_constants();
|
|
9878
9891
|
var SemVer = require_semver();
|
|
9879
9892
|
var identifiers = require_identifiers();
|
|
9880
|
-
var
|
|
9893
|
+
var parse3 = require_parse();
|
|
9881
9894
|
var valid = require_valid();
|
|
9882
9895
|
var clean = require_clean();
|
|
9883
9896
|
var inc = require_inc();
|
|
@@ -9916,7 +9929,7 @@ var require_semver2 = __commonJS({
|
|
|
9916
9929
|
var simplifyRange = require_simplify();
|
|
9917
9930
|
var subset = require_subset();
|
|
9918
9931
|
module.exports = {
|
|
9919
|
-
parse:
|
|
9932
|
+
parse: parse3,
|
|
9920
9933
|
valid,
|
|
9921
9934
|
clean,
|
|
9922
9935
|
inc,
|
|
@@ -12303,7 +12316,7 @@ var require_parser2 = __commonJS({
|
|
|
12303
12316
|
}
|
|
12304
12317
|
return buf;
|
|
12305
12318
|
};
|
|
12306
|
-
_proto.parse = function
|
|
12319
|
+
_proto.parse = function parse3() {
|
|
12307
12320
|
return new nodes.NodeList(0, 0, this.parseNodes());
|
|
12308
12321
|
};
|
|
12309
12322
|
_proto.parseAsRoot = function parseAsRoot() {
|
|
@@ -12312,7 +12325,7 @@ var require_parser2 = __commonJS({
|
|
|
12312
12325
|
return Parser2;
|
|
12313
12326
|
}(Obj);
|
|
12314
12327
|
module.exports = {
|
|
12315
|
-
parse: function
|
|
12328
|
+
parse: function parse3(src, extensions, opts) {
|
|
12316
12329
|
var p = new Parser(lexer.lex(src, opts));
|
|
12317
12330
|
if (extensions !== void 0) {
|
|
12318
12331
|
p.extensions = extensions;
|
|
@@ -13894,7 +13907,7 @@ var require_filters = __commonJS({
|
|
|
13894
13907
|
return r.copySafeness(str, res);
|
|
13895
13908
|
}
|
|
13896
13909
|
_exports.indent = indent;
|
|
13897
|
-
function
|
|
13910
|
+
function join14(arr, del, attr) {
|
|
13898
13911
|
del = del || "";
|
|
13899
13912
|
if (attr) {
|
|
13900
13913
|
arr = lib.map(arr, function(v) {
|
|
@@ -13903,7 +13916,7 @@ var require_filters = __commonJS({
|
|
|
13903
13916
|
}
|
|
13904
13917
|
return arr.join(del);
|
|
13905
13918
|
}
|
|
13906
|
-
_exports.join =
|
|
13919
|
+
_exports.join = join14;
|
|
13907
13920
|
function last(arr) {
|
|
13908
13921
|
return arr[arr.length - 1];
|
|
13909
13922
|
}
|
|
@@ -21103,7 +21116,7 @@ var require_extension = __commonJS({
|
|
|
21103
21116
|
if (dest[name] === void 0) dest[name] = [elem];
|
|
21104
21117
|
else dest[name].push(elem);
|
|
21105
21118
|
}
|
|
21106
|
-
function
|
|
21119
|
+
function parse3(header) {
|
|
21107
21120
|
const offers = /* @__PURE__ */ Object.create(null);
|
|
21108
21121
|
let params = /* @__PURE__ */ Object.create(null);
|
|
21109
21122
|
let mustUnescape = false;
|
|
@@ -21243,7 +21256,7 @@ var require_extension = __commonJS({
|
|
|
21243
21256
|
}).join(", ");
|
|
21244
21257
|
}).join(", ");
|
|
21245
21258
|
}
|
|
21246
|
-
module.exports = { format, parse:
|
|
21259
|
+
module.exports = { format, parse: parse3 };
|
|
21247
21260
|
}
|
|
21248
21261
|
});
|
|
21249
21262
|
|
|
@@ -21277,7 +21290,7 @@ var require_websocket = __commonJS({
|
|
|
21277
21290
|
var {
|
|
21278
21291
|
EventTarget: { addEventListener, removeEventListener }
|
|
21279
21292
|
} = require_event_target();
|
|
21280
|
-
var { format, parse:
|
|
21293
|
+
var { format, parse: parse3 } = require_extension();
|
|
21281
21294
|
var { toBuffer } = require_buffer_util();
|
|
21282
21295
|
var kAborted = Symbol("kAborted");
|
|
21283
21296
|
var protocolVersions = [8, 13];
|
|
@@ -21954,7 +21967,7 @@ var require_websocket = __commonJS({
|
|
|
21954
21967
|
}
|
|
21955
21968
|
let extensions;
|
|
21956
21969
|
try {
|
|
21957
|
-
extensions =
|
|
21970
|
+
extensions = parse3(secWebSocketExtensions);
|
|
21958
21971
|
} catch (err) {
|
|
21959
21972
|
const message = "Invalid Sec-WebSocket-Extensions header";
|
|
21960
21973
|
abortHandshake(websocket, socket, message);
|
|
@@ -22246,7 +22259,7 @@ var require_subprotocol = __commonJS({
|
|
|
22246
22259
|
"../../node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/subprotocol.js"(exports, module) {
|
|
22247
22260
|
"use strict";
|
|
22248
22261
|
var { tokenChars } = require_validation();
|
|
22249
|
-
function
|
|
22262
|
+
function parse3(header) {
|
|
22250
22263
|
const protocols = /* @__PURE__ */ new Set();
|
|
22251
22264
|
let start = -1;
|
|
22252
22265
|
let end = -1;
|
|
@@ -22282,7 +22295,7 @@ var require_subprotocol = __commonJS({
|
|
|
22282
22295
|
protocols.add(protocol);
|
|
22283
22296
|
return protocols;
|
|
22284
22297
|
}
|
|
22285
|
-
module.exports = { parse:
|
|
22298
|
+
module.exports = { parse: parse3 };
|
|
22286
22299
|
}
|
|
22287
22300
|
});
|
|
22288
22301
|
|
|
@@ -24865,7 +24878,7 @@ async function deviceLogin(opts) {
|
|
|
24865
24878
|
);
|
|
24866
24879
|
}
|
|
24867
24880
|
};
|
|
24868
|
-
const dc = await post("/oauth/device/code", { client_id: "corenel-cli", scope: "agent" });
|
|
24881
|
+
const dc = await post("/oauth/device/code", { client_id: "corenel-cli", scope: "agent pair" });
|
|
24869
24882
|
if (!dc.device_code) throw new Error("device authorization failed");
|
|
24870
24883
|
(opts.open ?? defaultOpen)(dc.verification_uri, dc.user_code);
|
|
24871
24884
|
let interval = opts.pollMs ?? Math.max(MIN_POLL_MS, (dc.interval ?? 5) * 1e3);
|
|
@@ -24913,8 +24926,8 @@ var InvalidApiBaseError = class extends Error {
|
|
|
24913
24926
|
this.name = "InvalidApiBaseError";
|
|
24914
24927
|
}
|
|
24915
24928
|
};
|
|
24916
|
-
function isLoopback(
|
|
24917
|
-
const h =
|
|
24929
|
+
function isLoopback(hostname2) {
|
|
24930
|
+
const h = hostname2.replace(/^\[|\]$/g, "").toLowerCase();
|
|
24918
24931
|
return h === "localhost" || h === "127.0.0.1" || h === "::1" || h.endsWith(".localhost");
|
|
24919
24932
|
}
|
|
24920
24933
|
var warnedCleartext = false;
|
|
@@ -25417,6 +25430,7 @@ var KNOWN_KEYS = [
|
|
|
25417
25430
|
"addUnder",
|
|
25418
25431
|
"cloneUnder",
|
|
25419
25432
|
"allowLan",
|
|
25433
|
+
"behindTlsProxy",
|
|
25420
25434
|
"allowOrigins",
|
|
25421
25435
|
"tlsCert",
|
|
25422
25436
|
"tlsKey",
|
|
@@ -25438,7 +25452,7 @@ var KNOWN_KEYS = [
|
|
|
25438
25452
|
"mcpServers",
|
|
25439
25453
|
"mcpAllow",
|
|
25440
25454
|
"identityIssuer",
|
|
25441
|
-
"
|
|
25455
|
+
"org",
|
|
25442
25456
|
"push",
|
|
25443
25457
|
"audit",
|
|
25444
25458
|
"sendTelemetry",
|
|
@@ -26323,7 +26337,7 @@ import { procTools } from "@corenel/harness/tools/procs";
|
|
|
26323
26337
|
|
|
26324
26338
|
// src/sidecarConnect.ts
|
|
26325
26339
|
import { stateDirName as stateDirName5 } from "@corenel/protocol";
|
|
26326
|
-
import { SidecarHost } from "@corenel/harness/sidecar/host";
|
|
26340
|
+
import { SidecarHost, isSidecarKeyMismatch, isSidecarAccountRefusal } from "@corenel/harness/sidecar/host";
|
|
26327
26341
|
|
|
26328
26342
|
// ../../node_modules/.pnpm/ws@8.21.0/node_modules/ws/wrapper.mjs
|
|
26329
26343
|
var import_stream = __toESM(require_stream(), 1);
|
|
@@ -26486,12 +26500,209 @@ function hostBackedProcs(host, seed = []) {
|
|
|
26486
26500
|
};
|
|
26487
26501
|
}
|
|
26488
26502
|
|
|
26503
|
+
// src/sidecarDevice.ts
|
|
26504
|
+
init_tools_node();
|
|
26505
|
+
import { join as join10 } from "node:path";
|
|
26506
|
+
import { asEcPublicJwk, generatePrivateJwk, signerFromPrivateJwk } from "@corenel/harness/sidecar/deviceKeys";
|
|
26507
|
+
function cliDevicesPath(base) {
|
|
26508
|
+
return join10(corenelDir(base), "cli", "sidecar-devices.json");
|
|
26509
|
+
}
|
|
26510
|
+
var B64 = /^[A-Za-z0-9_-]{1,64}$/;
|
|
26511
|
+
var B43 = /^[A-Za-z0-9_-]{43}$/;
|
|
26512
|
+
function isCliDevice(v) {
|
|
26513
|
+
if (typeof v !== "object" || v === null) return false;
|
|
26514
|
+
const r = v;
|
|
26515
|
+
const k = r.privateJwk;
|
|
26516
|
+
return typeof r.id === "string" && B64.test(r.id) && typeof r.sidecarJkt === "string" && B43.test(r.sidecarJkt) && typeof k === "object" && k !== null && !!asEcPublicJwk({ kty: k.kty, crv: k.crv, x: k.x, y: k.y }) && typeof k.d === "string" && B43.test(k.d);
|
|
26517
|
+
}
|
|
26518
|
+
function parse2(text) {
|
|
26519
|
+
let raw;
|
|
26520
|
+
try {
|
|
26521
|
+
raw = JSON.parse(text);
|
|
26522
|
+
} catch {
|
|
26523
|
+
return null;
|
|
26524
|
+
}
|
|
26525
|
+
const r = raw;
|
|
26526
|
+
if (typeof r !== "object" || r === null || r.version !== 1) return null;
|
|
26527
|
+
if (typeof r.devices !== "object" || r.devices === null || Array.isArray(r.devices)) return null;
|
|
26528
|
+
const devices = /* @__PURE__ */ Object.create(null);
|
|
26529
|
+
for (const [url, d] of Object.entries(r.devices)) {
|
|
26530
|
+
if (!isCliDevice(d)) return null;
|
|
26531
|
+
const k = d.privateJwk;
|
|
26532
|
+
devices[url] = { id: d.id, sidecarJkt: d.sidecarJkt, privateJwk: { kty: k.kty, crv: k.crv, x: k.x, y: k.y, d: k.d } };
|
|
26533
|
+
}
|
|
26534
|
+
return { version: 1, devices };
|
|
26535
|
+
}
|
|
26536
|
+
function cliDeviceStore(path = cliDevicesPath()) {
|
|
26537
|
+
const file = fileTextStore(path);
|
|
26538
|
+
const dir = join10(path, "..");
|
|
26539
|
+
const load = async () => {
|
|
26540
|
+
const text = await file.read();
|
|
26541
|
+
return text === null ? { version: 1, devices: /* @__PURE__ */ Object.create(null) } : parse2(text);
|
|
26542
|
+
};
|
|
26543
|
+
const change = async (edit) => {
|
|
26544
|
+
const f = await load();
|
|
26545
|
+
if (!f) throw new Error(`${path} is not a file this CLI understands. Remove it to pair again.`);
|
|
26546
|
+
edit(f);
|
|
26547
|
+
await ensurePrivateDir(dir);
|
|
26548
|
+
await file.write(`${JSON.stringify(f, null, 2)}
|
|
26549
|
+
`);
|
|
26550
|
+
};
|
|
26551
|
+
return {
|
|
26552
|
+
async get(url) {
|
|
26553
|
+
try {
|
|
26554
|
+
const f = await load();
|
|
26555
|
+
return f && Object.prototype.hasOwnProperty.call(f.devices, url) ? f.devices[url] : void 0;
|
|
26556
|
+
} catch {
|
|
26557
|
+
return void 0;
|
|
26558
|
+
}
|
|
26559
|
+
},
|
|
26560
|
+
set: (url, device) => change((f) => {
|
|
26561
|
+
f.devices[url] = device;
|
|
26562
|
+
}),
|
|
26563
|
+
forget: (url) => change((f) => {
|
|
26564
|
+
delete f.devices[url];
|
|
26565
|
+
})
|
|
26566
|
+
};
|
|
26567
|
+
}
|
|
26568
|
+
async function sidecarCredential(url, env, store) {
|
|
26569
|
+
const kept = await store.get(url);
|
|
26570
|
+
const enroll = env.CORENEL_SIDECAR_CODE || void 0;
|
|
26571
|
+
if (!kept && !enroll) return null;
|
|
26572
|
+
const privateJwk = kept?.privateJwk ?? await generatePrivateJwk();
|
|
26573
|
+
return {
|
|
26574
|
+
...enroll ? { enroll } : {},
|
|
26575
|
+
...kept ? { device: { id: kept.id, sidecarJkt: kept.sidecarJkt } } : {},
|
|
26576
|
+
deviceKey: await signerFromPrivateJwk(privateJwk),
|
|
26577
|
+
privateJwk
|
|
26578
|
+
};
|
|
26579
|
+
}
|
|
26580
|
+
|
|
26581
|
+
// src/sidecarIdentity.ts
|
|
26582
|
+
function cliIdentity(o) {
|
|
26583
|
+
const fetchImpl = o.fetchImpl ?? fetch;
|
|
26584
|
+
const timeoutMs = o.timeoutMs ?? 8e3;
|
|
26585
|
+
let last = null;
|
|
26586
|
+
return {
|
|
26587
|
+
problem: () => last,
|
|
26588
|
+
answer: async ({ nonce, sidecarId, jkt, orgId }) => {
|
|
26589
|
+
last = null;
|
|
26590
|
+
let token;
|
|
26591
|
+
try {
|
|
26592
|
+
token = await o.token();
|
|
26593
|
+
} catch {
|
|
26594
|
+
token = null;
|
|
26595
|
+
}
|
|
26596
|
+
if (!token) {
|
|
26597
|
+
last = "this CLI is not signed in, and the sidecar only admits a verified account. Run `corenel login` (or set CORENEL_TOKEN), then try again.";
|
|
26598
|
+
return null;
|
|
26599
|
+
}
|
|
26600
|
+
try {
|
|
26601
|
+
const base = (await o.base()).replace(/\/+$/, "");
|
|
26602
|
+
const res = await fetchImpl(`${base}/v1/pairing-assertions`, {
|
|
26603
|
+
method: "POST",
|
|
26604
|
+
headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` },
|
|
26605
|
+
body: JSON.stringify({ aud: sidecarId, nonce, jkt, ...orgId ? { org_id: orgId } : {} }),
|
|
26606
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
26607
|
+
});
|
|
26608
|
+
if (res.status === 403) {
|
|
26609
|
+
let code3;
|
|
26610
|
+
try {
|
|
26611
|
+
code3 = (await res.json())?.code;
|
|
26612
|
+
} catch {
|
|
26613
|
+
code3 = void 0;
|
|
26614
|
+
}
|
|
26615
|
+
if (code3 === "CLI_SCOPE") {
|
|
26616
|
+
last = "this CLI sign-in is not allowed to connect to sidecars. Run `corenel login` again and allow sidecar access when you approve it.";
|
|
26617
|
+
return null;
|
|
26618
|
+
}
|
|
26619
|
+
if (orgId) {
|
|
26620
|
+
last = `your account is not a member of the organization this sidecar admits (${orgId}).`;
|
|
26621
|
+
return null;
|
|
26622
|
+
}
|
|
26623
|
+
}
|
|
26624
|
+
if (res.status === 401) {
|
|
26625
|
+
last = "the API refused this CLI sign-in. Run `corenel login` again, then try again.";
|
|
26626
|
+
return null;
|
|
26627
|
+
}
|
|
26628
|
+
if (!res.ok) {
|
|
26629
|
+
last = `could not get a pairing assertion from ${base} (HTTP ${res.status}).`;
|
|
26630
|
+
return null;
|
|
26631
|
+
}
|
|
26632
|
+
const body = await res.json();
|
|
26633
|
+
const assertion = body?.assertion;
|
|
26634
|
+
if (typeof assertion !== "string" || !assertion) {
|
|
26635
|
+
last = `${base} answered without a pairing assertion.`;
|
|
26636
|
+
return null;
|
|
26637
|
+
}
|
|
26638
|
+
return assertion;
|
|
26639
|
+
} catch (e) {
|
|
26640
|
+
last = `could not reach the API for a pairing assertion (${e instanceof Error ? e.message : String(e)}).`;
|
|
26641
|
+
return null;
|
|
26642
|
+
}
|
|
26643
|
+
}
|
|
26644
|
+
};
|
|
26645
|
+
}
|
|
26646
|
+
|
|
26489
26647
|
// src/sidecarConnect.ts
|
|
26648
|
+
init_tools_node();
|
|
26649
|
+
import { hostname } from "node:os";
|
|
26490
26650
|
var CONNECT_TIMEOUT_MS = 3e3;
|
|
26491
|
-
|
|
26651
|
+
var HANDSHAKE_TIMEOUT_MS = 15e3;
|
|
26652
|
+
function cliDeviceName(host = hostname) {
|
|
26653
|
+
let h = "";
|
|
26654
|
+
try {
|
|
26655
|
+
h = host().trim();
|
|
26656
|
+
} catch {
|
|
26657
|
+
h = "";
|
|
26658
|
+
}
|
|
26659
|
+
return h ? `CLI on ${h}` : "CLI";
|
|
26660
|
+
}
|
|
26661
|
+
function defaultCliIdentity(env) {
|
|
26662
|
+
return cliIdentity({ base: () => apiBase(void 0, { env }), token: () => nodeAuthToken().getToken() });
|
|
26663
|
+
}
|
|
26664
|
+
async function reportHandshakeFailure(e, url, usedDevice, store, identity2, fallback) {
|
|
26665
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
26666
|
+
if (isSidecarKeyMismatch(e)) {
|
|
26667
|
+
process.stderr.write(`corenel: sidecar connection at ${url} failed to complete: ${msg} -- ${fallback}
|
|
26668
|
+
`);
|
|
26669
|
+
process.stderr.write(mismatchNote(url));
|
|
26670
|
+
return;
|
|
26671
|
+
}
|
|
26672
|
+
if (isSidecarAccountRefusal(e)) {
|
|
26673
|
+
const problem = identity2.problem() ?? "the sidecar verified this account and did not admit it (not its owner, or not a member of its organization, or a device another member paired).";
|
|
26674
|
+
process.stderr.write(`corenel: the sidecar at ${url} did not accept this CLI: ${problem} -- ${fallback}
|
|
26675
|
+
`);
|
|
26676
|
+
return;
|
|
26677
|
+
}
|
|
26678
|
+
process.stderr.write(`corenel: sidecar connection at ${url} failed to complete: ${msg} -- ${fallback}
|
|
26679
|
+
`);
|
|
26680
|
+
if (usedDevice && /denied/.test(msg)) await store.forget(url).catch(() => void 0);
|
|
26681
|
+
}
|
|
26682
|
+
async function credentialOptions(url, env, store) {
|
|
26683
|
+
const cred = await sidecarCredential(url, env, store);
|
|
26684
|
+
if (!cred) return null;
|
|
26685
|
+
const { privateJwk, ...host } = cred;
|
|
26686
|
+
return {
|
|
26687
|
+
...host,
|
|
26688
|
+
usedDevice: !!cred.device,
|
|
26689
|
+
onDeviceIssued: (device) => {
|
|
26690
|
+
store.set(url, { ...device, privateJwk }).catch((e) => {
|
|
26691
|
+
process.stderr.write(`corenel: paired, but could not keep the device key: ${e instanceof Error ? e.message : String(e)}
|
|
26692
|
+
`);
|
|
26693
|
+
});
|
|
26694
|
+
}
|
|
26695
|
+
};
|
|
26696
|
+
}
|
|
26697
|
+
function mismatchNote(url) {
|
|
26698
|
+
return `corenel: the sidecar at ${url} is not the sidecar this CLI paired with (its key does not match the pinned fingerprint). Check the address. If that sidecar was reinstalled, pair again with a fresh code (CORENEL_SIDECAR_CODE from \`corenel-sidecar pair\`).
|
|
26699
|
+
`;
|
|
26700
|
+
}
|
|
26701
|
+
async function connectSidecarProcs(env = process.env, store = cliDeviceStore(), identity2 = defaultCliIdentity(env)) {
|
|
26492
26702
|
const url = env.CORENEL_SIDECAR_URL;
|
|
26493
|
-
|
|
26494
|
-
|
|
26703
|
+
if (!url) return null;
|
|
26704
|
+
const cred = await credentialOptions(url, env, store);
|
|
26705
|
+
if (!cred) return null;
|
|
26495
26706
|
const ac = new AbortController();
|
|
26496
26707
|
const timer = setTimeout(() => ac.abort(), CONNECT_TIMEOUT_MS);
|
|
26497
26708
|
let channel;
|
|
@@ -26506,24 +26717,23 @@ async function connectSidecarProcs(env = process.env) {
|
|
|
26506
26717
|
} finally {
|
|
26507
26718
|
clearTimeout(timer);
|
|
26508
26719
|
}
|
|
26720
|
+
const { usedDevice, ...credential } = cred;
|
|
26509
26721
|
const host = new SidecarHost({
|
|
26510
26722
|
channel,
|
|
26511
|
-
|
|
26723
|
+
...credential,
|
|
26512
26724
|
stateDir: stateDirName5(),
|
|
26513
26725
|
clientId: `corenel-cli-${process.pid}`,
|
|
26514
|
-
clientName:
|
|
26726
|
+
clientName: cliDeviceName(),
|
|
26727
|
+
onIdentityChallenge: identity2.answer,
|
|
26515
26728
|
providers: {},
|
|
26516
26729
|
registerTool: () => {
|
|
26517
26730
|
}
|
|
26518
26731
|
});
|
|
26519
26732
|
try {
|
|
26520
|
-
await host.connect(
|
|
26733
|
+
await host.connect(HANDSHAKE_TIMEOUT_MS);
|
|
26521
26734
|
} catch (e) {
|
|
26522
|
-
process.stderr.write(
|
|
26523
|
-
`corenel: sidecar connection at ${url} failed to complete: ${e instanceof Error ? e.message : String(e)} -- continuing without proc_start/proc_stop/proc_list.
|
|
26524
|
-
`
|
|
26525
|
-
);
|
|
26526
26735
|
host.disconnect("handshake failed");
|
|
26736
|
+
await reportHandshakeFailure(e, url, usedDevice, store, identity2, "continuing without proc_start/proc_stop/proc_list.");
|
|
26527
26737
|
return null;
|
|
26528
26738
|
}
|
|
26529
26739
|
if (!host.supportsProcs()) {
|
|
@@ -26533,10 +26743,11 @@ async function connectSidecarProcs(env = process.env) {
|
|
|
26533
26743
|
const seed = await host.procList().catch(() => []);
|
|
26534
26744
|
return { procs: hostBackedProcs(host, seed), disconnect: () => host.disconnect() };
|
|
26535
26745
|
}
|
|
26536
|
-
async function connectMcpAdmin(env = process.env) {
|
|
26746
|
+
async function connectMcpAdmin(env = process.env, store = cliDeviceStore(), identity2 = defaultCliIdentity(env)) {
|
|
26537
26747
|
const url = env.CORENEL_SIDECAR_URL;
|
|
26538
|
-
|
|
26539
|
-
|
|
26748
|
+
if (!url) return null;
|
|
26749
|
+
const cred = await credentialOptions(url, env, store);
|
|
26750
|
+
if (!cred) return null;
|
|
26540
26751
|
const ac = new AbortController();
|
|
26541
26752
|
const timer = setTimeout(() => ac.abort(), CONNECT_TIMEOUT_MS);
|
|
26542
26753
|
let channel;
|
|
@@ -26551,24 +26762,23 @@ async function connectMcpAdmin(env = process.env) {
|
|
|
26551
26762
|
} finally {
|
|
26552
26763
|
clearTimeout(timer);
|
|
26553
26764
|
}
|
|
26765
|
+
const { usedDevice, ...credential } = cred;
|
|
26554
26766
|
const host = new SidecarHost({
|
|
26555
26767
|
channel,
|
|
26556
|
-
|
|
26768
|
+
...credential,
|
|
26557
26769
|
stateDir: stateDirName5(),
|
|
26558
26770
|
clientId: `corenel-cli-${process.pid}`,
|
|
26559
|
-
clientName:
|
|
26771
|
+
clientName: cliDeviceName(),
|
|
26772
|
+
onIdentityChallenge: identity2.answer,
|
|
26560
26773
|
providers: {},
|
|
26561
26774
|
registerTool: () => {
|
|
26562
26775
|
}
|
|
26563
26776
|
});
|
|
26564
26777
|
try {
|
|
26565
|
-
await host.connect(
|
|
26778
|
+
await host.connect(HANDSHAKE_TIMEOUT_MS);
|
|
26566
26779
|
} catch (e) {
|
|
26567
|
-
process.stderr.write(
|
|
26568
|
-
`corenel: sidecar connection at ${url} failed to complete: ${e instanceof Error ? e.message : String(e)} -- writing MCP config locally instead.
|
|
26569
|
-
`
|
|
26570
|
-
);
|
|
26571
26780
|
host.disconnect("handshake failed");
|
|
26781
|
+
await reportHandshakeFailure(e, url, usedDevice, store, identity2, "writing MCP config locally instead.");
|
|
26572
26782
|
return null;
|
|
26573
26783
|
}
|
|
26574
26784
|
if (!host.supportsMcpAdmin()) {
|
|
@@ -26823,7 +27033,7 @@ async function resolveStrategyPrompt(files, id) {
|
|
|
26823
27033
|
// src/policyResolve.ts
|
|
26824
27034
|
import { readFile as readFile2 } from "node:fs/promises";
|
|
26825
27035
|
import { homedir as homedir3 } from "node:os";
|
|
26826
|
-
import { join as
|
|
27036
|
+
import { join as join11 } from "node:path";
|
|
26827
27037
|
import { stateDirName as stateDirName6 } from "@corenel/protocol";
|
|
26828
27038
|
import { BUILTIN_POLICIES, STANDARD_POLICY as STANDARD_POLICY3, policyFromYaml } from "@corenel/harness/guardrail";
|
|
26829
27039
|
var PolicyResolutionError = class extends Error {
|
|
@@ -26883,10 +27093,10 @@ async function resolvePolicy(opts) {
|
|
|
26883
27093
|
);
|
|
26884
27094
|
return { policy, source: { kind: "file", path: flag2 } };
|
|
26885
27095
|
}
|
|
26886
|
-
const projectPath =
|
|
27096
|
+
const projectPath = join11(cwd, stateDirName6(), "policy.yaml");
|
|
26887
27097
|
const project = await loadDiscoveredPolicyFile(projectPath);
|
|
26888
27098
|
if (project) return { policy: project, source: { kind: "project", path: projectPath } };
|
|
26889
|
-
const userPath =
|
|
27099
|
+
const userPath = join11(homedir3(), stateDirName6(), "policy.yaml");
|
|
26890
27100
|
const user = await loadDiscoveredPolicyFile(userPath);
|
|
26891
27101
|
if (user) return { policy: user, source: { kind: "user", path: userPath } };
|
|
26892
27102
|
return { policy: STANDARD_POLICY3, source: { kind: "default" } };
|
|
@@ -27747,9 +27957,9 @@ function gatedAgentTools(registry, policy) {
|
|
|
27747
27957
|
// ../mcp/src/cache.ts
|
|
27748
27958
|
import { createHash as createHash2 } from "node:crypto";
|
|
27749
27959
|
import { readFile as readFile4, writeFile as writeFile3, mkdir as mkdir3, rename as rename2 } from "node:fs/promises";
|
|
27750
|
-
import { dirname as dirname8, join as
|
|
27960
|
+
import { dirname as dirname8, join as join12 } from "node:path";
|
|
27751
27961
|
function toolCachePath(stateDir) {
|
|
27752
|
-
return
|
|
27962
|
+
return join12(stateDir, "mcp-tools.json");
|
|
27753
27963
|
}
|
|
27754
27964
|
function credentialFingerprint(cred) {
|
|
27755
27965
|
if (!cred) return "none";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@corenel/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Corenel CLI — runs the harness in node, in-proc, no transport. The headless proof the kernel is host-agnostic. (corenel run/ask/chat/login + start --sidecar to follow.)",
|
|
6
6
|
"bin": {
|
|
@@ -9,11 +9,11 @@
|
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"openai": "^4.77.0",
|
|
11
11
|
"ws": "^8.18.0",
|
|
12
|
-
"@corenel/config": "0.
|
|
13
|
-
"@corenel/
|
|
14
|
-
"@corenel/
|
|
15
|
-
"@corenel/
|
|
16
|
-
"@corenel/term": "0.
|
|
12
|
+
"@corenel/config": "0.6.0",
|
|
13
|
+
"@corenel/mcp": "0.4.0",
|
|
14
|
+
"@corenel/protocol": "0.12.0",
|
|
15
|
+
"@corenel/harness": "0.13.0",
|
|
16
|
+
"@corenel/term": "0.7.0"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
19
|
"esbuild": "^0.21.5",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"tsx": "^4.19.2",
|
|
23
23
|
"typescript": "^5.9.3",
|
|
24
24
|
"@corenel/crew": "0.0.0",
|
|
25
|
-
"@corenel/tools-node": "0.
|
|
25
|
+
"@corenel/tools-node": "0.7.0"
|
|
26
26
|
},
|
|
27
27
|
"publishConfig": {
|
|
28
28
|
"access": "public"
|