@cabane/companion 0.6.180 → 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 +54 -22
- package/dist/runtime.js +53 -21
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -9367,7 +9367,7 @@ function fingerprintSessionState(state) {
|
|
|
9367
9367
|
}
|
|
9368
9368
|
return createHash2("sha256").update(opaqueId).digest("hex").slice(0, 16);
|
|
9369
9369
|
}
|
|
9370
|
-
var PREPARING_TOOL_NAME,
|
|
9370
|
+
var PREPARING_TOOL_NAME, HARNESS_UNAVAILABLE_NOTICE, NO_TURN_TOKEN_REASON, UNEXPECTED_ROLE_REASON, DEFAULT_PREPARING_ROW_DELAY_MS, DEFAULT_AGENT_IDLE_TIMEOUT_MS, DEFAULT_AGENT_TOTAL_TIMEOUT_MS, DEFAULT_LEASE_RENEWAL_MS, TurnConcluded, TurnExecution;
|
|
9371
9371
|
var init_turn_execution = __esm({
|
|
9372
9372
|
"src/turn-execution.ts"() {
|
|
9373
9373
|
"use strict";
|
|
@@ -9396,7 +9396,7 @@ var init_turn_execution = __esm({
|
|
|
9396
9396
|
init_dispatcher();
|
|
9397
9397
|
init_sandbox_policy();
|
|
9398
9398
|
PREPARING_TOOL_NAME = "preparing";
|
|
9399
|
-
|
|
9399
|
+
HARNESS_UNAVAILABLE_NOTICE = "**This harness isn't available on the companion.** Check the harness on the device, or choose another harness in the agent's settings. Then reply to try again.";
|
|
9400
9400
|
NO_TURN_TOKEN_REASON = "no_turn_token: the server issued no turn credential for this turn";
|
|
9401
9401
|
UNEXPECTED_ROLE_REASON = `refused the wake trigger (role "system" isn't dispatchable on this companion) \u2014 the companion is likely running outdated code; refresh it, then re-address the agent`;
|
|
9402
9402
|
DEFAULT_PREPARING_ROW_DELAY_MS = 1500;
|
|
@@ -10082,7 +10082,7 @@ var init_turn_execution = __esm({
|
|
|
10082
10082
|
);
|
|
10083
10083
|
try {
|
|
10084
10084
|
await this.opts.api.postTurnMessage(workspaceId, payload.conversationId, {
|
|
10085
|
-
body:
|
|
10085
|
+
body: HARNESS_UNAVAILABLE_NOTICE,
|
|
10086
10086
|
kind: "runtime_notice",
|
|
10087
10087
|
turnId,
|
|
10088
10088
|
parentMessageId: payload.messageId,
|
|
@@ -12554,11 +12554,24 @@ function parseHarnessRuntime(raw) {
|
|
|
12554
12554
|
if (key === "opencode") return "opencode";
|
|
12555
12555
|
return null;
|
|
12556
12556
|
}
|
|
12557
|
-
function
|
|
12558
|
-
return
|
|
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(
|
|
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
|
);
|
|
@@ -13533,7 +13546,7 @@ function turnFailureCopy(reason, runtime) {
|
|
|
13533
13546
|
if (reason?.startsWith("runtime_incomplete:"))
|
|
13534
13547
|
return `The agent installation is incomplete. ${repairAction()} Then restart the companion.`;
|
|
13535
13548
|
if (/^(runtime|codex|opencode)_unavailable:/.test(reason ?? ""))
|
|
13536
|
-
return "
|
|
13549
|
+
return "This harness isn't available on the companion. Check the harness on this device, or choose another harness in the agent's settings in Cabane. Then reply in Cabane to try again.";
|
|
13537
13550
|
if (reason?.startsWith("model_unavailable:"))
|
|
13538
13551
|
return "The selected model is unavailable. Choose a different model in the agent settings in Cabane.";
|
|
13539
13552
|
if (reason?.startsWith("prepare_failed:"))
|
|
@@ -16163,7 +16176,13 @@ 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;
|
|
16183
|
+
// Liveness may be acknowledged before discovery. Execution waits on this
|
|
16184
|
+
// first look only, never on a periodic refresh of an established inventory.
|
|
16185
|
+
initialHarnessReady = null;
|
|
16167
16186
|
detectTimer = null;
|
|
16168
16187
|
runHarnessCheck;
|
|
16169
16188
|
probeOpencode;
|
|
@@ -16315,8 +16334,17 @@ var CompanionSupervisor = class {
|
|
|
16315
16334
|
this.trackHeartbeat(this.sendHeartbeat(true));
|
|
16316
16335
|
}
|
|
16317
16336
|
const firstHeartbeat = this.inFlightHeartbeat;
|
|
16318
|
-
|
|
16319
|
-
|
|
16337
|
+
this.initialHarnessReady = this.detect().then(
|
|
16338
|
+
() => {
|
|
16339
|
+
},
|
|
16340
|
+
(err) => {
|
|
16341
|
+
this.log.warn(
|
|
16342
|
+
{ err: err instanceof Error ? err.message : String(err) },
|
|
16343
|
+
"Couldn't check harnesses at startup. Turns may fail until the next check."
|
|
16344
|
+
);
|
|
16345
|
+
}
|
|
16346
|
+
);
|
|
16347
|
+
void this.initialHarnessReady.then(async () => {
|
|
16320
16348
|
await firstHeartbeat;
|
|
16321
16349
|
if (this.stopped) return;
|
|
16322
16350
|
await this.heartbeatNow();
|
|
@@ -16395,8 +16423,7 @@ var CompanionSupervisor = class {
|
|
|
16395
16423
|
async sendHeartbeat(first = false) {
|
|
16396
16424
|
if (!this.deviceApi) return;
|
|
16397
16425
|
try {
|
|
16398
|
-
if (!first && this.detection &&
|
|
16399
|
-
await this.detect();
|
|
16426
|
+
if (!first && this.detection && this.advertised().length === 0) await this.detect();
|
|
16400
16427
|
const store = loadSecretStoreTolerant(
|
|
16401
16428
|
(m) => this.log.warn({ err: m }, "Could not read the secrets file. Check ~/.cabane/secrets.json.")
|
|
16402
16429
|
);
|
|
@@ -16730,11 +16757,15 @@ var CompanionSupervisor = class {
|
|
|
16730
16757
|
bundledResolution(runtime) {
|
|
16731
16758
|
return this.resolveBundled(runtime);
|
|
16732
16759
|
}
|
|
16733
|
-
// Does this device OFFER a runtime —
|
|
16734
|
-
// ONE signal the heartbeat manifest, the adapter registry and the
|
|
16735
|
-
// read, so what the device advertises and what it can select can't
|
|
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.
|
|
16736
16764
|
offered(runtime) {
|
|
16737
|
-
return this.
|
|
16765
|
+
return this.advertised().includes(runtime);
|
|
16766
|
+
}
|
|
16767
|
+
advertised() {
|
|
16768
|
+
return this.detection ? advertisedRuntimes(this.detection, this.used) : [];
|
|
16738
16769
|
}
|
|
16739
16770
|
// The address an OpenCode turn runs against: the serve detection found, else
|
|
16740
16771
|
// the configured one, for the model list a beat still asks for.
|
|
@@ -17173,6 +17204,8 @@ var CompanionSupervisor = class {
|
|
|
17173
17204
|
return;
|
|
17174
17205
|
this.recovering = true;
|
|
17175
17206
|
try {
|
|
17207
|
+
await this.initialHarnessReady;
|
|
17208
|
+
if (this.stopped) return;
|
|
17176
17209
|
const page = await this.deviceApi.getRuns(this.recoveryCursor);
|
|
17177
17210
|
if (this.stopped) return;
|
|
17178
17211
|
let assignmentsMissing = false;
|
|
@@ -17224,6 +17257,8 @@ var CompanionSupervisor = class {
|
|
|
17224
17257
|
}
|
|
17225
17258
|
// One turn: the skip-vs-resume dedupe, the dispatch, then the console summary.
|
|
17226
17259
|
async runDispatch(wr, dispatchId, payload, agent, recoveredTurnId) {
|
|
17260
|
+
await this.initialHarnessReady;
|
|
17261
|
+
if (this.stopped) return;
|
|
17227
17262
|
const workspaceId = wr.workspaceId;
|
|
17228
17263
|
if (dispatchId && hasDispatched(workspaceId, dispatchId)) {
|
|
17229
17264
|
if (hasCompleted(workspaceId, dispatchId)) {
|
|
@@ -17383,19 +17418,20 @@ var CompanionSupervisor = class {
|
|
|
17383
17418
|
async detect() {
|
|
17384
17419
|
if (this.detecting) return this.detecting;
|
|
17385
17420
|
this.detecting = (async () => {
|
|
17386
|
-
const
|
|
17421
|
+
const previousOpencodeUrl = this.opencodeUrl();
|
|
17387
17422
|
const detection = await detectHarnesses(this.config, {
|
|
17388
17423
|
check: this.runHarnessCheck,
|
|
17389
17424
|
...this.probeOpencode ? { probeOpencode: this.probeOpencode } : {}
|
|
17390
17425
|
});
|
|
17391
17426
|
this.detection = detection;
|
|
17427
|
+
this.used = rememberUsed(this.used, detection);
|
|
17392
17428
|
this.logBundledTransitions();
|
|
17393
17429
|
this.harnessVersions = {
|
|
17394
17430
|
claudeCode: detectedVersion(detection["claude-code"]),
|
|
17395
17431
|
opencode: detectedVersion(detection.opencode),
|
|
17396
17432
|
codex: detectedVersion(detection.codex)
|
|
17397
17433
|
};
|
|
17398
|
-
if (
|
|
17434
|
+
if (previousOpencodeUrl !== this.opencodeUrl()) {
|
|
17399
17435
|
this.rebuildDispatchers();
|
|
17400
17436
|
}
|
|
17401
17437
|
this.hub.setHarnesses(deriveHarnessSnapshot(detection).harnesses);
|
|
@@ -17443,7 +17479,7 @@ var CompanionSupervisor = class {
|
|
|
17443
17479
|
const health = this.connectorHealth.reports();
|
|
17444
17480
|
if (health.length === 0 || !this.detection) return health;
|
|
17445
17481
|
const named = new Set(health.map((r) => r.runtime));
|
|
17446
|
-
const bare =
|
|
17482
|
+
const bare = this.advertised().filter((runtime) => !named.has(runtime)).map((runtime) => ({ runtime }));
|
|
17447
17483
|
return [...health, ...bare];
|
|
17448
17484
|
}
|
|
17449
17485
|
// Beat NOW and wait for it to land. `start` calls this before asking the
|
|
@@ -17587,10 +17623,6 @@ function defaultReexec() {
|
|
|
17587
17623
|
}
|
|
17588
17624
|
});
|
|
17589
17625
|
}
|
|
17590
|
-
function opencodeAddress(detection) {
|
|
17591
|
-
const found = detection.opencode;
|
|
17592
|
-
return found.state === "usable" ? found.url ?? DEFAULT_OPENCODE_SERVER_URL : null;
|
|
17593
|
-
}
|
|
17594
17626
|
|
|
17595
17627
|
// src/runtime.ts
|
|
17596
17628
|
init_version2();
|
package/dist/runtime.js
CHANGED
|
@@ -1893,7 +1893,7 @@ function turnFailureCopy(reason, runtime) {
|
|
|
1893
1893
|
if (reason?.startsWith("runtime_incomplete:"))
|
|
1894
1894
|
return `The agent installation is incomplete. ${repairAction()} Then restart the companion.`;
|
|
1895
1895
|
if (/^(runtime|codex|opencode)_unavailable:/.test(reason ?? ""))
|
|
1896
|
-
return "
|
|
1896
|
+
return "This harness isn't available on the companion. Check the harness on this device, or choose another harness in the agent's settings in Cabane. Then reply in Cabane to try again.";
|
|
1897
1897
|
if (reason?.startsWith("model_unavailable:"))
|
|
1898
1898
|
return "The selected model is unavailable. Choose a different model in the agent settings in Cabane.";
|
|
1899
1899
|
if (reason?.startsWith("prepare_failed:"))
|
|
@@ -9850,7 +9850,7 @@ async function absorbBundledLoss(ctx, aborted, outcome) {
|
|
|
9850
9850
|
|
|
9851
9851
|
// src/turn-execution.ts
|
|
9852
9852
|
var PREPARING_TOOL_NAME = "preparing";
|
|
9853
|
-
var
|
|
9853
|
+
var HARNESS_UNAVAILABLE_NOTICE = "**This harness isn't available on the companion.** Check the harness on the device, or choose another harness in the agent's settings. Then reply to try again.";
|
|
9854
9854
|
var NO_TURN_TOKEN_REASON = "no_turn_token: the server issued no turn credential for this turn";
|
|
9855
9855
|
var UNEXPECTED_ROLE_REASON = `refused the wake trigger (role "system" isn't dispatchable on this companion) \u2014 the companion is likely running outdated code; refresh it, then re-address the agent`;
|
|
9856
9856
|
var DEFAULT_PREPARING_ROW_DELAY_MS = 1500;
|
|
@@ -10561,7 +10561,7 @@ var TurnExecution = class {
|
|
|
10561
10561
|
);
|
|
10562
10562
|
try {
|
|
10563
10563
|
await this.opts.api.postTurnMessage(workspaceId, payload.conversationId, {
|
|
10564
|
-
body:
|
|
10564
|
+
body: HARNESS_UNAVAILABLE_NOTICE,
|
|
10565
10565
|
kind: "runtime_notice",
|
|
10566
10566
|
turnId,
|
|
10567
10567
|
parentMessageId: payload.messageId,
|
|
@@ -13042,11 +13042,24 @@ function withTimeout(promise, fallback, timeoutMs) {
|
|
|
13042
13042
|
}
|
|
13043
13043
|
|
|
13044
13044
|
// src/harness-status.ts
|
|
13045
|
-
function
|
|
13046
|
-
return
|
|
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(
|
|
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,7 +14108,13 @@ 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;
|
|
14115
|
+
// Liveness may be acknowledged before discovery. Execution waits on this
|
|
14116
|
+
// first look only, never on a periodic refresh of an established inventory.
|
|
14117
|
+
initialHarnessReady = null;
|
|
14099
14118
|
detectTimer = null;
|
|
14100
14119
|
runHarnessCheck;
|
|
14101
14120
|
probeOpencode;
|
|
@@ -14247,8 +14266,17 @@ var CompanionSupervisor = class {
|
|
|
14247
14266
|
this.trackHeartbeat(this.sendHeartbeat(true));
|
|
14248
14267
|
}
|
|
14249
14268
|
const firstHeartbeat = this.inFlightHeartbeat;
|
|
14250
|
-
|
|
14251
|
-
|
|
14269
|
+
this.initialHarnessReady = this.detect().then(
|
|
14270
|
+
() => {
|
|
14271
|
+
},
|
|
14272
|
+
(err) => {
|
|
14273
|
+
this.log.warn(
|
|
14274
|
+
{ err: err instanceof Error ? err.message : String(err) },
|
|
14275
|
+
"Couldn't check harnesses at startup. Turns may fail until the next check."
|
|
14276
|
+
);
|
|
14277
|
+
}
|
|
14278
|
+
);
|
|
14279
|
+
void this.initialHarnessReady.then(async () => {
|
|
14252
14280
|
await firstHeartbeat;
|
|
14253
14281
|
if (this.stopped) return;
|
|
14254
14282
|
await this.heartbeatNow();
|
|
@@ -14327,8 +14355,7 @@ var CompanionSupervisor = class {
|
|
|
14327
14355
|
async sendHeartbeat(first = false) {
|
|
14328
14356
|
if (!this.deviceApi) return;
|
|
14329
14357
|
try {
|
|
14330
|
-
if (!first && this.detection &&
|
|
14331
|
-
await this.detect();
|
|
14358
|
+
if (!first && this.detection && this.advertised().length === 0) await this.detect();
|
|
14332
14359
|
const store = loadSecretStoreTolerant(
|
|
14333
14360
|
(m) => this.log.warn({ err: m }, "Could not read the secrets file. Check ~/.cabane/secrets.json.")
|
|
14334
14361
|
);
|
|
@@ -14662,11 +14689,15 @@ var CompanionSupervisor = class {
|
|
|
14662
14689
|
bundledResolution(runtime) {
|
|
14663
14690
|
return this.resolveBundled(runtime);
|
|
14664
14691
|
}
|
|
14665
|
-
// Does this device OFFER a runtime —
|
|
14666
|
-
// ONE signal the heartbeat manifest, the adapter registry and the
|
|
14667
|
-
// read, so what the device advertises and what it can select can't
|
|
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.
|
|
14668
14696
|
offered(runtime) {
|
|
14669
|
-
return this.
|
|
14697
|
+
return this.advertised().includes(runtime);
|
|
14698
|
+
}
|
|
14699
|
+
advertised() {
|
|
14700
|
+
return this.detection ? advertisedRuntimes(this.detection, this.used) : [];
|
|
14670
14701
|
}
|
|
14671
14702
|
// The address an OpenCode turn runs against: the serve detection found, else
|
|
14672
14703
|
// the configured one, for the model list a beat still asks for.
|
|
@@ -15105,6 +15136,8 @@ var CompanionSupervisor = class {
|
|
|
15105
15136
|
return;
|
|
15106
15137
|
this.recovering = true;
|
|
15107
15138
|
try {
|
|
15139
|
+
await this.initialHarnessReady;
|
|
15140
|
+
if (this.stopped) return;
|
|
15108
15141
|
const page = await this.deviceApi.getRuns(this.recoveryCursor);
|
|
15109
15142
|
if (this.stopped) return;
|
|
15110
15143
|
let assignmentsMissing = false;
|
|
@@ -15156,6 +15189,8 @@ var CompanionSupervisor = class {
|
|
|
15156
15189
|
}
|
|
15157
15190
|
// One turn: the skip-vs-resume dedupe, the dispatch, then the console summary.
|
|
15158
15191
|
async runDispatch(wr, dispatchId, payload, agent, recoveredTurnId) {
|
|
15192
|
+
await this.initialHarnessReady;
|
|
15193
|
+
if (this.stopped) return;
|
|
15159
15194
|
const workspaceId = wr.workspaceId;
|
|
15160
15195
|
if (dispatchId && hasDispatched(workspaceId, dispatchId)) {
|
|
15161
15196
|
if (hasCompleted(workspaceId, dispatchId)) {
|
|
@@ -15315,19 +15350,20 @@ var CompanionSupervisor = class {
|
|
|
15315
15350
|
async detect() {
|
|
15316
15351
|
if (this.detecting) return this.detecting;
|
|
15317
15352
|
this.detecting = (async () => {
|
|
15318
|
-
const
|
|
15353
|
+
const previousOpencodeUrl = this.opencodeUrl();
|
|
15319
15354
|
const detection = await detectHarnesses(this.config, {
|
|
15320
15355
|
check: this.runHarnessCheck,
|
|
15321
15356
|
...this.probeOpencode ? { probeOpencode: this.probeOpencode } : {}
|
|
15322
15357
|
});
|
|
15323
15358
|
this.detection = detection;
|
|
15359
|
+
this.used = rememberUsed(this.used, detection);
|
|
15324
15360
|
this.logBundledTransitions();
|
|
15325
15361
|
this.harnessVersions = {
|
|
15326
15362
|
claudeCode: detectedVersion(detection["claude-code"]),
|
|
15327
15363
|
opencode: detectedVersion(detection.opencode),
|
|
15328
15364
|
codex: detectedVersion(detection.codex)
|
|
15329
15365
|
};
|
|
15330
|
-
if (
|
|
15366
|
+
if (previousOpencodeUrl !== this.opencodeUrl()) {
|
|
15331
15367
|
this.rebuildDispatchers();
|
|
15332
15368
|
}
|
|
15333
15369
|
this.hub.setHarnesses(deriveHarnessSnapshot(detection).harnesses);
|
|
@@ -15375,7 +15411,7 @@ var CompanionSupervisor = class {
|
|
|
15375
15411
|
const health = this.connectorHealth.reports();
|
|
15376
15412
|
if (health.length === 0 || !this.detection) return health;
|
|
15377
15413
|
const named = new Set(health.map((r) => r.runtime));
|
|
15378
|
-
const bare =
|
|
15414
|
+
const bare = this.advertised().filter((runtime) => !named.has(runtime)).map((runtime) => ({ runtime }));
|
|
15379
15415
|
return [...health, ...bare];
|
|
15380
15416
|
}
|
|
15381
15417
|
// Beat NOW and wait for it to land. `start` calls this before asking the
|
|
@@ -15519,10 +15555,6 @@ function defaultReexec() {
|
|
|
15519
15555
|
}
|
|
15520
15556
|
});
|
|
15521
15557
|
}
|
|
15522
|
-
function opencodeAddress(detection) {
|
|
15523
|
-
const found = detection.opencode;
|
|
15524
|
-
return found.state === "usable" ? found.url ?? DEFAULT_OPENCODE_SERVER_URL : null;
|
|
15525
|
-
}
|
|
15526
15558
|
|
|
15527
15559
|
// src/safety.ts
|
|
15528
15560
|
var RECOVERABLE_CODES = /* @__PURE__ */ new Set([
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cabane/companion",
|
|
3
|
-
"version": "0.6.
|
|
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",
|