@cabane/companion 0.6.203 → 0.6.204

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/runtime.js CHANGED
@@ -167,25 +167,7 @@ var prepareHookSchema = z.object({
167
167
  // Wall-clock cap for the hook. Provisioning is slow (minutes), so the
168
168
  // default is generous; a hook that hangs past this is killed and the turn
169
169
  // fails with a clear timeout message rather than pinning the companion.
170
- timeoutMs: z.number().int().positive().optional(),
171
- // Re-invoke the hook when a prepared result already exists, in VALIDATE
172
- // mode: the cached result is handed back as `prepared` and stdout is
173
- // ignored, so the cwd cannot move. Its only power is to exit non-zero and
174
- // fail the turn. The hook resolves once per (conversation, agent), so a
175
- // later message asking for a different environment is otherwise silently
176
- // ignored; this lets a hook refuse it out loud.
177
- //
178
- // Default OFF: a hook that provisions unconditionally must not start
179
- // running on every turn because the companion upgraded.
180
- validateCached: z.boolean().optional(),
181
- // Independent operator-owned reporter. Receives sanitized failure metadata
182
- // on stdin; never re-enters this hook and cannot change the turn outcome.
183
- failureReporter: z.object({
184
- command: z.string().min(1),
185
- args: z.array(z.string()).optional(),
186
- env: z.record(z.string(), z.string()).optional(),
187
- timeoutMs: z.number().int().positive().max(3e4).optional()
188
- }).strict().optional()
170
+ timeoutMs: z.number().int().positive().optional()
189
171
  }).strict();
190
172
  var DEFAULT_TIMEOUT_MS = 10 * 6e4;
