@cabane/companion 0.6.237 → 0.6.238

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/cli.js CHANGED
@@ -724,7 +724,7 @@ var init_config = __esm({
724
724
  // the rest of the config; `pair` always writes one.
725
725
  deviceToken: z2.string().optional(),
726
726
  // Identity hints, learned from the device flow and refreshed on the first
727
- // assignments pull. Cosmetic — used for `status`/dashboard display only.
727
+ // assignments pull. Cosmetic — used for `status` display only.
728
728
  deviceId: z2.string().optional(),
729
729
  deviceLabel: z2.string().optional(),
730
730
  // Optional per-agent machine-local overrides (cwd / prepareHook), keyed by
@@ -736,9 +736,8 @@ var init_config = __esm({
736
736
  // silent roster: an agent nobody listed gets no hook and no error, and starts
737
737
  // in the operator's `$HOME`.
738
738
  prepareHook: prepareHookSchema.optional(),
739
- // The CLI ignores both dashboard settings. Desktop uses `dashboardPort`;
740
- // `autoOpen` remains parseable for older config files but no longer controls
741
- // startup. `logLevel` is pino's level, live-editable.
739
+ // Nothing reads either dashboard setting any more; both stay parseable so an
740
+ // older config file still loads. `logLevel` is pino's level, live-editable.
742
741
  dashboardPort: z2.number().int().min(1).max(65535).optional(),
743
742
  autoOpen: z2.boolean().optional(),
744
743
  logLevel: z2.enum(["warn", "info", "debug"]).optional(),
@@ -7434,10 +7433,6 @@ var init_turn_committer = __esm({
7434
7433
  get lastMessageSeq() {
7435
7434
  return this.pump.lastMessageSeq;
7436
7435
  }
7437
- // The turn's final reply text, or null if none landed.
7438
- get replyBody() {
7439
- return this.pump.replyBody;
7440
- }
7441
7436
  get finalSource() {
7442
7437
  return this.pump.finalSource;
7443
7438
  }
@@ -7815,7 +7810,6 @@ var init_turn_execution = __esm({
7815
7810
  );
7816
7811
  }
7817
7812
  const durationMs = Date.now() - startedAt;
7818
- this.supervisor.notifyEnd({ id: payload.messageId, ok: false, durationMs, reason });
7819
7813
  return { ok: false, durationMs, reason, runtime: this.turnContext?.runtime };
7820
7814
  }
7821
7815
  // The admitted turn holds the conversation's lease, so the clear must NAME the
@@ -7854,7 +7848,6 @@ var init_turn_execution = __esm({
7854
7848
  }
7855
7849
  }
7856
7850
  const durationMs = Date.now() - startedAt;
7857
- this.supervisor.notifyEnd({ id: payload.messageId, ok: false, durationMs, reason });
7858
7851
  return { ok: false, durationMs, reason, runtime: this.turnContext?.runtime };
7859
7852
  }
7860
7853
  async fetchContext() {
@@ -7963,11 +7956,7 @@ var init_turn_execution = __esm({
7963
7956
  turnLog.debug({ role: message2.role }, "dispatcher: trigger role not dispatchable \u2014 skipping");
7964
7957
  throw this.concluded("unexpected_role", UNEXPECTED_ROLE_REASON);
7965
7958
  }
7966
- this.supervisor.notifyStart({
7967
- id: this.dispatchId,
7968
- conversationId: payload.conversationId,
7969
- message: message2.body
7970
- });
7959
+ this.supervisor.notifyStart({ id: this.dispatchId, conversationId: payload.conversationId });
7971
7960
  }
7972
7961
  async resolveSecrets() {
7973
7962
  const { turnLog } = this;
@@ -8736,7 +8725,6 @@ var init_turn_execution = __esm({
8736
8725
  const o = this.outcome;
8737
8726
  const { startedAt, turnLog } = this;
8738
8727
  const durationMs = Date.now() - startedAt;
8739
- const finalReplyBody = this.committer.replyBody;
8740
8728
  if (this.transcript) {
8741
8729
  this.transcript.close({
8742
8730
  ok: o.okResult,
@@ -8749,21 +8737,9 @@ var init_turn_execution = __esm({
8749
8737
  }
8750
8738
  if (o.okResult) {
8751
8739
  turnLog.debug({ durationMs }, "dispatcher: turn end (ok)");
8752
- this.supervisor.notifyEnd({
8753
- id: this.dispatchId,
8754
- ok: true,
8755
- durationMs,
8756
- ...finalReplyBody ? { reply: finalReplyBody.trim() } : {}
8757
- });
8758
8740
  return { ok: true, durationMs };
8759
8741
  }
8760
8742
  turnLog.debug({ durationMs, reason: o.resultReason }, "dispatcher: turn end (not ok)");
8761
- this.supervisor.notifyEnd({
8762
- id: this.dispatchId,
8763
- ok: false,
8764
- durationMs,
8765
- ...o.resultReason ? { reason: o.resultReason } : {}
8766
- });
8767
8743
  return {
8768
8744
  ok: false,
8769
8745
  durationMs,
@@ -9269,8 +9245,7 @@ async function runTurn(env, deps) {
9269
9245
  emit({ cabaneRunner: "session_write_notice" });
9270
9246
  return true;
9271
9247
  },
9272
- notifyStart: (info) => emit({ cabaneRunner: "start", ...info }),
9273
- notifyEnd: (info) => emit({ cabaneRunner: "end", ...info })
9248
+ notifyStart: (info) => emit({ cabaneRunner: "start", ...info })
9274
9249
  };
9275
9250
  let outbox;
9276
9251
  const opts = runnerTurnOptions(input, log2, emit, {
@@ -10322,7 +10297,6 @@ init_config();
10322
10297
  init_pairing();
10323
10298
  init_errors();
10324
10299
  init_install_kind();
10325
- init_errors();
10326
10300
  function resolvePairBaseUrl(server) {
10327
10301
  const raw = (server ?? process.env.CABANE_BASE_URL ?? "").trim();
10328
10302
  if (!raw) throw new NoPairAddressError();
@@ -10371,7 +10345,6 @@ function isDevicePaired() {
10371
10345
  init_config();
10372
10346
  init_cabane_command();
10373
10347
  import { randomUUID as randomUUID7 } from "crypto";
10374
- import { fileURLToPath as fileURLToPath5 } from "url";
10375
10348
 
10376
10349
  // src/prereqs.ts
10377
10350
  init_config();
@@ -10388,71 +10361,37 @@ function warnAboutHarnessReadiness(cfg, deps = {}) {
10388
10361
  }
10389
10362
 
10390
10363
  // src/state.ts
10391
- import { EventEmitter } from "events";
10392
- function dispatchToWire(r) {
10393
- return {
10394
- id: r.id,
10395
- timestamp: r.timestamp,
10396
- workspace_slug: r.workspaceSlug,
10397
- ...r.agentUsername ? { agent_username: r.agentUsername } : {},
10398
- message: r.message,
10399
- status: r.status,
10400
- ...r.durationMs !== void 0 ? { duration_ms: r.durationMs } : {},
10401
- ...r.error ? { error: r.error } : {},
10402
- ...r.reply ? { reply: r.reply } : {}
10403
- };
10404
- }
10405
- var MAX_DISPATCHES = 50;
10406
10364
  function today() {
10407
10365
  return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
10408
10366
  }
10409
10367
  var CompanionStateHub = class {
10410
10368
  constructor(opts) {
10411
10369
  this.opts = opts;
10412
- this.emitter.setMaxListeners(0);
10413
10370
  }
10414
10371
  opts;
10415
- emitter = new EventEmitter();
10416
10372
  workspaces = /* @__PURE__ */ new Map();
10417
- dispatches = [];
10418
- dashboardUrl = null;
10419
10373
  deviceId = null;
10420
10374
  deviceLabel = null;
10421
10375
  deviceError = null;
10422
10376
  // The latest harness snapshot the supervisor probed, or null before the
10423
10377
  // first probe (see CompanionStatusJson.harnesses).
10424
10378
  harnesses = null;
10425
- // ---- subscription (SSE) ----
10426
- on(listener) {
10427
- this.emitter.on("event", listener);
10428
- return () => this.emitter.off("event", listener);
10429
- }
10430
- emit(type, data) {
10431
- this.emitter.emit("event", { type, data });
10432
- }
10433
10379
  // ---- device ----
10434
10380
  setDevice(info) {
10435
10381
  if (info.deviceId !== void 0) this.deviceId = info.deviceId;
10436
10382
  if (info.deviceLabel !== void 0) this.deviceLabel = info.deviceLabel;
10437
- this.emitStatus();
10438
10383
  }
10439
10384
  setDeviceError(message2) {
10440
- if (this.deviceError === message2) return;
10441
10385
  this.deviceError = message2;
10442
- this.emitStatus();
10443
10386
  }
10444
10387
  clearDeviceError() {
10445
- if (this.deviceError === null) return;
10446
10388
  this.deviceError = null;
10447
- this.emitStatus();
10448
10389
  }
10449
10390
  // ---- harnesses ----
10450
- // Replace the harness snapshot and push a status change (so the SSE feed flips
10451
- // the Companion's Harnesses surface live). The supervisor calls this on each
10391
+ // Replace the harness snapshot. The supervisor calls this on each
10452
10392
  // heartbeat-cadence probe and on an on-demand recheck.
10453
10393
  setHarnesses(harnesses) {
10454
10394
  this.harnesses = harnesses;
10455
- this.emitStatus();
10456
10395
  }
10457
10396
  // ---- workspace lifecycle ----
10458
10397
  registerWorkspace(ws) {
@@ -10473,29 +10412,21 @@ var CompanionStateHub = class {
10473
10412
  countDate: today(),
10474
10413
  agents: /* @__PURE__ */ new Map()
10475
10414
  });
10476
- this.emitStatus();
10477
10415
  }
10478
10416
  removeWorkspace(workspaceId) {
10479
- const ws = this.workspaces.get(workspaceId);
10480
- if (!ws) return;
10481
10417
  this.workspaces.delete(workspaceId);
10482
- this.emit("workspace:disconnected", { slug: ws.slug });
10483
- this.emitStatus();
10484
10418
  }
10485
10419
  setConnected(workspaceId, connected) {
10486
10420
  const ws = this.workspaces.get(workspaceId);
10487
10421
  if (!ws || ws.connected === connected) return;
10488
10422
  ws.connected = connected;
10489
10423
  if (connected) ws.authFailed = false;
10490
- this.emitStatus();
10491
10424
  }
10492
10425
  setAuthFailed(workspaceId) {
10493
10426
  const ws = this.workspaces.get(workspaceId);
10494
10427
  if (!ws) return;
10495
- if (ws.authFailed && !ws.connected) return;
10496
10428
  ws.authFailed = true;
10497
10429
  ws.connected = false;
10498
- this.emitStatus();
10499
10430
  }
10500
10431
  recordEvent(workspaceId) {
10501
10432
  const ws = this.workspaces.get(workspaceId);
@@ -10508,22 +10439,15 @@ var CompanionStateHub = class {
10508
10439
  const ws = this.workspaces.get(workspaceId);
10509
10440
  if (!ws) return;
10510
10441
  ws.agents.set(agent.agentId, agent);
10511
- this.emitStatus();
10512
10442
  }
10513
10443
  removeAgent(workspaceId, agentId) {
10514
- const ws = this.workspaces.get(workspaceId);
10515
- if (!ws) return;
10516
- if (ws.agents.delete(agentId)) this.emitStatus();
10444
+ this.workspaces.get(workspaceId)?.agents.delete(agentId);
10517
10445
  }
10518
- // ---- dispatch feed ----
10519
- // A DispatchObserver bound to one (workspace, agent), handed to that agent's
10520
- // Dispatcher by the supervisor.
10521
- observerFor(workspaceId, agentId, slug) {
10522
- const username = () => this.workspaces.get(workspaceId)?.agents.get(agentId)?.username ?? "";
10523
- return {
10524
- onStart: (info) => this.dispatchStarted(workspaceId, slug, username(), info),
10525
- onEnd: (info) => this.dispatchEnded(slug, username(), info)
10526
- };
10446
+ // ---- dispatch count ----
10447
+ // A DispatchObserver bound to one workspace, handed to each of its agents'
10448
+ // Dispatchers by the supervisor: a turn counts toward the day when it starts.
10449
+ observerFor(workspaceId) {
10450
+ return { onStart: () => this.bumpCount(workspaceId) };
10527
10451
  }
10528
10452
  bumpCount(workspaceId) {
10529
10453
  const ws = this.workspaces.get(workspaceId);
@@ -10535,52 +10459,6 @@ var CompanionStateHub = class {
10535
10459
  }
10536
10460
  ws.dispatchCountToday += 1;
10537
10461
  }
10538
- dispatchStarted(workspaceId, slug, agentUsername, info) {
10539
- this.bumpCount(workspaceId);
10540
- const record = {
10541
- id: info.id,
10542
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
10543
- workspaceSlug: slug,
10544
- ...agentUsername ? { agentUsername } : {},
10545
- message: info.message,
10546
- status: "running"
10547
- };
10548
- this.upsertDispatch(record);
10549
- this.emit("dispatch:started", dispatchToWire(record));
10550
- this.emitStatus();
10551
- }
10552
- dispatchEnded(slug, agentUsername, info) {
10553
- const existing = this.dispatches.find((d) => d.id === info.id);
10554
- const record = {
10555
- id: info.id,
10556
- timestamp: existing?.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
10557
- workspaceSlug: existing?.workspaceSlug ?? slug,
10558
- ...existing?.agentUsername ?? agentUsername ? { agentUsername: existing?.agentUsername ?? agentUsername } : {},
10559
- message: existing?.message ?? "",
10560
- status: info.ok ? "replied" : "error",
10561
- durationMs: info.durationMs,
10562
- ...info.reason ? { error: info.reason } : {},
10563
- ...info.reply ? { reply: info.reply } : {}
10564
- };
10565
- this.upsertDispatch(record);
10566
- this.emit(info.ok ? "dispatch:completed" : "dispatch:error", dispatchToWire(record));
10567
- }
10568
- upsertDispatch(record) {
10569
- const idx = this.dispatches.findIndex((d) => d.id === record.id);
10570
- if (idx >= 0) {
10571
- this.dispatches[idx] = record;
10572
- return;
10573
- }
10574
- this.dispatches.unshift(record);
10575
- if (this.dispatches.length > MAX_DISPATCHES) this.dispatches.length = MAX_DISPATCHES;
10576
- }
10577
- // ---- snapshots for the HTTP routes ----
10578
- setDashboardUrl(url) {
10579
- this.dashboardUrl = url;
10580
- }
10581
- recentDispatches(limit = 20) {
10582
- return this.dispatches.slice(0, Math.max(0, limit));
10583
- }
10584
10462
  statusJson() {
10585
10463
  const list = [...this.workspaces.values()].sort((a, b) => a.name.localeCompare(b.name));
10586
10464
  const lastOverall = list.reduce((acc, ws) => {
@@ -10610,15 +10488,11 @@ var CompanionStateHub = class {
10610
10488
  }))
10611
10489
  })),
10612
10490
  last_event_at_overall: lastOverall,
10613
- dashboard_url: this.dashboardUrl,
10614
10491
  companion_version: this.opts.companionVersion,
10615
10492
  instance_id: this.opts.instanceId ?? null,
10616
10493
  harnesses: this.harnesses
10617
10494
  };
10618
10495
  }
10619
- emitStatus() {
10620
- this.emit("status:changed", this.statusJson());
10621
- }
10622
10496
  };
10623
10497
 
10624
10498
  // src/supervisor.ts
@@ -11387,7 +11261,6 @@ async function runTurnInRunner(opts, launch, duties, payload, handleOpts) {
11387
11261
  duties.releaseAbort(turnId, controller);
11388
11262
  const durationMs2 = Date.now() - startedAt;
11389
11263
  await settleUnstarted(opts, payload, turnId, minted.errorReason, log2);
11390
- duties.notifyEnd({ id: payload.messageId, ok: false, durationMs: durationMs2, reason: minted.reason });
11391
11264
  return { ok: false, durationMs: durationMs2, reason: minted.reason };
11392
11265
  }
11393
11266
  let result;
@@ -11418,7 +11291,6 @@ async function runTurnInRunner(opts, launch, duties, payload, handleOpts) {
11418
11291
  reason: "provider_failed"
11419
11292
  });
11420
11293
  const durationMs2 = Date.now() - startedAt;
11421
- duties.notifyEnd({ id: payload.messageId, ok: false, durationMs: durationMs2, reason: reason2 });
11422
11294
  return { ok: false, durationMs: durationMs2, reason: reason2 };
11423
11295
  }
11424
11296
  try {
@@ -11482,17 +11354,8 @@ async function runTurnInRunner(opts, launch, duties, payload, handleOpts) {
11482
11354
  }
11483
11355
  return;
11484
11356
  case "start":
11485
- duties.notifyStart({
11486
- id: event.id,
11487
- conversationId: event.conversationId,
11488
- message: event.message
11489
- });
11490
- return;
11491
- case "end": {
11492
- const { cabaneRunner: _kind, ...info } = event;
11493
- duties.notifyEnd(info);
11357
+ duties.notifyStart({ id: event.id, conversationId: event.conversationId });
11494
11358
  return;
11495
- }
11496
11359
  case "session_write_notice":
11497
11360
  duties.markSessionWriteNotice();
11498
11361
  return;
@@ -11596,7 +11459,6 @@ async function runTurnInRunner(opts, launch, duties, payload, handleOpts) {
11596
11459
  if (thrown !== void 0) throw new Error(thrown);
11597
11460
  if (stopped) log2.info({ turnId, code }, "runner: stopped before it could report");
11598
11461
  else log2.warn({ turnId, code }, "runner: exited without reporting a result");
11599
- duties.notifyEnd({ id: payload.messageId, ok: false, durationMs, reason });
11600
11462
  return { ok: false, durationMs, reason };
11601
11463
  }
11602
11464
 
@@ -11623,12 +11485,6 @@ var Dispatcher = class {
11623
11485
  } catch {
11624
11486
  }
11625
11487
  }
11626
- notifyEnd(info) {
11627
- try {
11628
- this.opts.observer?.onEnd(info);
11629
- } catch {
11630
- }
11631
- }
11632
11488
  // The supervisor supplies a stable turnId on both fresh and resumed dispatch.
11633
11489
  // resumed is separate: only replay seeds sequence/speech recovery from the
11634
11490
  // prior span. A direct caller omitting turnId gets a fresh id.
@@ -11656,8 +11512,7 @@ var Dispatcher = class {
11656
11512
  markSessionWriteNotice: () => {
11657
11513
  this.sessionWriteNotified.add(key);
11658
11514
  },
11659
- notifyStart: (info) => this.notifyStart(info),
11660
- notifyEnd: (info) => this.notifyEnd(info)
11515
+ notifyStart: (info) => this.notifyStart(info)
11661
11516
  },
11662
11517
  payload,
11663
11518
  {
@@ -12756,7 +12611,6 @@ var CompanionSupervisor = class {
12756
12611
  runHarnessCheck;
12757
12612
  probeOpencode;
12758
12613
  exitFn;
12759
- reexecFn;
12760
12614
  dispatcherFactory;
12761
12615
  runnerCommand;
12762
12616
  runnerEnv;
@@ -12767,8 +12621,8 @@ var CompanionSupervisor = class {
12767
12621
  host = hostReport();
12768
12622
  deviceApi = null;
12769
12623
  deviceSub = null;
12770
- // Whether the device stream is open, which is what every workspace's link on
12771
- // the dashboard reports.
12624
+ // Whether the device stream is open, which is what every workspace's link in
12625
+ // the status snapshot reports.
12772
12626
  deviceConnected = false;
12773
12627
  // Set when the device stream ended on a 403: the device was deactivated, not
12774
12628
  // unpaired. The next accepted heartbeat proves it was reactivated, and
@@ -12829,7 +12683,6 @@ var CompanionSupervisor = class {
12829
12683
  this.probeOpencode = opts.probeOpencode;
12830
12684
  this.harnessVersions = opts.harnessVersions ?? emptyHarnessVersions();
12831
12685
  this.exitFn = opts.exit ?? ((code) => process.exit(code));
12832
- this.reexecFn = opts.reexec ?? defaultReexec;
12833
12686
  this.restartForUpdate = opts.restartForUpdate ?? (async () => {
12834
12687
  await this.shutdown();
12835
12688
  this.exitFn(0);
@@ -13463,7 +13316,7 @@ var CompanionSupervisor = class {
13463
13316
  locks: this.runnerLocks,
13464
13317
  gzipBodies: this.gzipBodies
13465
13318
  },
13466
- observer: this.hub.observerFor(ctx2.workspaceId, ctx2.agentId, ctx2.workspaceSlug),
13319
+ observer: this.hub.observerFor(ctx2.workspaceId),
13467
13320
  aborts: ctx2.aborts
13468
13321
  });
13469
13322
  }
@@ -13917,36 +13770,9 @@ var CompanionSupervisor = class {
13917
13770
  };
13918
13771
  return { kick, cancel: cancel2 };
13919
13772
  }
13920
- // ---- dashboard-facing operations ----
13921
- // Re-read `~/.cabane/config.json` (the operator may have edited the `agents`
13922
- // overrides or dashboard prefs), apply the log level live, and re-pull
13923
- // assignments so any structural change is reflected. A device-token change
13924
- // means re-pairing, which `pair` + a restart handle.
13925
- reloadConfig() {
13926
- const next = loadConfig();
13927
- if (!next) return;
13928
- this.config = next;
13929
- configureLogger(this.log, next);
13930
- this.rebuildDispatchers();
13931
- void this.refreshAssignments();
13932
- }
13933
- // The dashboard "refresh assignments" control — an immediate pull.
13934
- refresh() {
13935
- void this.refreshAssignments();
13936
- }
13937
- applySettings(patch) {
13938
- const next = {
13939
- ...this.config,
13940
- ...patch.logLevel ? { logLevel: patch.logLevel } : {},
13941
- ...patch.autoOpen !== void 0 ? { autoOpen: patch.autoOpen } : {}
13942
- };
13943
- this.config = next;
13944
- saveConfig(next);
13945
- configureLogger(this.log, next);
13946
- }
13947
13773
  // ---- harnesses ----
13948
13774
  // Look at every agent, in this process: the one whose environment turns run
13949
- // in. Cached for the heartbeat and the dashboard; coalesced, so a re-detect
13775
+ // in. Cached for the heartbeat and the status snapshot; coalesced, so a re-detect
13950
13776
  // during the timer's own run waits for that one. Never throws.
13951
13777
  async detect() {
13952
13778
  if (this.detecting) return this.detecting;
@@ -13974,8 +13800,8 @@ var CompanionSupervisor = class {
13974
13800
  });
13975
13801
  return this.detecting;
13976
13802
  }
13977
- // A re-detect asked for over the control socket (`setup`, `connect`) or the
13978
- // dashboard: read the config file again first — this process owns it, so an
13803
+ // A re-detect asked for over the control socket (`setup`, `connect`): read
13804
+ // the config file again first — this process owns it, so an
13979
13805
  // edit made on disk (the allowlist, the OpenCode address) is adopted here
13980
13806
  // rather than overwritten by its next save — then detect now, and beat at
13981
13807
  // once so Cabane shows it promptly.
@@ -14111,9 +13937,6 @@ var CompanionSupervisor = class {
14111
13937
  await this.shutdown();
14112
13938
  this.exitFn(0);
14113
13939
  }
14114
- requestRestart() {
14115
- this.reexecFn();
14116
- }
14117
13940
  };
14118
13941
  async function waitForBoundedHeartbeat(heartbeat) {
14119
13942
  let timer = null;
@@ -14127,21 +13950,6 @@ async function waitForBoundedHeartbeat(heartbeat) {
14127
13950
  if (timer) clearTimeout(timer);
14128
13951
  }
14129
13952
  }
14130
- function defaultReexec() {
14131
- clearRuntimeState();
14132
- void import("child_process").then(({ spawn: spawn8 }) => {
14133
- try {
14134
- const child = spawn8(process.execPath, process.argv.slice(1), {
14135
- stdio: "inherit",
14136
- detached: false
14137
- });
14138
- child.on("spawn", () => process.exit(0));
14139
- child.on("error", () => {
14140
- });
14141
- } catch {
14142
- }
14143
- });
14144
- }
14145
13953
 
14146
13954
  // src/safety.ts
14147
13955
  var RECOVERABLE_CODES = /* @__PURE__ */ new Set([
@@ -14313,15 +14121,6 @@ function strayCompanionLines(strays, retry) {
14313
14121
  }
14314
14122
 
14315
14123
  // src/runtime.ts
14316
- init_errors();
14317
- function embeddedRunner(host) {
14318
- if (!host.electron) return null;
14319
- const cli = fileURLToPath5(new URL("./cli.js", host.moduleUrl));
14320
- return {
14321
- runnerCommand: [host.execPath, cli, "run-turn"],
14322
- runnerEnv: { ...host.env, ELECTRON_RUN_AS_NODE: "1" }
14323
- };
14324
- }
14325
14124
  async function createCompanionRuntime(opts = {}) {
14326
14125
  const log2 = getLogger();
14327
14126
  installProcessSafetyNet(log2);
@@ -14361,7 +14160,7 @@ async function createCompanionRuntime(opts = {}) {
14361
14160
  const clearRuntimeOnExit = () => clearRuntimeStateIfOurs(instanceId);
14362
14161
  process.on("exit", clearRuntimeOnExit);
14363
14162
  const hub = new CompanionStateHub({
14364
- // The dashboard's connection line shows it.
14163
+ // `status` names the Cabane it is paired with.
14365
14164
  baseUrl: cfg.baseUrl,
14366
14165
  companionVersion: COMPANION_VERSION,
14367
14166
  // Surfaced on `/api/status` so `stop`/`status` can confirm the
@@ -14372,7 +14171,6 @@ async function createCompanionRuntime(opts = {}) {
14372
14171
  };
14373
14172
  let supervisor;
14374
14173
  let control = null;
14375
- let dashboard = null;
14376
14174
  let stopped = false;
14377
14175
  const stop2 = async () => {
14378
14176
  if (stopped) return;
@@ -14381,8 +14179,7 @@ async function createCompanionRuntime(opts = {}) {
14381
14179
  process.removeListener("exit", clearRuntimeOnExit);
14382
14180
  await Promise.allSettled([
14383
14181
  ...supervisor ? [supervisor.shutdown()] : [],
14384
- ...control ? [control.close()] : [],
14385
- ...dashboard ? [dashboard.close()] : []
14182
+ ...control ? [control.close()] : []
14386
14183
  ]);
14387
14184
  };
14388
14185
  try {
@@ -14391,12 +14188,6 @@ async function createCompanionRuntime(opts = {}) {
14391
14188
  log: log2,
14392
14189
  hub,
14393
14190
  ...opts.checkHarness ? { checkHarness: opts.checkHarness } : {},
14394
- ...embeddedRunner({
14395
- electron: Boolean(process.versions.electron),
14396
- execPath: process.execPath,
14397
- moduleUrl: import.meta.url,
14398
- env: process.env
14399
- }) ?? {},
14400
14191
  restartForUpdate: () => restartForUpdate()
14401
14192
  });
14402
14193
  const active2 = supervisor;
@@ -14411,21 +14202,10 @@ async function createCompanionRuntime(opts = {}) {
14411
14202
  update: (auto) => active2.update(auto),
14412
14203
  stop: () => void stop2().then(() => active2.requestStop())
14413
14204
  });
14414
- if (opts.startDashboard) {
14415
- const preferredPort = cfg.dashboardPort;
14416
- dashboard = await opts.startDashboard({
14417
- supervisor,
14418
- hub,
14419
- logPath: companionLogPath(),
14420
- ...preferredPort !== void 0 ? { port: preferredPort } : {}
14421
- });
14422
- hub.setDashboardUrl(dashboard.url);
14423
- }
14424
14205
  if (stopped) throw new Error("The companion was stopped during startup.");
14425
14206
  writeRuntimeState({
14426
14207
  pid: process.pid,
14427
14208
  socket: control.path,
14428
- ...dashboard ? { url: dashboard.url, port: dashboard.port } : {},
14429
14209
  startedAt,
14430
14210
  // The daemon launcher sets this env on the detached child, so the
14431
14211
  // marker records whether this companion is backgrounded (foreground start
@@ -14440,8 +14220,7 @@ async function createCompanionRuntime(opts = {}) {
14440
14220
  process.removeListener("exit", clearRuntimeOnExit);
14441
14221
  await Promise.allSettled([
14442
14222
  ...supervisor ? [supervisor.shutdown()] : [],
14443
- ...control ? [control.close()] : [],
14444
- ...dashboard ? [dashboard.close()] : []
14223
+ ...control ? [control.close()] : []
14445
14224
  ]);
14446
14225
  recordCrash({
14447
14226
  reason: err instanceof Error ? err.message : String(err),
@@ -14465,7 +14244,6 @@ async function createCompanionRuntime(opts = {}) {
14465
14244
  return {
14466
14245
  ok: true,
14467
14246
  runtime: {
14468
- ...dashboard ? { url: dashboard.url, port: dashboard.port } : {},
14469
14247
  socketPath: control.path,
14470
14248
  config: cfg,
14471
14249
  stop: stop2,
package/dist/launch.js CHANGED
@@ -133,7 +133,7 @@ var companionConfigSchema = z2.object({
133
133
  // the rest of the config; `pair` always writes one.
134
134
  deviceToken: z2.string().optional(),
135
135
  // Identity hints, learned from the device flow and refreshed on the first
136
- // assignments pull. Cosmetic — used for `status`/dashboard display only.
136
+ // assignments pull. Cosmetic — used for `status` display only.
137
137
  deviceId: z2.string().optional(),
138
138
  deviceLabel: z2.string().optional(),
139
139
  // Optional per-agent machine-local overrides (cwd / prepareHook), keyed by
@@ -145,9 +145,8 @@ var companionConfigSchema = z2.object({
145
145
  // silent roster: an agent nobody listed gets no hook and no error, and starts
146
146
  // in the operator's `$HOME`.
147
147
  prepareHook: prepareHookSchema.optional(),
148
- // The CLI ignores both dashboard settings. Desktop uses `dashboardPort`;
149
- // `autoOpen` remains parseable for older config files but no longer controls
150
- // startup. `logLevel` is pino's level, live-editable.
148
+ // Nothing reads either dashboard setting any more; both stay parseable so an
149
+ // older config file still loads. `logLevel` is pino's level, live-editable.
151
150
  dashboardPort: z2.number().int().min(1).max(65535).optional(),
152
151
  autoOpen: z2.boolean().optional(),
153
152
  logLevel: z2.enum(["warn", "info", "debug"]).optional(),
@@ -183,7 +183,7 @@ var companionConfigSchema = z2.object({
183
183
  // the rest of the config; `pair` always writes one.
184
184
  deviceToken: z2.string().optional(),
185
185
  // Identity hints, learned from the device flow and refreshed on the first
186
- // assignments pull. Cosmetic — used for `status`/dashboard display only.
186
+ // assignments pull. Cosmetic — used for `status` display only.
187
187
  deviceId: z2.string().optional(),
188
188
  deviceLabel: z2.string().optional(),
189
189
  // Optional per-agent machine-local overrides (cwd / prepareHook), keyed by
@@ -195,9 +195,8 @@ var companionConfigSchema = z2.object({
195
195
  // silent roster: an agent nobody listed gets no hook and no error, and starts
196
196
  // in the operator's `$HOME`.
197
197
  prepareHook: prepareHookSchema.optional(),
198
- // The CLI ignores both dashboard settings. Desktop uses `dashboardPort`;
199
- // `autoOpen` remains parseable for older config files but no longer controls
200
- // startup. `logLevel` is pino's level, live-editable.
198
+ // Nothing reads either dashboard setting any more; both stay parseable so an
199
+ // older config file still loads. `logLevel` is pino's level, live-editable.
201
200
  dashboardPort: z2.number().int().min(1).max(65535).optional(),
202
201
  autoOpen: z2.boolean().optional(),
203
202
  logLevel: z2.enum(["warn", "info", "debug"]).optional(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cabane/companion",
3
- "version": "0.6.237",
3
+ "version": "0.6.238",
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",
@@ -16,8 +16,6 @@
16
16
  "main": "./dist/cli.js",
17
17
  "exports": {
18
18
  ".": "./dist/cli.js",
19
- "./runtime": "./dist/runtime.js",
20
- "./pairing": "./dist/pairing-config.js",
21
19
  "./credential-broker": "./dist/credential-broker.js",
22
20
  "./package.json": "./package.json",
23
21
  "./*": "./*"