@corenel/sidecar 0.4.3 → 0.4.4

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 +73 -17
  2. package/package.json +2 -2
package/dist/cli.js CHANGED
@@ -22606,6 +22606,26 @@ async function loadOrCreateToken() {
22606
22606
  return token;
22607
22607
  }
22608
22608
 
22609
+ // ../harness/redact.ts
22610
+ var MASK = "[redacted]";
22611
+ var KEY_PATTERNS = [
22612
+ /\bsk-[A-Za-z0-9_*-]{8,}/g,
22613
+ // OpenAI + Anthropic: sk-, sk-proj-, sk-svcacct-, sk-ant-
22614
+ /\bgsk_[A-Za-z0-9_*-]{8,}/g,
22615
+ // Groq
22616
+ /\bAIza[A-Za-z0-9_*-]{8,}/g,
22617
+ // Google
22618
+ /\bxai-[A-Za-z0-9_*-]{8,}/g
22619
+ // xAI
22620
+ ];
22621
+ var BEARER = /\bBearer\s+[A-Za-z0-9._*-]+/gi;
22622
+ function redactSecrets(text) {
22623
+ let out = text;
22624
+ for (const re2 of KEY_PATTERNS) out = out.replace(re2, MASK);
22625
+ out = out.replace(BEARER, `Bearer ${MASK}`);
22626
+ return out;
22627
+ }
22628
+
22609
22629
  // ../harness/api/client.ts
