@corenel/sidecar 0.6.1 → 0.6.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.
Files changed (2) hide show
  1. package/dist/cli.js +263 -29
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -14040,7 +14040,7 @@ var require_express_app = __commonJS({
14040
14040
  this.name += this.ext = (this.defaultEngine[0] !== "." ? "." : "") + this.defaultEngine;
14041
14041
  }
14042
14042
  }
14043
- NunjucksView.prototype.render = function render(opts, cb) {
14043
+ NunjucksView.prototype.render = function render2(opts, cb) {
14044
14044
  env.render(this.name, opts, cb);
14045
14045
  };
14046
14046
  app.set("view", NunjucksView);
@@ -14313,7 +14313,7 @@ var require_environment = __commonJS({
14313
14313
  _proto.express = function express(app) {
14314
14314
  return expressApp(this, app);
14315
14315
  };
14316
- _proto.render = function render(name, ctx, cb) {
14316
+ _proto.render = function render2(name, ctx, cb) {
14317
14317
  if (lib.isFunction(ctx)) {
14318
14318
  cb = ctx;
14319
14319
  ctx = null;
@@ -14441,7 +14441,7 @@ var require_environment = __commonJS({
14441
14441
  this.compiled = false;
14442
14442
  }
14443
14443
  };
14444
- _proto3.render = function render(ctx, parentFrame, cb) {
14444
+ _proto3.render = function render2(ctx, parentFrame, cb) {
14445
14445
  var _this6 = this;
14446
14446
  if (typeof ctx === "function") {
14447
14447
  cb = ctx;
@@ -15021,7 +15021,7 @@ var require_nunjucks = __commonJS({
15021
15021
  }
15022
15022
  return new Template(src2, env, path, eagerCompile);
15023
15023
  },
15024
- render: function render(name, ctx, cb) {
15024
+ render: function render2(name, ctx, cb) {
15025
15025
  if (!e2) {
15026
15026
  configure();
15027
15027
  }
@@ -23279,6 +23279,11 @@ function helpText() {
23279
23279
  " roots list|add|remove [path]",
23280
23280
  " edit the working directories in daemon.json (add stores the",
23281
23281
  " resolved, absolute path)",
23282
+ " add-under list|add|remove [path]",
23283
+ " edit the areas a client may add a root under, same way",
23284
+ " config list|get|set|unset|add|remove [key] [value]",
23285
+ " read or change any daemon.json setting, including turning",
23286
+ " a capability back off (config set allow-shell false)",
23282
23287
  " doctor report what this machine would serve, and what is wrong",
23283
23288
  " (exits non-zero on a definite fault -- safe to script)",
23284
23289
  " login|logout|auth manage the signed-in account",
@@ -28845,7 +28850,7 @@ function makeMicrovmBackend(deps) {
28845
28850
  if (!live.length) return;
28846
28851
  const r2 = await deps.run(listArgs());
28847
28852
  if (r2.code !== 0) return;
28848
- const present2 = new Set(parseSandboxList(r2.stdout).map((row) => row.name));
28853
+ const present2 = new Set(parseSandboxList(r2.stdout).map((row2) => row2.name));
28849
28854
  for (const s2 of live) {
28850
28855
  if (present2.has(sandboxName(s2.id))) continue;
28851
28856
  if (at2 - s2.createdAt < RECONCILE_MS) continue;
@@ -29130,21 +29135,21 @@ function makeMicrovmBackend(deps) {
29130
29135
  deps.log?.(`sessions: could not list existing sandboxes (msb exit ${r2.code}) \u2014 nothing adopted`);
29131
29136
  return { adopted, unmanaged };
29132
29137
  }
29133
- for (const row of parseSandboxList(r2.stdout)) {
29134
- const id = idFromSandboxName(row.name);
29138
+ for (const row2 of parseSandboxList(r2.stdout)) {
29139
+ const id = idFromSandboxName(row2.name);
29135
29140
  if (!id) continue;
29136
29141
  seq2 = Math.max(seq2, seqOf(id));
29137
29142
  if (sessions.has(id)) continue;
29138
- const inspected = await deps.run(inspectArgs(row.name)).catch(() => null);
29143
+ const inspected = await deps.run(inspectArgs(row2.name)).catch(() => null);
29139
29144
  const labels = inspected && inspected.code === 0 ? parseSandboxLabels(inspected.stdout) : {};
29140
29145
  const workdir = labels[LABEL_WORKDIR];
29141
29146
  if (!workdir) {
29142
- unmanaged.push(row.name);
29147
+ unmanaged.push(row2.name);
29143
29148
  continue;
29144
29149
  }
29145
29150
  if (!within(workdir)) {
29146
- deps.log?.(`sessions: sandbox "${row.name}" holds ${workdir}, outside this daemon's roots \u2014 not adopted`);
29147
- unmanaged.push(row.name);
29151
+ deps.log?.(`sessions: sandbox "${row2.name}" holds ${workdir}, outside this daemon's roots \u2014 not adopted`);
29152
+ unmanaged.push(row2.name);
29148
29153
  continue;
29149
29154
  }
29150
29155
  const stamped = Number(labels[LABEL_CREATED]);
@@ -29154,9 +29159,9 @@ function makeMicrovmBackend(deps) {
29154
29159
  const repoRef = labels[LABEL_REPO_REF];
29155
29160
  sessions.set(id, {
29156
29161
  id,
29157
- status: statusFromSandbox(row.status),
29162
+ status: statusFromSandbox(row2.status),
29158
29163
  workdir,
29159
- createdAt: Number.isFinite(stamped) && stamped > 0 ? stamped : row.createdAt ?? now2(),
29164
+ createdAt: Number.isFinite(stamped) && stamped > 0 ? stamped : row2.createdAt ?? now2(),
29160
29165
  ...owner ? { owner } : {},
29161
29166
  ...repoUrl && repoCommit ? { source: { url: repoUrl, commit: repoCommit, ...repoRef ? { ref: repoRef } : {} } } : {},
29162
29167
  /* THE ONLY PLACE THIS IS EVER SET TRUE. `create()` never touches it,
@@ -45398,6 +45403,7 @@ async function resolveEndpoint(args, env = process.env) {
45398
45403
  import { readFile as readFile2, writeFile, mkdir as mkdir3 } from "node:fs/promises";
45399
45404
  import { dirname as dirname7, join as join18 } from "node:path";
45400
45405
  var DAEMON_CONFIG_VERSION = 1;
45406
+ var SECRET_KEYS = ["acpAuth", "tunnelToken", "token"];
45401
45407
  var KNOWN_KEYS = [
45402
45408
  "version",
45403
45409
  "port",
@@ -45576,59 +45582,285 @@ async function runSetup(argv, io) {
45576
45582
  return 0;
45577
45583
  }
45578
45584
 
45579
- // src/config/roots.ts
45585
+ // src/config/pathList.ts
45580
45586
  import { resolve as resolve10 } from "node:path";
45581
- async function runRoots(argv, io) {
45587
+ function stripStateDir(argv) {
45588
+ const at2 = argv.indexOf("--state-dir");
45589
+ if (at2 < 0) return argv;
45590
+ return [...argv.slice(0, at2), ...argv.slice(at2 + (argv[at2 + 1] === void 0 ? 1 : 2))];
45591
+ }
45592
+ async function runPathList(raw, io, spec) {
45593
+ const argv = stripStateDir(raw);
45582
45594
  const sub = argv[0];
45583
45595
  const { config, unknown, corrupt } = await readDaemonConfig(io.stateDir);
45584
- const roots = Array.isArray(config.roots) ? config.roots : [];
45596
+ const stored = config[spec.key];
45597
+ const list = Array.isArray(stored) ? stored : [];
45585
45598
  if (corrupt && (sub === "add" || sub === "remove")) {
45586
45599
  io.err(`daemon.json in ${io.stateDir} is not valid JSON; fix or delete it before writing.`);
45587
45600
  return 2;
45588
45601
  }
45589
45602
  if (sub === "list") {
45590
- if (roots.length === 0) {
45591
- io.out("No working directories are configured. Add one with: corenel roots add <path>");
45603
+ if (list.length === 0) {
45604
+ io.out(spec.empty);
45592
45605
  return 0;
45593
45606
  }
45594
- for (const r2 of roots) io.out(r2);
45607
+ for (const p2 of list) io.out(p2);
45595
45608
  return 0;
45596
45609
  }
45597
45610
  if (sub === "add") {
45598
45611
  const path = argv[1];
45599
45612
  if (!path) {
45600
- io.err("corenel roots add needs a path.");
45613
+ io.err(`${spec.command} add needs a path.`);
45601
45614
  return 2;
45602
45615
  }
45603
45616
  const full = resolve10(path);
45604
- if (roots.some((r2) => resolve10(r2) === full)) {
45605
- io.out(`${full} is already a configured working directory.`);
45617
+ if (list.some((p2) => resolve10(p2) === full)) {
45618
+ io.out(`${full} is already a configured ${spec.noun}.`);
45606
45619
  return 0;
45607
45620
  }
45608
- await writeDaemonConfig(io.stateDir, { ...config, roots: [...roots, full] }, unknown);
45621
+ await writeDaemonConfig(io.stateDir, { ...config, [spec.key]: [...list, full] }, unknown);
45609
45622
  io.out(`Added ${full} to daemon.json. A running daemon picks this up on restart.`);
45610
45623
  return 0;
45611
45624
  }
45612
45625
  if (sub === "remove") {
45613
45626
  const path = argv[1];
45614
45627
  if (!path) {
45615
- io.err("corenel roots remove needs a path.");
45628
+ io.err(`${spec.command} remove needs a path.`);
45616
45629
  return 2;
45617
45630
  }
45618
45631
  const full = resolve10(path);
45619
- if (!roots.some((r2) => resolve10(r2) === full)) {
45620
- io.err(`${full} is not a configured working directory.`);
45632
+ if (!list.some((p2) => resolve10(p2) === full)) {
45633
+ io.err(`${full} is not a configured ${spec.noun}.`);
45621
45634
  return 2;
45622
45635
  }
45623
45636
  await writeDaemonConfig(
45624
45637
  io.stateDir,
45625
- { ...config, roots: roots.filter((r2) => resolve10(r2) !== full) },
45638
+ { ...config, [spec.key]: list.filter((p2) => resolve10(p2) !== full) },
45626
45639
  unknown
45627
45640
  );
45628
45641
  io.out(`Removed ${full} from daemon.json. A running daemon keeps it until restart.`);
45629
45642
  return 0;
45630
45643
  }
45631
- io.err(`Unknown subcommand "${sub ?? ""}". Use: corenel roots list | add <path> | remove <path>`);
45644
+ io.err(`Unknown subcommand "${sub ?? ""}". Use: ${spec.command} list | add <path> | remove <path>`);
45645
+ return 2;
45646
+ }
45647
+
45648
+ // src/config/roots.ts
45649
+ function runRoots(argv, io) {
45650
+ return runPathList(argv, io, {
45651
+ key: "roots",
45652
+ command: "corenel roots",
45653
+ noun: "working directory",
45654
+ empty: "No working directories are configured. Add one with: corenel roots add <path>"
45655
+ });
45656
+ }
45657
+
45658
+ // src/config/addUnder.ts
45659
+ function runAddUnder(argv, io) {
45660
+ return runPathList(argv, io, {
45661
+ key: "addUnder",
45662
+ command: "corenel add-under",
45663
+ noun: "area a client may add a root under",
45664
+ empty: "No areas are configured. Clients cannot add roots. Add one with: corenel add-under add <path>"
45665
+ });
45666
+ }
45667
+
45668
+ // src/config/keyTypes.ts
45669
+ var KEY_TYPES = {
45670
+ port: "number",
45671
+ host: "string",
45672
+ roots: "string[]",
45673
+ addUnder: "string[]",
45674
+ cloneUnder: "string[]",
45675
+ allowLan: "boolean",
45676
+ allowOrigins: "string[]",
45677
+ tlsCert: "string",
45678
+ tlsKey: "string",
45679
+ selfSigned: "boolean",
45680
+ tunnel: "string",
45681
+ tunnelName: "string",
45682
+ tunnelHostname: "string",
45683
+ endpoint: "string",
45684
+ allowShell: "boolean",
45685
+ keepTranscripts: "boolean",
45686
+ isolation: "string",
45687
+ msbBin: "string",
45688
+ guestImage: "string",
45689
+ maxChainDepth: "number",
45690
+ name: "string",
45691
+ appUrl: "string",
45692
+ defaultModel: "string"
45693
+ };
45694
+ var kebab = (k2) => k2.replace(/[A-Z]/g, (c2) => `-${c2.toLowerCase()}`);
45695
+ function resolveKeyName(input) {
45696
+ if (Object.prototype.hasOwnProperty.call(KEY_TYPES, input)) return input;
45697
+ for (const k2 of Object.keys(KEY_TYPES)) if (kebab(k2) === input) return k2;
45698
+ return null;
45699
+ }
45700
+ function isListKey(key) {
45701
+ return KEY_TYPES[key] === "string[]";
45702
+ }
45703
+ function coerceValue(key, raw) {
45704
+ const type = KEY_TYPES[key];
45705
+ if (!type) return { ok: false, reason: `"${key}" is not a daemon.json setting.` };
45706
+ if (type === "boolean") {
45707
+ if (raw === "true") return { ok: true, value: true };
45708
+ if (raw === "false") return { ok: true, value: false };
45709
+ return { ok: false, reason: `${key} must be true or false, not ${JSON.stringify(raw)}.` };
45710
+ }
45711
+ if (type === "number") {
45712
+ if (!/^-?\d+$/.test(raw)) return { ok: false, reason: `${key} must be a whole number, not ${JSON.stringify(raw)}.` };
45713
+ return { ok: true, value: Number(raw) };
45714
+ }
45715
+ return { ok: true, value: raw };
45716
+ }
45717
+
45718
+ // src/config/configCmd.ts
45719
+ var USAGE = "Use: corenel config list | get <key> | set <key> <value> | unset <key> | add <key> <value> | remove <key> <value>";
45720
+ function render(value) {
45721
+ if (Array.isArray(value)) return value.length ? value.join(", ") : "(none)";
45722
+ if (value === void 0) return "(unset)";
45723
+ return String(value);
45724
+ }
45725
+ function row(key, value, origin) {
45726
+ return ` ${key.padEnd(18)} ${render(value).padEnd(24)} (${origin})`;
45727
+ }
45728
+ function keyOrReason(name) {
45729
+ if (SECRET_KEYS.includes(name)) {
45730
+ return { reason: `${name} is a credential and does not belong in daemon.json. It goes in auth.json.` };
45731
+ }
45732
+ const key = resolveKeyName(name);
45733
+ if (!key) return { reason: `"${name}" is not a daemon.json setting. ${USAGE}` };
45734
+ return { key };
45735
+ }
45736
+ async function runConfig(raw, io) {
45737
+ const argv = stripStateDir(raw);
45738
+ const sub = argv[0];
45739
+ const { config, unknown, corrupt } = await readDaemonConfig(io.stateDir);
45740
+ const isWrite = sub === "set" || sub === "unset" || sub === "add" || sub === "remove";
45741
+ if (corrupt && isWrite) {
45742
+ io.err(`daemon.json in ${io.stateDir} is not valid JSON; fix or delete it before writing.`);
45743
+ return 2;
45744
+ }
45745
+ const read3 = (key) => {
45746
+ const value = config[key];
45747
+ return { value, origin: value === void 0 ? "default" : "file" };
45748
+ };
45749
+ const commit = async (next, said) => {
45750
+ await writeDaemonConfig(io.stateDir, next, unknown);
45751
+ io.out(`${said} A running daemon picks this up on restart.`);
45752
+ return 0;
45753
+ };
45754
+ if (sub === "list") {
45755
+ for (const key of Object.keys(KEY_TYPES).sort()) {
45756
+ const { value, origin } = read3(key);
45757
+ io.out(row(key, value, origin));
45758
+ }
45759
+ const extras = Object.keys(unknown);
45760
+ if (extras.length) {
45761
+ io.out("");
45762
+ io.out(" Keys this version does not manage (kept as they are):");
45763
+ for (const k2 of extras.sort()) io.out(` ${k2.padEnd(18)} ${render(unknown[k2])}`);
45764
+ }
45765
+ if (corrupt) io.err(`daemon.json in ${io.stateDir} is not valid JSON; these are the defaults, not what the file says.`);
45766
+ return 0;
45767
+ }
45768
+ if (sub === "get") {
45769
+ const name = argv[1];
45770
+ if (!name) {
45771
+ io.err(`corenel config get needs a key. ${USAGE}`);
45772
+ return 2;
45773
+ }
45774
+ const found = keyOrReason(name);
45775
+ if ("reason" in found) {
45776
+ io.err(found.reason);
45777
+ return 2;
45778
+ }
45779
+ const { value, origin } = read3(found.key);
45780
+ io.out(` ${render(value).padEnd(24)} (${origin})`);
45781
+ return 0;
45782
+ }
45783
+ if (sub === "set") {
45784
+ const name = argv[1];
45785
+ const values = argv.slice(2);
45786
+ if (!name) {
45787
+ io.err(`corenel config set needs a key. ${USAGE}`);
45788
+ return 2;
45789
+ }
45790
+ const found = keyOrReason(name);
45791
+ if ("reason" in found) {
45792
+ io.err(found.reason);
45793
+ return 2;
45794
+ }
45795
+ if (values.length === 0) {
45796
+ io.err(`corenel config set ${name} needs a value.`);
45797
+ return 2;
45798
+ }
45799
+ if (isListKey(found.key)) {
45800
+ await commit({ ...config, [found.key]: values }, `Set ${found.key} to ${values.join(", ")}.`);
45801
+ return 0;
45802
+ }
45803
+ if (values.length > 1) {
45804
+ io.err(`${found.key} holds one value; give just one.`);
45805
+ return 2;
45806
+ }
45807
+ const coerced = coerceValue(found.key, values[0]);
45808
+ if (!coerced.ok) {
45809
+ io.err(coerced.reason);
45810
+ return 2;
45811
+ }
45812
+ return commit({ ...config, [found.key]: coerced.value }, `Set ${found.key} to ${String(coerced.value)}.`);
45813
+ }
45814
+ if (sub === "unset") {
45815
+ const name = argv[1];
45816
+ if (!name) {
45817
+ io.err(`corenel config unset needs a key. ${USAGE}`);
45818
+ return 2;
45819
+ }
45820
+ const found = keyOrReason(name);
45821
+ if ("reason" in found) {
45822
+ io.err(found.reason);
45823
+ return 2;
45824
+ }
45825
+ const next = { ...config };
45826
+ delete next[found.key];
45827
+ return commit(next, `Unset ${found.key}; the default applies again.`);
45828
+ }
45829
+ if (sub === "add" || sub === "remove") {
45830
+ const name = argv[1];
45831
+ const value = argv[2];
45832
+ if (!name || !value) {
45833
+ io.err(`corenel config ${sub} needs a key and a value.`);
45834
+ return 2;
45835
+ }
45836
+ const found = keyOrReason(name);
45837
+ if ("reason" in found) {
45838
+ io.err(found.reason);
45839
+ return 2;
45840
+ }
45841
+ if (!isListKey(found.key)) {
45842
+ io.err(`${found.key} holds one value; change it with: corenel config set ${name} <value>`);
45843
+ return 2;
45844
+ }
45845
+ const raw2 = config[found.key];
45846
+ const list = Array.isArray(raw2) ? raw2 : [];
45847
+ if (sub === "add") {
45848
+ if (list.includes(value)) {
45849
+ io.out(`${value} is already in ${found.key}.`);
45850
+ return 0;
45851
+ }
45852
+ return commit({ ...config, [found.key]: [...list, value] }, `Added ${value} to ${found.key}.`);
45853
+ }
45854
+ if (!list.includes(value)) {
45855
+ io.err(`${value} is not in ${found.key}.`);
45856
+ return 2;
45857
+ }
45858
+ return commit(
45859
+ { ...config, [found.key]: list.filter((v2) => v2 !== value) },
45860
+ `Removed ${value} from ${found.key}.`
45861
+ );
45862
+ }
45863
+ io.err(`Unknown subcommand "${sub ?? ""}". ${USAGE}`);
45632
45864
  return 2;
45633
45865
  }
45634
45866
 
@@ -47253,7 +47485,7 @@ async function main() {
47253
47485
  await runAcpAgent(rawArgv.slice(1));
47254
47486
  return;
47255
47487
  }
47256
- if (rawArgv[0] === "setup" || rawArgv[0] === "roots" || rawArgv[0] === "doctor") {
47488
+ if (rawArgv[0] === "setup" || rawArgv[0] === "roots" || rawArgv[0] === "add-under" || rawArgv[0] === "config" || rawArgv[0] === "doctor") {
47257
47489
  const sub = rawArgv[0];
47258
47490
  const rest = rawArgv.slice(1);
47259
47491
  try {
@@ -47266,6 +47498,8 @@ async function main() {
47266
47498
  };
47267
47499
  if (sub === "setup") process.exit(await runSetup(rest, io));
47268
47500
  if (sub === "roots") process.exit(await runRoots(rest, io));
47501
+ if (sub === "add-under") process.exit(await runAddUnder(rest, io));
47502
+ if (sub === "config") process.exit(await runConfig(rest, io));
47269
47503
  const { args: flagArgs2, explicit: explicit2 } = parseArgsWithProvenance(rest);
47270
47504
  const { config, corrupt } = await readDaemonConfig(io.stateDir);
47271
47505
  const { args: args2, from, warnings } = layerConfig(flagArgs2, explicit2, config);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@corenel/sidecar",
3
- "version": "0.6.1",
3
+ "version": "0.6.2",
4
4
  "type": "module",
5
5
  "license": "Elastic-2.0",
6
6
  "description": "Prompd sidecar — a local capability server. Run it next to Prompd (prompd.app) so the browser app can reach your machine: local LLMs (Ollama/LM Studio/vLLM) without CORS, your filesystem, and (opt-in) shell.",