@cabane/companion 0.6.181 → 0.6.182

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
@@ -12554,11 +12554,24 @@ function parseHarnessRuntime(raw) {
12554
12554
  if (key === "opencode") return "opencode";
12555
12555
  return null;
12556
12556
  }
12557
- function advertisedRuntimes(detection) {
12558
- return usableRuntimes(detection);
12557
+ function stillRunnable(agent) {
12558
+ return agent.state === "usable" || agent.state === "signed_out" || agent.state === "problem" && agent.check.status === "check_failed";
12559
+ }
12560
+ function rememberUsed(used, detection) {
12561
+ const next = /* @__PURE__ */ new Set();
12562
+ for (const runtime of ["claude-code", "codex"]) {
12563
+ const agent = detection[runtime];
12564
+ if (agent.state === "usable" || used.has(runtime) && stillRunnable(agent)) next.add(runtime);
12565
+ }
12566
+ return next;
12567
+ }
12568
+ function advertisedRuntimes(detection, used) {
12569
+ return HARNESS_RUNTIMES.filter(
12570
+ (runtime) => detection[runtime].state === "usable" || used.has(runtime) && stillRunnable(detection[runtime])
12571
+ );
12559
12572
  }
12560
12573
  function deriveHarnessSnapshot(detection) {
12561
- const advertised = new Set(advertisedRuntimes(detection));
12574
+ const advertised = new Set(usableRuntimes(detection));
12562
12575
  const harnesses = HARNESS_RUNTIMES.map(
12563
12576
  (runtime) => derive(runtime, detection[runtime], advertised.has(runtime))
12564
12577
  );
@@ -16163,6 +16176,9 @@ var CompanionSupervisor = class {
16163
16176
  // control socket, so none can disagree with what is advertised. Null until
16164
16177
  // the first detection; a heartbeat spawns nothing and reads this.
16165
16178
  detection = null;
16179
+ // The bundled harnesses a detection in this run found usable, which stay offered
16180
+ // through a lapsed sign-in (`rememberUsed`). Empty until the first detection.
16181
+ used = /* @__PURE__ */ new Set();
16166
16182
  detecting = null;
16167
16183
  // Liveness may be acknowledged before discovery. Execution waits on this
16168
16184
  // first look only, never on a periodic refresh of an established inventory.
@@ -16407,8 +16423,7 @@ var CompanionSupervisor = class {
16407
16423
  async sendHeartbeat(first = false) {
16408
16424
  if (!this.deviceApi) return;
16409
16425
  try {
16410
- if (!first && this.detection && advertisedRuntimes(this.detection).length === 0)
16411
- await this.detect();
16426
+ if (!first && this.detection && this.advertised().length === 0) await this.detect();
16412
16427
  const store = loadSecretStoreTolerant(
16413
16428
  (m) => this.log.warn({ err: m }, "Could not read the secrets file. Check ~/.cabane/secrets.json.")
16414
16429
  );
@@ -16742,11 +16757,15 @@ var CompanionSupervisor = class {
16742
16757
  bundledResolution(runtime) {
16743
16758
  return this.resolveBundled(runtime);
16744
16759
  }
16745
- // Does this device OFFER a runtime — found usable by the last detection? The
16746
- // ONE signal the heartbeat manifest, the adapter registry and the dispatcher
16747
- // read, so what the device advertises and what it can select can't disagree.
16760
+ // Does this device OFFER a runtime — usable now, or used in this run and still
16761
+ // runnable? The ONE signal the heartbeat manifest, the adapter registry and the
16762
+ // dispatcher read, so what the device advertises and what it can select can't
16763
+ // disagree.
16748
16764
  offered(runtime) {
16749
- return this.detection !== null && advertisedRuntimes(this.detection).includes(runtime);
16765
+ return this.advertised().includes(runtime);
16766
+ }
16767
+ advertised() {
16768
+ return this.detection ? advertisedRuntimes(this.detection, this.used) : [];
16750
16769
  }
16751
16770
  // The address an OpenCode turn runs against: the serve detection found, else
16752
16771
  // the configured one, for the model list a beat still asks for.
@@ -17405,6 +17424,7 @@ var CompanionSupervisor = class {
17405
17424
  ...this.probeOpencode ? { probeOpencode: this.probeOpencode } : {}
17406
17425
  });
17407
17426
  this.detection = detection;
17427
+ this.used = rememberUsed(this.used, detection);
17408
17428
  this.logBundledTransitions();
17409
17429
  this.harnessVersions = {
17410
17430
  claudeCode: detectedVersion(detection["claude-code"]),
@@ -17459,7 +17479,7 @@ var CompanionSupervisor = class {
17459
17479
  const health = this.connectorHealth.reports();
17460
17480
  if (health.length === 0 || !this.detection) return health;
17461
17481
  const named = new Set(health.map((r) => r.runtime));
17462
- const bare = advertisedRuntimes(this.detection).filter((runtime) => !named.has(runtime)).map((runtime) => ({ runtime }));
17482
+ const bare = this.advertised().filter((runtime) => !named.has(runtime)).map((runtime) => ({ runtime }));
17463
17483
  return [...health, ...bare];
17464
17484
  }
17465
17485
  // Beat NOW and wait for it to land. `start` calls this before asking the
package/dist/runtime.js CHANGED
@@ -13042,11 +13042,24 @@ function withTimeout(promise, fallback, timeoutMs) {
13042
13042
  }
13043
13043
 
13044
13044
  // src/harness-status.ts
13045
- function advertisedRuntimes(detection) {
13046
- return usableRuntimes(detection);
13045
+ function stillRunnable(agent) {
13046
+ return agent.state === "usable" || agent.state === "signed_out" || agent.state === "problem" && agent.check.status === "check_failed";
13047
+ }
13048
+ function rememberUsed(used, detection) {
13049
+ const next = /* @__PURE__ */ new Set();
13050
+ for (const runtime of ["claude-code", "codex"]) {
13051
+ const agent = detection[runtime];
13052
+ if (agent.state === "usable" || used.has(runtime) && stillRunnable(agent)) next.add(runtime);
13053
+ }
13054
+ return next;
13055
+ }
13056
+ function advertisedRuntimes(detection, used) {
13057
+ return HARNESS_RUNTIMES.filter(
13058
+ (runtime) => detection[runtime].state === "usable" || used.has(runtime) && stillRunnable(detection[runtime])
13059
+ );
13047
13060
  }
13048
13061
  function deriveHarnessSnapshot(detection) {
13049
- const advertised = new Set(advertisedRuntimes(detection));
13062
+ const advertised = new Set(usableRuntimes(detection));
13050
13063
  const harnesses = HARNESS_RUNTIMES.map(
13051
13064
  (runtime) => derive(runtime, detection[runtime], advertised.has(runtime))
13052
13065
  );
@@ -14095,6 +14108,9 @@ var CompanionSupervisor = class {
14095
14108
  // control socket, so none can disagree with what is advertised. Null until
14096
14109
  // the first detection; a heartbeat spawns nothing and reads this.
14097
14110
  detection = null;
14111
+ // The bundled harnesses a detection in this run found usable, which stay offered
14112
+ // through a lapsed sign-in (`rememberUsed`). Empty until the first detection.
14113
+ used = /* @__PURE__ */ new Set();
14098
14114
  detecting = null;
14099
14115
  // Liveness may be acknowledged before discovery. Execution waits on this
14100
14116
  // first look only, never on a periodic refresh of an established inventory.
@@ -14339,8 +14355,7 @@ var CompanionSupervisor = class {
14339
14355
  async sendHeartbeat(first = false) {
14340
14356
  if (!this.deviceApi) return;
14341
14357
  try {
14342
- if (!first && this.detection && advertisedRuntimes(this.detection).length === 0)
14343
- await this.detect();
14358
+ if (!first && this.detection && this.advertised().length === 0) await this.detect();
14344
14359
  const store = loadSecretStoreTolerant(
14345
14360
  (m) => this.log.warn({ err: m }, "Could not read the secrets file. Check ~/.cabane/secrets.json.")
14346
14361
  );
@@ -14674,11 +14689,15 @@ var CompanionSupervisor = class {
14674
14689
  bundledResolution(runtime) {
14675
14690
  return this.resolveBundled(runtime);
14676
14691
  }
14677
- // Does this device OFFER a runtime — found usable by the last detection? The
14678
- // ONE signal the heartbeat manifest, the adapter registry and the dispatcher
14679
- // read, so what the device advertises and what it can select can't disagree.
14692
+ // Does this device OFFER a runtime — usable now, or used in this run and still
14693
+ // runnable? The ONE signal the heartbeat manifest, the adapter registry and the
14694
+ // dispatcher read, so what the device advertises and what it can select can't
14695
+ // disagree.
14680
14696
  offered(runtime) {
14681
- return this.detection !== null && advertisedRuntimes(this.detection).includes(runtime);
14697
+ return this.advertised().includes(runtime);
14698
+ }
14699
+ advertised() {
14700
+ return this.detection ? advertisedRuntimes(this.detection, this.used) : [];
14682
14701
  }
14683
14702
  // The address an OpenCode turn runs against: the serve detection found, else
14684
14703
  // the configured one, for the model list a beat still asks for.
@@ -15337,6 +15356,7 @@ var CompanionSupervisor = class {
15337
15356
  ...this.probeOpencode ? { probeOpencode: this.probeOpencode } : {}
15338
15357
  });
15339
15358
  this.detection = detection;
15359
+ this.used = rememberUsed(this.used, detection);
15340
15360
  this.logBundledTransitions();
15341
15361
  this.harnessVersions = {
15342
15362
  claudeCode: detectedVersion(detection["claude-code"]),
@@ -15391,7 +15411,7 @@ var CompanionSupervisor = class {
15391
15411
  const health = this.connectorHealth.reports();
15392
15412
  if (health.length === 0 || !this.detection) return health;
15393
15413
  const named = new Set(health.map((r) => r.runtime));
15394
- const bare = advertisedRuntimes(this.detection).filter((runtime) => !named.has(runtime)).map((runtime) => ({ runtime }));
15414
+ const bare = this.advertised().filter((runtime) => !named.has(runtime)).map((runtime) => ({ runtime }));
15395
15415
  return [...health, ...bare];
15396
15416
  }
15397
15417
  // Beat NOW and wait for it to land. `start` calls this before asking the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cabane/companion",
3
- "version": "0.6.181",
3
+ "version": "0.6.182",
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",