22610
22630
  var ApiError = class extends Error {
22611
22631
  status;
@@ -22646,7 +22666,7 @@ var CorenelApiClient = class {
22646
22666
  body = text;
22647
22667
  }
22648
22668
  if (!res.ok) {
22649
- const message = String(rec(body).error || res.statusText || `HTTP ${res.status}`);
22669
+ const message = redactSecrets(String(rec(body).error || res.statusText || `HTTP ${res.status}`));
22650
22670
  if (res.status === 409 && "epoch" in rec(body)) {
22651
22671
  throw new LeaseConflict(res.status, message, body, Number(rec(body).epoch));
22652
22672
  }
@@ -23551,6 +23571,19 @@ var MAX_CHUNKS = 400;
23551
23571
  var MAX_CHARS = 2e5;
23552
23572
  var KEEP_EXITED = 20;
23553
23573
  var KILL_GRACE_MS = 3e3;
23574
+ function signalTree(child, sig) {
23575
+ if (process.platform !== "win32" && typeof child.pid === "number") {
23576
+ try {
23577
+ process.kill(-child.pid, sig);
23578
+ return;
23579
+ } catch {
23580
+ }
23581
+ }
23582
+ try {
23583
+ child.kill(sig);
23584
+ } catch {
23585
+ }
23586
+ }
23554
23587
  function createNodeProcs(opts) {
23555
23588
  const entries = /* @__PURE__ */ new Map();
23556
23589
  const subs = /* @__PURE__ */ new Set();
@@ -23594,7 +23627,12 @@ function createNodeProcs(opts) {
23594
23627
  const isWin = process.platform === "win32";
23595
23628
  const shell = isWin ? "cmd.exe" : "/bin/sh";
23596
23629
  const shellArgs = isWin ? ["/d", "/s", "/c", line] : ["-c", line];
23597
- const child = spawn2(shell, shellArgs, { cwd: dir, windowsHide: true, stdio: "pipe" });
23630
+ const child = spawn2(shell, shellArgs, {
23631
+ cwd: dir,
23632
+ windowsHide: true,
23633
+ stdio: "pipe",
23634
+ detached: !isWin
23635
+ });
23598
23636
  const info = {
23599
23637
  procId: nextId(),
23600
23638
  command: line,
@@ -23651,9 +23689,9 @@ function createNodeProcs(opts) {
23651
23689
  if (!e2) throw new Error(`no such process: ${procId}`);
23652
23690
  if (!e2.info.running || !e2.child) return;
23653
23691
  const child = e2.child;
23654
- child.kill("SIGTERM");
23692
+ signalTree(child, "SIGTERM");
23655
23693
  const timer = setTimeout(() => {
23656
- if (e2.info.running) child.kill("SIGKILL");
23694
+ if (e2.info.running) signalTree(child, "SIGKILL");
23657
23695
  }, KILL_GRACE_MS);
23658
23696
  timer.unref?.();
23659
23697
  child.once("close", () => clearTimeout(timer));
@@ -23667,12 +23705,7 @@ function createNodeProcs(opts) {
23667
23705
  shutdown() {
23668
23706
  closed = true;
23669
23707
  for (const e2 of entries.values()) {
23670
- if (e2.info.running && e2.child) {
23671
- try {
23672
- e2.child.kill("SIGKILL");
23673
- } catch {
23674
- }
23675
- }
23708
+ if (e2.info.running && e2.child) signalTree(e2.child, "SIGKILL");
23676
23709
  }
23677
23710
  subs.clear();
23678
23711
  }
@@ -28384,17 +28417,19 @@ async function workspaceRootsFor(dirName2, hostDir) {
28384
28417
  for (const entry of entries) {
28385
28418
  if (!entry.isDirectory()) continue;
28386
28419
  if (!WORKSPACE_ID_RE.test(entry.name)) continue;
28420
+ const wsDir = join8(hostDir, WORKSPACES_SEG, entry.name);
28387
28421
  out.push({
28388
28422
  owner: `${dirName2}/ws/${entry.name}`,
28389
- files: new NodeFileService(join8(hostDir, WORKSPACES_SEG, entry.name)),
28390
- root: "crew"
28423
+ files: new NodeFileService(wsDir),
28424
+ root: "crew",
28425
+ dir: wsDir
28391
28426
  });
28392
28427
  }
28393
28428
  return out;
28394
28429
  }
28395
28430
  async function listOwnerRoots(stateDir) {
28396
28431
  const roots = [
28397
- { owner: "", files: new NodeFileService(stateDir), root: "crew" }
28432
+ { owner: "", files: new NodeFileService(stateDir), root: "crew", dir: stateDir }
28398
28433
  ];
28399
28434
  let entries;
28400
28435
  try {
@@ -28411,7 +28446,7 @@ async function listOwnerRoots(stateDir) {
28411
28446
  } catch {
28412
28447
  continue;
28413
28448
  }
28414
- roots.push({ owner: dirName2, files: new NodeFileService(hostDir), root: "crew" });
28449
+ roots.push({ owner: dirName2, files: new NodeFileService(hostDir), root: "crew", dir: hostDir });
28415
28450
  roots.push(...await workspaceRootsFor(dirName2, hostDir));
28416
28451
  }
28417
28452
  return roots;
@@ -37069,7 +37104,9 @@ async function streamCompletion(client, params, signal, onText) {
37069
37104
  } catch (e2) {
37070
37105
  const err = e2;
37071
37106
  const raw = err?.error;
37072
- const detail = (typeof raw === "string" ? raw : raw?.error || raw?.message) || err?.message || String(e2);
37107
+ const detail = redactSecrets(
37108
+ String((typeof raw === "string" ? raw : raw?.error || raw?.message) || err?.message || String(e2))
37109
+ );
37073
37110
  const msg = typeof err?.status === "number" ? `Gateway ${err.status}: ${detail}` : detail;
37074
37111
  alog("stream:create-error", msg);
37075
37112
  throw new Error(msg);
@@ -39700,6 +39737,14 @@ function safeForLog(id) {
39700
39737
  function makeHostSync(opts) {
39701
39738
  const log = opts.log ?? (() => {
39702
39739
  });
39740
+ const woke = () => {
39741
+ if (!opts.onWrite) return;
39742
+ try {
39743
+ opts.onWrite();
39744
+ } catch (err) {
39745
+ log(`host-sync: onWrite failed: ${err instanceof Error ? err.message : String(err)}`);
39746
+ }
39747
+ };
39703
39748
  const recordFor = async (clientId) => {
39704
39749
  const rec5 = (await opts.manifest.list())[clientId];
39705
39750
  if (!rec5) throw new Error(`unknown client "${safeForLog(clientId)}" -- no hosts.json entry`);
@@ -39724,12 +39769,14 @@ function makeHostSync(opts) {
39724
39769
  await syncWrite(hostFilesFor(opts.stateDir, rec5.dirName), path, content);
39725
39770
  await ensureMaterialized(clientId, rec5);
39726
39771
  log(`host-sync: wrote ${rec5.dirName}/${path}`);
39772
+ woke();
39727
39773
  },
39728
39774
  async remove(clientId, path) {
39729
39775
  assertSyncPath(path);
39730
39776
  const rec5 = await recordFor(clientId);
39731
39777
  await syncRemove(hostFilesFor(opts.stateDir, rec5.dirName), path);
39732
39778
  log(`host-sync: removed ${rec5.dirName}/${path}`);
39779
+ woke();
39733
39780
  }
39734
39781
  };
39735
39782
  }
@@ -42086,7 +42133,16 @@ async function main() {
42086
42133
  await assertPortFree(probeAddress(args.host), args.port);
42087
42134
  await assertStateDirFree(sidecarSubdir(args.stateDir));
42088
42135
  await checkHostsDrift(args.stateDir, hosts, slog);
42089
- const hostSync = makeHostSync({ stateDir: args.stateDir, manifest: hosts, log: slog });
42136
+ const hostSync = makeHostSync({
42137
+ stateDir: args.stateDir,
42138
+ manifest: hosts,
42139
+ log: slog,
42140
+ // Same late-bound `core` holder as onScheduleSelf/onRunComplete below: a
42141
+ // synced definition is useless until a clock pass reads it, and with
42142
+ // nothing due the clock sleeps up to 15 minutes. Without this a deployed
42143
+ // schedule looks broken for a quarter of an hour.
42144
+ onWrite: () => core?.wake()
42145
+ });
42090
42146
  const attendance = makeAttendanceRegistry({ log: slog });
42091
42147
  const runs = makeRunHub({ log: slog });
42092
42148
  let core;
@@ -42138,7 +42194,7 @@ async function main() {
42138
42194
  if (args.daemon && runner) {
42139
42195
  const flipped = await runner.reconcilePendingOnBoot();
42140
42196
  if (flipped > 0) slog(`daemon: marked ${flipped} stale pending permission record(s) dead (daemon restarted)`);
42141
- const hostCrewDirs = (await listOwnerRoots(args.stateDir)).filter((r2) => r2.owner !== "").map((r2) => join15(hostsDirFor(args.stateDir, r2.owner), "crew"));
42197
+ const hostCrewDirs = (await listOwnerRoots(args.stateDir)).filter((r2) => r2.owner !== "").map((r2) => join15(r2.dir, r2.root));
42142
42198
  const watchDirs = [
42143
42199
  join15(args.stateDir, "crew"),
42144
42200
  ...args.roots.map((r2) => join15(r2, stateDirName(), "crew")),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@corenel/sidecar",
3
- "version": "0.4.3",
3
+ "version": "0.4.4",
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.",
@@ -37,8 +37,8 @@
37
37
  "tsx": "^4.19.2",
38
38
  "typescript": "^5.9.3",
39
39
  "@corenel/protocol": "0.4.2",
40
- "@corenel/harness": "0.4.1",
41
40
  "@corenel/tools-node": "0.2.2",
41
+ "@corenel/harness": "0.4.1",
42
42
  "@corenel/crew": "0.0.0"
43
43
  },
44
44
  "scripts": {