191
173
  var prepareResultSchema = z.object({
@@ -260,8 +242,7 @@ var companionConfigSchema = z2.object({
260
242
  // The DEVICE-LEVEL prepare hook, for every agent assigned here unless its own
261
243
  // `agents` row names one. Per-agent hooks alone make the config a second
262
244
  // silent roster: an agent nobody listed gets no hook and no error, and starts
263
- // in the operator's `$HOME` (an agent woke in `/home/joshed` this way on
264
- // 2026-08-17).
245
+ // in the operator's `$HOME`.
265
246
  prepareHook: prepareHookSchema.optional(),
266
247
  // `dashboardPort` and `autoOpen` are IGNORED by the CLI (no port, no browser)
267
248
  // but stay in the schema so an existing file still parses; the Electron shell
@@ -298,9 +279,10 @@ var companionConfigSchema = z2.object({
298
279
  root: z2.string().min(1).refine(isRootPath, { message: "must be an absolute path, or start with ~/" }).optional(),
299
280
  // An argv prefix the operator puts in front of every turn's runner: the companion starts
300
281
  // `<prefix…> <its own run-turn command…>` instead of the runner bare. What the prefix does
301
- // is the operator's (a box of their own making, ENG225); the companion knows nothing of it
282
+ // is the operator's (a container or VM per turn, say); the companion knows nothing of it
302
283
  // beyond handing the runner over, with the turn's inputs in its environment and the
303
- // credential and secrets on its stdin (`runner/launch.ts`, `boxed`).
284
+ // credential and secrets on its stdin (`runner/launch.ts`, `wrapped`). The README lists
285
+ // what a wrapper can rely on.
304
286
  runner: z2.object({
305
287
  command: z2.array(z2.string().min(1)).min(1)
306
288
  }).strict().optional()
@@ -312,33 +294,38 @@ function workRoot(cfg) {
312
294
  if (root.startsWith("~/")) return join4(homedir5(), root.slice(2));
313
295
  return root;
314
296
  }
315
- function retiredConfigKeys(raw) {
316
- if (!raw || typeof raw !== "object") return [];
317
- const obj = raw;
297
+ var RETIRED_ROW_KEYS = ["sandbox"];
298
+ var RETIRED_HOOK_KEYS = ["validateCached", "failureReporter"];
299
+ function isObject(value) {
300
+ return !!value && typeof value === "object" && !Array.isArray(value);
301
+ }
302
+ function splitRetired(raw) {
318
303
  const keys = [];
319
- if ("runners" in obj) keys.push("runners");
320
- const agents = obj.agents;
321
- if (agents && typeof agents === "object") {
322
- for (const [key, row] of Object.entries(agents)) {
323
- if (row && typeof row === "object" && "sandbox" in row) keys.push(`agents.${key}.sandbox`);
304
+ const without = (obj, names, path) => {
305
+ const out = {};
306
+ for (const [k, v] of Object.entries(obj)) {
307
+ if (names.includes(k)) keys.push(`${path}${k}`);
308
+ else out[k] = v;
309
+ }
310
+ return out;
311
+ };
312
+ const hook = (row, path) => isObject(row.prepareHook) ? { ...row, prepareHook: without(row.prepareHook, RETIRED_HOOK_KEYS, `${path}prepareHook.`) } : row;
313
+ const kept = hook(without(raw, ["runners"], ""), "");
314
+ if (isObject(kept.agents)) {
315
+ const agents = {};
316
+ for (const [key, row] of Object.entries(kept.agents)) {
317
+ const path = `agents.${key}.`;
318
+ agents[key] = isObject(row) ? hook(without(row, RETIRED_ROW_KEYS, path), path) : row;
324
319
  }
320
+ kept.agents = agents;
325
321
  }
326
- return keys;
322
+ return { keys, kept };
323
+ }
324
+ function retiredConfigKeys(raw) {
325
+ return isObject(raw) ? splitRetired(raw).keys : [];
327
326
  }
328
327
  function withoutRetiredKeys(raw) {
329
- if (retiredConfigKeys(raw).length === 0) return raw;
330
- const { runners: _runners, ...rest } = raw;
331
- if (!rest.agents || typeof rest.agents !== "object") return rest;
332
- const agents = {};
333
- for (const [key, row] of Object.entries(rest.agents)) {
334
- if (row && typeof row === "object" && "sandbox" in row) {
335
- const { sandbox: _sandbox, ...kept } = row;
336
- agents[key] = kept;
337
- } else {
338
- agents[key] = row;
339
- }
340
- }
341
- return { ...rest, agents };
328
+ return isObject(raw) ? splitRetired(raw).kept : raw;
342
329
  }
343
330
  function retiredConfigKeysOnDisk() {
344
331
  try {
@@ -1598,7 +1585,7 @@ var emptyHeartbeatStatus = () => ({
1598
1585
  });
1599
1586
 
1600
1587
  // src/supervisor.ts
1601
- import { hostname as hostname2 } from "os";
1588
+ import { hostname } from "os";
1602
1589
 
1603
1590
  // packages/agent-runtime/src/failure.ts
1604
1591
  import { z as z4 } from "zod";
@@ -6378,7 +6365,7 @@ function createCodexAdapter(deps = {}) {
6378
6365
  if (signal.aborted) return;
6379
6366
  if (compactions === null) {
6380
6367
  deps.onWarn?.(
6381
- "codex adapter: the thread's compaction count could not be read \u2014 re-sending the standing instructions (ENG210)",
6368
+ "codex adapter: the thread's compaction count could not be read \u2014 re-sending the standing instructions",
6382
6369
  { threadId: decision.resume }
6383
6370
  );
6384
6371
  } else if (decision.compactions === compactions) {
@@ -6388,7 +6375,7 @@ function createCodexAdapter(deps = {}) {
6388
6375
  };
6389
6376
  } else if (decision.compactions !== null && compactions > decision.compactions) {
6390
6377
  deps.onWarn?.(
6391
- "codex adapter: the thread compacted since the last turn \u2014 re-sending the standing instructions (ENG210)",
6378
+ "codex adapter: the thread compacted since the last turn \u2014 re-sending the standing instructions",
6392
6379
  {
6393
6380
  threadId: decision.resume,
6394
6381
  compactions,
@@ -7539,8 +7526,6 @@ var ConnectorHealthStore = class {
7539
7526
 
7540
7527
  // src/dispatcher.ts
7541
7528
  import { randomUUID as randomUUID4 } from "crypto";
7542
- import { existsSync as existsSync12, readdirSync as readdirSync2, statSync as statSync4 } from "fs";
7543
- import { join as join21 } from "path";
7544
7529
 
7545
7530
  // src/runner/launch.ts
7546
7531
  import { createInterface } from "readline";
@@ -7790,7 +7775,7 @@ function selfRunnerCommand() {
7790
7775
  function wrappedRunnerCommand(prefix, own) {
7791
7776
  return [...prefix ?? [], ...own];
7792
7777
  }
7793
- var BOXED_ENV_DROPPED = [
7778
+ var WRAPPED_ENV_DROPPED = [
7794
7779
  "ANTHROPIC_API_KEY",
7795
7780
  "CLAUDE_CODE_OAUTH_TOKEN",
7796
7781
  "CODEX_API_KEY",
@@ -7799,11 +7784,11 @@ var BOXED_ENV_DROPPED = [
7799
7784
  "DBUS_SESSION_BUS_ADDRESS",
7800
7785
  "XDG_RUNTIME_DIR"
7801
7786
  ];
7802
- function runnerExecEnv(base, boxed) {
7787
+ function runnerExecEnv(base, wrapped) {
7803
7788
  const env = {};
7804
7789
  for (const [k, v] of Object.entries(base)) {
7805
7790
  if (v === void 0) continue;
7806
- if (boxed && BOXED_ENV_DROPPED.includes(k)) continue;
7791
+ if (wrapped && WRAPPED_ENV_DROPPED.includes(k)) continue;
7807
7792
  env[k] = v;
7808
7793
  }
7809
7794
  return env;
@@ -8025,13 +8010,13 @@ async function runTurnInRunner(opts, launch, duties, payload, handleOpts) {
8025
8010
  return { ok: false, durationMs: durationMs2, reason: reason2 };
8026
8011
  }
8027
8012
  try {
8028
- const boxed = launch.boxed === true;
8029
- const env = runnerExecEnv(launch.env ?? process.env, boxed);
8013
+ const wrapped = launch.wrapped === true;
8014
+ const env = runnerExecEnv(launch.env ?? process.env, wrapped);
8030
8015
  const grants = minted.deviceGrants.length > 0 ? launch.grants?.(minted.deviceGrants) ?? {} : {};
8031
8016
  const input = {
8032
8017
  baseUrl: opts.baseUrl,
8033
8018
  credential: minted.credential,
8034
- ...boxed ? { secrets: launch.secrets?.() ?? {} } : {},
8019
+ ...wrapped ? { secrets: launch.secrets?.() ?? {} } : {},
8035
8020
  ...Object.keys(grants).length > 0 ? { grants } : {},
8036
8021
  dispatch: payload,
8037
8022
  turnId,
@@ -8105,7 +8090,7 @@ async function runTurnInRunner(opts, launch, duties, payload, handleOpts) {
8105
8090
  locks?.release(lockOwner(event.id));
8106
8091
  return;
8107
8092
  case "process_group":
8108
- if (!boxed) groups.push(event.pgid);
8093
+ if (!wrapped) groups.push(event.pgid);
8109
8094
  return;
8110
8095
  case "remote_session":
8111
8096
  remote.push({ serverUrl: event.serverUrl, sessionId: event.sessionId });
@@ -8180,7 +8165,7 @@ async function runTurnInRunner(opts, launch, duties, payload, handleOpts) {
8180
8165
 
8181
8166
  // src/turn-execution.ts
8182
8167
  import { createHash as createHash2, randomUUID as randomUUID3 } from "crypto";
8183
- import { mkdirSync as mkdirSync9 } from "fs";
8168
+ import { existsSync as existsSync12, mkdirSync as mkdirSync9 } from "fs";
8184
8169
 
8185
8170
  // src/grants.ts
8186
8171
  import { existsSync as existsSync9, readFileSync as readFileSync7 } from "fs";
@@ -8234,7 +8219,7 @@ function loadGrantsFile(report) {
8234
8219
  const result = grantsFileSchema.safeParse(parsed);
8235
8220
  if (!result.success) {
8236
8221
  report.unreadable(
8237
- `${path} must map a secret's variable name to an object of "VARIABLE": "value" pairs (e.g. { "HAS_PROD_ACCESS": { "RENDER_API_KEY": "rnd_\u2026" } }).`
8222
+ `${path} must map a secret's variable name to an object of "VARIABLE": "value" pairs (e.g. { "HAS_STAGING_DB": { "DATABASE_URL": "postgres://\u2026" } }).`
8238
8223
  );
8239
8224
  return {};
8240
8225
  }
@@ -8277,10 +8262,6 @@ import { homedir as homedir7 } from "os";
8277
8262
  import { join as join17 } from "path";
8278
8263
  import { createInterface as createInterface2 } from "readline";
8279
8264
 
8280
- // src/prepare-failure.ts
8281
- import { spawn as spawn3 } from "child_process";
8282
- import { hostname } from "os";
8283
-
8284
8265
  // src/prepared.ts
8285
8266
  import { mkdirSync as mkdirSync7, readFileSync as readFileSync8, rmSync as rmSync5, writeFileSync as writeFileSync5, existsSync as existsSync10 } from "fs";
8286
8267
  import { join as join18 } from "path";
@@ -8356,7 +8337,7 @@ function requiredSecretNames(mcpServers) {
8356
8337
  }
8357
8338
 
8358
8339
  // src/harness-usable.ts
8359
- import { spawn as spawn4 } from "child_process";
8340
+ import { spawn as spawn3 } from "child_process";
8360
8341
 
8361
8342
  // src/harness-versions.ts
8362
8343
  var EMPTY = { claudeCode: null, opencode: null, codex: null };
@@ -8459,7 +8440,7 @@ function runBounded(path, args, env) {
8459
8440
  };
8460
8441
  let child;
8461
8442
  try {
8462
- child = spawn4(path, args, { stdio: ["ignore", "pipe", "pipe"], env });
8443
+ child = spawn3(path, args, { stdio: ["ignore", "pipe", "pipe"], env });
8463
8444
  } catch {
8464
8445
  resolve({ code: null, output: "", error: "spawn" });
8465
8446
  return;
@@ -8626,7 +8607,7 @@ function hostReport() {
8626
8607
  }
8627
8608
 
8628
8609
  // src/providers/local-process.ts
8629
- import { spawn as spawn5 } from "child_process";
8610
+ import { spawn as spawn4 } from "child_process";
8630
8611
  import { constants as constants2 } from "os";
8631
8612
  var DEFAULT_KILL_GRACE_MS = 3e4;
8632
8613
  var DEFAULT_REAP_GRACE_MS = 3e3;
@@ -8637,7 +8618,7 @@ function exitCode(code, signal) {
8637
8618
  }
8638
8619
  function createLocalProcessProvider(opts = {}) {
8639
8620
  const killGraceMs = opts.killGraceMs ?? DEFAULT_KILL_GRACE_MS;
8640
- const spawnFn = opts.spawnFn ?? spawn5;
8621
+ const spawnFn = opts.spawnFn ?? spawn4;
8641
8622
  const reapGraceMs = opts.reapGraceMs ?? DEFAULT_REAP_GRACE_MS;
8642
8623
  const killFn = opts.killFn ?? ((pid, signal) => process.kill(pid, signal));
8643
8624
  const groupAlive = (pgid) => {
@@ -8841,7 +8822,7 @@ function checkReason(check) {
8841
8822
 
8842
8823
  // src/harness-copy.ts
8843
8824
  import { homedir as homedir8 } from "os";
8844
- import { join as join22 } from "path";
8825
+ import { join as join21 } from "path";
8845
8826
  var HARNESS_LABELS = {
8846
8827
  "claude-code": "Claude Code",
8847
8828
  codex: "Codex",
@@ -8855,7 +8836,7 @@ function failureText(runtime, reason) {
8855
8836
  case "spawn":
8856
8837
  return `Couldn't check whether ${label} is signed in: Cabane's bundled ${label} wouldn't start. Repair it with ${repairSteps()} and try again.${spaced(repairCost())}`;
8857
8838
  case "config":
8858
- return `Couldn't check whether ${label} is signed in: its configuration file didn't load${runtime === "codex" ? ` (${tildePath(join22(homedir8(), ".codex", "config.toml"))})` : ""}. Fix it, then try again.`;
8839
+ return `Couldn't check whether ${label} is signed in: its configuration file didn't load${runtime === "codex" ? ` (${tildePath(join21(homedir8(), ".codex", "config.toml"))})` : ""}. Fix it, then try again.`;
8859
8840
  case "unreadable":
8860
8841
  return `Couldn't check whether ${label} is signed in: it answered in a way Cabane couldn't read. Try again, and if it keeps happening, update Cabane.`;
8861
8842
  }
@@ -9114,13 +9095,13 @@ var DispatchClaims = class {
9114
9095
  import {
9115
9096
  existsSync as existsSync14,
9116
9097
  mkdirSync as mkdirSync10,
9117
- readdirSync as readdirSync3,
9098
+ readdirSync as readdirSync2,
9118
9099
  readFileSync as readFileSync11,
9119
9100
  renameSync as renameSync5,
9120
9101
  rmSync as rmSync7,
9121
9102
  writeFileSync as writeFileSync6
9122
9103
  } from "fs";
9123
- import { join as join23 } from "path";
9104
+ import { join as join22 } from "path";
9124
9105
  var MAX_ENTRIES = 2e3;
9125
9106
  var MAX_AGE_MS = 24 * 60 * 60 * 1e3;
9126
9107
  var Outbox = class {
@@ -9133,10 +9114,10 @@ var Outbox = class {
9133
9114
  // Resolved lazily (per call) so tests that swap HOME between
9134
9115
  // cases route writes at the right tmpdir.
9135
9116
  dir() {
9136
- return join23(cabaneDir(), "outbox", encodeURIComponent(this.workspaceId));
9117
+ return join22(cabaneDir(), "outbox", encodeURIComponent(this.workspaceId));
9137
9118
  }
9138
9119
  fileFor(turnId, seq) {
9139
- return join23(this.dir(), `${encodeURIComponent(turnId)}__${seq}.json`);
9120
+ return join22(this.dir(), `${encodeURIComponent(turnId)}__${seq}.json`);
9140
9121
  }
9141
9122
  // Persist a commit for later draining. Atomic (temp file + rename) so a
9142
9123
  // concurrent `list()` never reads a half-written entry, then enforces the
@@ -9171,14 +9152,14 @@ var Outbox = class {
9171
9152
  if (!existsSync14(dir2)) return [];
9172
9153
  let names;
9173
9154
  try {
9174
- names = readdirSync3(dir2);
9155
+ names = readdirSync2(dir2);
9175
9156
  } catch {
9176
9157
  return [];
9177
9158
  }
9178
9159
  const entries = [];
9179
9160
  for (const name of names) {
9180
9161
  if (!name.endsWith(".json")) continue;
9181
- const full = join23(dir2, name);
9162
+ const full = join22(dir2, name);
9182
9163
  try {
9183
9164
  const parsed = JSON.parse(readFileSync11(full, "utf8"));
9184
9165
  if (parsed && typeof parsed.turnId === "string" && typeof parsed.seq === "number" && typeof parsed.path === "string") {
@@ -9215,7 +9196,7 @@ var Outbox = class {
9215
9196
  maxSeqForTurn(turnId) {
9216
9197
  const dir2 = this.dir();
9217
9198
  if (!existsSync14(dir2)) return 0;
9218
- const names = readdirSync3(dir2);
9199
+ const names = readdirSync2(dir2);
9219
9200
  const prefix = `${encodeURIComponent(turnId)}__`;
9220
9201
  let max = 0;
9221
9202
  for (const name of names) {
@@ -9236,7 +9217,7 @@ var Outbox = class {
9236
9217
  const dir2 = this.dir();
9237
9218
  if (!existsSync14(dir2)) return 0;
9238
9219
  try {
9239
- return readdirSync3(dir2).filter((n) => n.endsWith(".json")).length;
9220
+ return readdirSync2(dir2).filter((n) => n.endsWith(".json")).length;
9240
9221
  } catch {
9241
9222
  return 0;
9242
9223
  }
@@ -9400,9 +9381,9 @@ var SseSubscriber = class {
9400
9381
  };
9401
9382
 
9402
9383
  // src/updater.ts
9403
- import { spawn as spawn6 } from "child_process";
9384
+ import { spawn as spawn5 } from "child_process";
9404
9385
  import { copyFileSync as copyFileSync2, existsSync as existsSync16, mkdirSync as mkdirSync14, renameSync as renameSync9, rmSync as rmSync10 } from "fs";
9405
- import { dirname as dirname11, join as join27 } from "path";
9386
+ import { dirname as dirname11, join as join26 } from "path";
9406
9387
 
9407
9388
  // src/boot-rule.ts
9408
9389
  import {
@@ -9414,7 +9395,7 @@ import {
9414
9395
  symlinkSync,
9415
9396
  writeFileSync as writeFileSync7
9416
9397
  } from "fs";
9417
- import { dirname as dirname8, join as join24 } from "path";
9398
+ import { dirname as dirname8, join as join23 } from "path";
9418
9399
  var UNCONFIRMED_WINDOW_MS = 10 * 6e4;
9419
9400
  var MAX_STAGE_ATTEMPTS = 3;
9420
9401
  function superseded(pending, ...running) {
@@ -9441,32 +9422,32 @@ import {
9441
9422
  lstatSync,
9442
9423
  mkdirSync as mkdirSync12,
9443
9424
  readFileSync as readFileSync13,
9444
- readdirSync as readdirSync4,
9425
+ readdirSync as readdirSync3,
9445
9426
  realpathSync as realpathSync5,
9446
9427
  renameSync as renameSync7,
9447
9428
  rmSync as rmSync9,
9448
9429
  symlinkSync as symlinkSync2
9449
9430
  } from "fs";
9450
- import { dirname as dirname9, join as join25 } from "path";
9431
+ import { dirname as dirname9, join as join24 } from "path";
9451
9432
  import { fileURLToPath as fileURLToPath5 } from "url";
9452
9433
  function versionsDir() {
9453
- return join25(cabaneDir(), "versions");
9434
+ return join24(cabaneDir(), "versions");
9454
9435
  }
9455
9436
  function currentLink() {
9456
- return join25(cabaneDir(), "current");
9437
+ return join24(cabaneDir(), "current");
9457
9438
  }
9458
9439
  function bootGuardPath() {
9459
- return join25(cabaneDir(), "boot-guard.mjs");
9440
+ return join24(cabaneDir(), "boot-guard.mjs");
9460
9441
  }
9461
9442
  function versionPackageRoot(version) {
9462
- return join25(versionsDir(), version, "node_modules", "@cabane", "companion");
9443
+ return join24(versionsDir(), version, "node_modules", "@cabane", "companion");
9463
9444
  }
9464
9445
  function ownPackageRoot(moduleUrl = import.meta.url) {
9465
9446
  return dirname9(dirname9(fileURLToPath5(moduleUrl)));
9466
9447
  }
9467
9448
  function packageVersion(root) {
9468
9449
  try {
9469
- const pkg2 = JSON.parse(readFileSync13(join25(root, "package.json"), "utf8"));
9450
+ const pkg2 = JSON.parse(readFileSync13(join24(root, "package.json"), "utf8"));
9470
9451
  return typeof pkg2.version === "string" ? pkg2.version : null;
9471
9452
  } catch {
9472
9453
  return null;
@@ -9475,7 +9456,7 @@ function packageVersion(root) {
9475
9456
  function currentRoot() {
9476
9457
  try {
9477
9458
  const root = realpathSync5(currentLink());
9478
- return existsSync15(join25(root, "dist", "cli.js")) ? root : null;
9459
+ return existsSync15(join24(root, "dist", "cli.js")) ? root : null;
9479
9460
  } catch {
9480
9461
  return null;
9481
9462
  }
@@ -9496,9 +9477,9 @@ function pruneVersions(keep) {
9496
9477
  const dir2 = versionsDir();
9497
9478
  if (!existsSync15(dir2)) return [];
9498
9479
  const removed = [];
9499
- for (const name of readdirSync4(dir2)) {
9480
+ for (const name of readdirSync3(dir2)) {
9500
9481
  if (keep.includes(name)) continue;
9501
- rmSync9(join25(dir2, name), { recursive: true, force: true });
9482
+ rmSync9(join24(dir2, name), { recursive: true, force: true });
9502
9483
  removed.push(name);
9503
9484
  }
9504
9485
  return removed;
@@ -9517,7 +9498,7 @@ function compareVersions(a, b) {
9517
9498
 
9518
9499
  // src/update-state.ts
9519
9500
  import { mkdirSync as mkdirSync13, readFileSync as readFileSync14, renameSync as renameSync8, writeFileSync as writeFileSync8 } from "fs";
9520
- import { dirname as dirname10, join as join26 } from "path";
9501
+ import { dirname as dirname10, join as join25 } from "path";
9521
9502
  import { z as z18 } from "zod";
9522
9503
  var resultSchema = z18.object({
9523
9504
  kind: z18.enum(["updated", "rolled_back", "failed"]),
@@ -9541,7 +9522,7 @@ var stateSchema = z18.object({
9541
9522
  failed: z18.object({ version: z18.string(), attempts: z18.number().int(), at: z18.string() }).optional()
9542
9523
  });
9543
9524
  function updateStatePath(dir2 = cabaneDir()) {
9544
- return join26(dir2, "update.json");
9525
+ return join25(dir2, "update.json");
9545
9526
  }
9546
9527
  function readUpdateState(path = updateStatePath()) {
9547
9528
  try {
@@ -9590,7 +9571,7 @@ function rollBack(pending, reason, now = /* @__PURE__ */ new Date()) {
9590
9571
  return updateUpdateState((state) => rolledBackState(state, pending, reason, now));
9591
9572
  }
9592
9573
  function writeBootGuard(root = ownPackageRoot()) {
9593
- const built = join27(root, "dist", "boot-guard.js");
9574
+ const built = join26(root, "dist", "boot-guard.js");
9594
9575
  if (!existsSync16(built)) return false;
9595
9576
  const target = bootGuardPath();
9596
9577
  mkdirSync14(dirname11(target), { recursive: true });
@@ -9607,7 +9588,7 @@ var runProcess = (command, args, opts = {}) => new Promise((resolve) => {
9607
9588
  let stderr = "";
9608
9589
  let child;
9609
9590
  try {
9610
- child = spawn6(command, [...args], {
9591
+ child = spawn5(command, [...args], {
9611
9592
  stdio: ["ignore", "pipe", "pipe"],
9612
9593
  env: opts.env ?? process.env
9613
9594
  });
@@ -9630,17 +9611,17 @@ var runProcess = (command, args, opts = {}) => new Promise((resolve) => {
9630
9611
  async function stageVersion(version, harnesses, deps = {}) {
9631
9612
  const run = deps.run ?? runProcess;
9632
9613
  const node = deps.execPath ?? process.execPath;
9633
- const target = join27(versionsDir(), version);
9614
+ const target = join26(versionsDir(), version);
9634
9615
  const placed = versionPackageRoot(version);
9635
9616
  if (existsSync16(placed)) {
9636
9617
  if (!await verifyInstall(placed, version, harnesses, { run, execPath: node }))
9637
9618
  return { ok: true, root: placed };
9638
9619
  }
9639
- const npm = join27(dirname11(node), "npm");
9620
+ const npm = join26(dirname11(node), "npm");
9640
9621
  if (!existsSync16(npm))
9641
9622
  return { ok: false, reason: `there is no npm beside Node at ${dirname11(node)}` };
9642
9623
  mkdirSync14(versionsDir(), { recursive: true });
9643
- const staging = join27(versionsDir(), `.${version}.staging-${process.pid}`);
9624
+ const staging = join26(versionsDir(), `.${version}.staging-${process.pid}`);
9644
9625
  rmSync10(staging, { recursive: true, force: true });
9645
9626
  const installed = await run(
9646
9627
  npm,
@@ -9669,7 +9650,7 @@ async function stageVersion(version, harnesses, deps = {}) {
9669
9650
  return { ok: false, reason: `version ${version} isn't published yet`, unpublished: true };
9670
9651
  return { ok: false, reason: `npm couldn't install it: ${lastLine(installed.stderr)}` };
9671
9652
  }
9672
- const root = join27(staging, "node_modules", "@cabane", "companion");
9653
+ const root = join26(staging, "node_modules", "@cabane", "companion");
9673
9654
  const verdict = await verifyInstall(root, version, harnesses, { run, execPath: node });
9674
9655
  if (verdict) {
9675
9656
  rmSync10(staging, { recursive: true, force: true });
@@ -9681,7 +9662,7 @@ async function stageVersion(version, harnesses, deps = {}) {
9681
9662
  }
9682
9663
  async function verifyInstall(root, version, harnesses, deps) {
9683
9664
  if (packageVersion(root) !== version) return `the installed package isn't version ${version}`;
9684
- const answered = await deps.run(deps.execPath, [join27(root, "dist", "bin.js"), "--version"], {
9665
+ const answered = await deps.run(deps.execPath, [join26(root, "dist", "bin.js"), "--version"], {
9685
9666
  timeoutMs: 6e4,
9686
9667
  env: { ...process.env, CABANE_LAUNCH_SELF: "1" }
9687
9668
  });
@@ -9689,7 +9670,7 @@ async function verifyInstall(root, version, harnesses, deps) {
9689
9670
  return `it doesn't start: ${lastLine(answered.stderr) || "no version printed"}`;
9690
9671
  }
9691
9672
  if (harnesses.length === 0) return null;
9692
- const probed = await deps.run(deps.execPath, [join27(root, "dist", "postinstall.js"), "--json"], {
9673
+ const probed = await deps.run(deps.execPath, [join26(root, "dist", "postinstall.js"), "--json"], {
9693
9674
  timeoutMs: 6e4
9694
9675
  });
9695
9676
  let resolutions = {};
@@ -10106,13 +10087,13 @@ var CompanionSupervisor = class {
10106
10087
  if (this.stopped) return;
10107
10088
  this.log.info(
10108
10089
  { protocolVersion: TURN_PROTOCOL_VERSION, version: COMPANION_VERSION },
10109
- `Companion ${COMPANION_VERSION} starting on ${this.config.deviceLabel ?? hostname2()}`
10090
+ `Companion ${COMPANION_VERSION} starting on ${this.config.deviceLabel ?? hostname()}`
10110
10091
  );
10111
10092
  const retired = retiredConfigKeysOnDisk();
10112
10093
  if (retired.length > 0) {
10113
10094
  this.log.warn(
10114
10095
  { keys: retired },
10115
- `config.json: ${retired.join(", ")} ${retired.length === 1 ? "is" : "are"} no longer read and can be removed. The companion does no sandboxing, and every turn runs in a child process of its own.`
10096
+ `config.json: ${retired.join(", ")} ${retired.length === 1 ? "is" : "are"} no longer read and can be removed.`
10116
10097
  );
10117
10098
  }
10118
10099
  if (this.config.deviceToken) {
@@ -10152,7 +10133,7 @@ var CompanionSupervisor = class {
10152
10133
  log: this.log,
10153
10134
  lastEventId: null,
10154
10135
  onOpen: () => {
10155
- this.log.info(`Connected to Cabane as ${this.hub.statusJson().device_label ?? hostname2()}`);
10136
+ this.log.info(`Connected to Cabane as ${this.hub.statusJson().device_label ?? hostname()}`);
10156
10137
  this.deviceConnected = true;
10157
10138
  for (const wr of this.workspaces.values()) {
10158
10139
  this.hub.setConnected(wr.workspaceId, true);
@@ -10698,9 +10679,9 @@ var CompanionSupervisor = class {
10698
10679
  this.runnerCommand ?? selfRunnerCommand()
10699
10680
  ),
10700
10681
  ...this.config.runner?.command ? {
10701
- boxed: true,
10682
+ wrapped: true,
10702
10683
  secrets: () => loadSecretValuesTolerant(
10703
- (m) => this.log.warn({ err: m }, "Could not read the secrets file for a boxed turn.")
10684
+ (m) => this.log.warn({ err: m }, "Could not read the secrets file for a wrapped turn.")
10704
10685
  )
10705
10686
  } : {},
10706
10687
  // Read per dispatch, for the secret variables its mint named and no others.
@@ -11379,9 +11360,9 @@ async function waitForBoundedHeartbeat(heartbeat) {
11379
11360
  }
11380
11361
  function defaultReexec() {
11381
11362
  clearRuntimeState();
11382
- void import("child_process").then(({ spawn: spawn7 }) => {
11363
+ void import("child_process").then(({ spawn: spawn6 }) => {
11383
11364
  try {
11384
- const child = spawn7(process.execPath, process.argv.slice(1), {
11365
+ const child = spawn6(process.execPath, process.argv.slice(1), {
11385
11366
  stdio: "inherit",
11386
11367
  detached: false
11387
11368
  });
@@ -11452,9 +11433,9 @@ function handleUncaught(log, err, origin) {
11452
11433
 
11453
11434
  // src/crash-marker.ts
11454
11435
  import { existsSync as existsSync17, mkdirSync as mkdirSync15, readFileSync as readFileSync15, rmSync as rmSync11, writeFileSync as writeFileSync9 } from "fs";
11455
- import { join as join28 } from "path";
11436
+ import { join as join27 } from "path";
11456
11437
  function crashMarkerPath() {
11457
- return join28(cabaneDir(), "last-error.json");
11438
+ return join27(cabaneDir(), "last-error.json");
11458
11439
  }
11459
11440
  function recordCrash(rec) {
11460
11441
  try {
@@ -11474,7 +11455,7 @@ function clearCrash() {
11474
11455
  // src/stray-companion.ts
11475
11456
  import { spawnSync } from "child_process";
11476
11457
  import { readFileSync as readFileSync16 } from "fs";
11477
- import { join as join29 } from "path";
11458
+ import { join as join28 } from "path";
11478
11459
  var COMPANION_ENTRY = /@cabane\/companion\/|cabane-companion|(^|[\s/])cabane\s|\.cabane\/(versions|current|boot-guard)/;
11479
11460
  var START = /\sstart(\s|$)/;
11480
11461
  function companionStarts(psOutput) {
@@ -11491,7 +11472,7 @@ function companionStarts(psOutput) {
11491
11472
  }
11492
11473
  function stateDirOf(env) {
11493
11474
  const home = env.CABANE_COMPANION_HOME || env.HOME;
11494
- return home ? join29(home, ".cabane") : null;
11475
+ return home ? join28(home, ".cabane") : null;
11495
11476
  }
11496
11477
  function envFromPsE(output, command) {
11497
11478
  const line = output.replace(/\n$/, "");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cabane/companion",
3
- "version": "0.6.203",
3
+ "version": "0.6.204",
4
4
  "type": "module",
5
5
  "description": "The Cabane Companion (headless): connect an agent on your machine to your Cabane workspace as a responder — drive work against your own codebase, files, and MCP servers without putting any of it in Cabane.",
6
6
  "license": "UNLICENSED",