@cabane/companion 0.6.179 → 0.6.181
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 +26 -14
- package/dist/runtime.js +23 -11
- 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,
|
|
@@ -12148,7 +12148,7 @@ var HARNESS_STATE_LABEL = {
|
|
|
12148
12148
|
needs_sign_in: "needs sign-in",
|
|
12149
12149
|
limited: "limited",
|
|
12150
12150
|
problem: "problem",
|
|
12151
|
-
off: "
|
|
12151
|
+
off: "disabled",
|
|
12152
12152
|
gone: "gone"
|
|
12153
12153
|
};
|
|
12154
12154
|
|
|
@@ -12260,7 +12260,7 @@ function agentRowText(runtime, state, opts = {}) {
|
|
|
12260
12260
|
case "not_running":
|
|
12261
12261
|
return `${word} \u2014 not running`;
|
|
12262
12262
|
case "off":
|
|
12263
|
-
return `${word} \u2014
|
|
12263
|
+
return `${word} \u2014 disabled in config`;
|
|
12264
12264
|
case "problem":
|
|
12265
12265
|
return runtime === "opencode" ? `${word} \u2014 not running` : `${word} \u2014 ${unusableReason(runtime, state.check) ?? "could not be checked"}`;
|
|
12266
12266
|
}
|
|
@@ -13533,7 +13533,7 @@ function turnFailureCopy(reason, runtime) {
|
|
|
13533
13533
|
if (reason?.startsWith("runtime_incomplete:"))
|
|
13534
13534
|
return `The agent installation is incomplete. ${repairAction()} Then restart the companion.`;
|
|
13535
13535
|
if (/^(runtime|codex|opencode)_unavailable:/.test(reason ?? ""))
|
|
13536
|
-
return "
|
|
13536
|
+
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
13537
|
if (reason?.startsWith("model_unavailable:"))
|
|
13538
13538
|
return "The selected model is unavailable. Choose a different model in the agent settings in Cabane.";
|
|
13539
13539
|
if (reason?.startsWith("prepare_failed:"))
|
|
@@ -16164,6 +16164,9 @@ var CompanionSupervisor = class {
|
|
|
16164
16164
|
// the first detection; a heartbeat spawns nothing and reads this.
|
|
16165
16165
|
detection = null;
|
|
16166
16166
|
detecting = null;
|
|
16167
|
+
// Liveness may be acknowledged before discovery. Execution waits on this
|
|
16168
|
+
// first look only, never on a periodic refresh of an established inventory.
|
|
16169
|
+
initialHarnessReady = null;
|
|
16167
16170
|
detectTimer = null;
|
|
16168
16171
|
runHarnessCheck;
|
|
16169
16172
|
probeOpencode;
|
|
@@ -16315,8 +16318,17 @@ var CompanionSupervisor = class {
|
|
|
16315
16318
|
this.trackHeartbeat(this.sendHeartbeat(true));
|
|
16316
16319
|
}
|
|
16317
16320
|
const firstHeartbeat = this.inFlightHeartbeat;
|
|
16318
|
-
|
|
16319
|
-
|
|
16321
|
+
this.initialHarnessReady = this.detect().then(
|
|
16322
|
+
() => {
|
|
16323
|
+
},
|
|
16324
|
+
(err) => {
|
|
16325
|
+
this.log.warn(
|
|
16326
|
+
{ err: err instanceof Error ? err.message : String(err) },
|
|
16327
|
+
"Couldn't check harnesses at startup. Turns may fail until the next check."
|
|
16328
|
+
);
|
|
16329
|
+
}
|
|
16330
|
+
);
|
|
16331
|
+
void this.initialHarnessReady.then(async () => {
|
|
16320
16332
|
await firstHeartbeat;
|
|
16321
16333
|
if (this.stopped) return;
|
|
16322
16334
|
await this.heartbeatNow();
|
|
@@ -17173,6 +17185,8 @@ var CompanionSupervisor = class {
|
|
|
17173
17185
|
return;
|
|
17174
17186
|
this.recovering = true;
|
|
17175
17187
|
try {
|
|
17188
|
+
await this.initialHarnessReady;
|
|
17189
|
+
if (this.stopped) return;
|
|
17176
17190
|
const page = await this.deviceApi.getRuns(this.recoveryCursor);
|
|
17177
17191
|
if (this.stopped) return;
|
|
17178
17192
|
let assignmentsMissing = false;
|
|
@@ -17224,6 +17238,8 @@ var CompanionSupervisor = class {
|
|
|
17224
17238
|
}
|
|
17225
17239
|
// One turn: the skip-vs-resume dedupe, the dispatch, then the console summary.
|
|
17226
17240
|
async runDispatch(wr, dispatchId, payload, agent, recoveredTurnId) {
|
|
17241
|
+
await this.initialHarnessReady;
|
|
17242
|
+
if (this.stopped) return;
|
|
17227
17243
|
const workspaceId = wr.workspaceId;
|
|
17228
17244
|
if (dispatchId && hasDispatched(workspaceId, dispatchId)) {
|
|
17229
17245
|
if (hasCompleted(workspaceId, dispatchId)) {
|
|
@@ -17383,7 +17399,7 @@ var CompanionSupervisor = class {
|
|
|
17383
17399
|
async detect() {
|
|
17384
17400
|
if (this.detecting) return this.detecting;
|
|
17385
17401
|
this.detecting = (async () => {
|
|
17386
|
-
const
|
|
17402
|
+
const previousOpencodeUrl = this.opencodeUrl();
|
|
17387
17403
|
const detection = await detectHarnesses(this.config, {
|
|
17388
17404
|
check: this.runHarnessCheck,
|
|
17389
17405
|
...this.probeOpencode ? { probeOpencode: this.probeOpencode } : {}
|
|
@@ -17395,7 +17411,7 @@ var CompanionSupervisor = class {
|
|
|
17395
17411
|
opencode: detectedVersion(detection.opencode),
|
|
17396
17412
|
codex: detectedVersion(detection.codex)
|
|
17397
17413
|
};
|
|
17398
|
-
if (
|
|
17414
|
+
if (previousOpencodeUrl !== this.opencodeUrl()) {
|
|
17399
17415
|
this.rebuildDispatchers();
|
|
17400
17416
|
}
|
|
17401
17417
|
this.hub.setHarnesses(deriveHarnessSnapshot(detection).harnesses);
|
|
@@ -17587,10 +17603,6 @@ function defaultReexec() {
|
|
|
17587
17603
|
}
|
|
17588
17604
|
});
|
|
17589
17605
|
}
|
|
17590
|
-
function opencodeAddress(detection) {
|
|
17591
|
-
const found = detection.opencode;
|
|
17592
|
-
return found.state === "usable" ? found.url ?? DEFAULT_OPENCODE_SERVER_URL : null;
|
|
17593
|
-
}
|
|
17594
17606
|
|
|
17595
17607
|
// src/runtime.ts
|
|
17596
17608
|
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,
|
|
@@ -14096,6 +14096,9 @@ var CompanionSupervisor = class {
|
|
|
14096
14096
|
// the first detection; a heartbeat spawns nothing and reads this.
|
|
14097
14097
|
detection = null;
|
|
14098
14098
|
detecting = null;
|
|
14099
|
+
// Liveness may be acknowledged before discovery. Execution waits on this
|
|
14100
|
+
// first look only, never on a periodic refresh of an established inventory.
|
|
14101
|
+
initialHarnessReady = null;
|
|
14099
14102
|
detectTimer = null;
|
|
14100
14103
|
runHarnessCheck;
|
|
14101
14104
|
probeOpencode;
|
|
@@ -14247,8 +14250,17 @@ var CompanionSupervisor = class {
|
|
|
14247
14250
|
this.trackHeartbeat(this.sendHeartbeat(true));
|
|
14248
14251
|
}
|
|
14249
14252
|
const firstHeartbeat = this.inFlightHeartbeat;
|
|
14250
|
-
|
|
14251
|
-
|
|
14253
|
+
this.initialHarnessReady = this.detect().then(
|
|
14254
|
+
() => {
|
|
14255
|
+
},
|
|
14256
|
+
(err) => {
|
|
14257
|
+
this.log.warn(
|
|
14258
|
+
{ err: err instanceof Error ? err.message : String(err) },
|
|
14259
|
+
"Couldn't check harnesses at startup. Turns may fail until the next check."
|
|
14260
|
+
);
|
|
14261
|
+
}
|
|
14262
|
+
);
|
|
14263
|
+
void this.initialHarnessReady.then(async () => {
|
|
14252
14264
|
await firstHeartbeat;
|
|
14253
14265
|
if (this.stopped) return;
|
|
14254
14266
|
await this.heartbeatNow();
|
|
@@ -15105,6 +15117,8 @@ var CompanionSupervisor = class {
|
|
|
15105
15117
|
return;
|
|
15106
15118
|
this.recovering = true;
|
|
15107
15119
|
try {
|
|
15120
|
+
await this.initialHarnessReady;
|
|
15121
|
+
if (this.stopped) return;
|
|
15108
15122
|
const page = await this.deviceApi.getRuns(this.recoveryCursor);
|
|
15109
15123
|
if (this.stopped) return;
|
|
15110
15124
|
let assignmentsMissing = false;
|
|
@@ -15156,6 +15170,8 @@ var CompanionSupervisor = class {
|
|
|
15156
15170
|
}
|
|
15157
15171
|
// One turn: the skip-vs-resume dedupe, the dispatch, then the console summary.
|
|
15158
15172
|
async runDispatch(wr, dispatchId, payload, agent, recoveredTurnId) {
|
|
15173
|
+
await this.initialHarnessReady;
|
|
15174
|
+
if (this.stopped) return;
|
|
15159
15175
|
const workspaceId = wr.workspaceId;
|
|
15160
15176
|
if (dispatchId && hasDispatched(workspaceId, dispatchId)) {
|
|
15161
15177
|
if (hasCompleted(workspaceId, dispatchId)) {
|
|
@@ -15315,7 +15331,7 @@ var CompanionSupervisor = class {
|
|
|
15315
15331
|
async detect() {
|
|
15316
15332
|
if (this.detecting) return this.detecting;
|
|
15317
15333
|
this.detecting = (async () => {
|
|
15318
|
-
const
|
|
15334
|
+
const previousOpencodeUrl = this.opencodeUrl();
|
|
15319
15335
|
const detection = await detectHarnesses(this.config, {
|
|
15320
15336
|
check: this.runHarnessCheck,
|
|
15321
15337
|
...this.probeOpencode ? { probeOpencode: this.probeOpencode } : {}
|
|
@@ -15327,7 +15343,7 @@ var CompanionSupervisor = class {
|
|
|
15327
15343
|
opencode: detectedVersion(detection.opencode),
|
|
15328
15344
|
codex: detectedVersion(detection.codex)
|
|
15329
15345
|
};
|
|
15330
|
-
if (
|
|
15346
|
+
if (previousOpencodeUrl !== this.opencodeUrl()) {
|
|
15331
15347
|
this.rebuildDispatchers();
|
|
15332
15348
|
}
|
|
15333
15349
|
this.hub.setHarnesses(deriveHarnessSnapshot(detection).harnesses);
|
|
@@ -15519,10 +15535,6 @@ function defaultReexec() {
|
|
|
15519
15535
|
}
|
|
15520
15536
|
});
|
|
15521
15537
|
}
|
|
15522
|
-
function opencodeAddress(detection) {
|
|
15523
|
-
const found = detection.opencode;
|
|
15524
|
-
return found.state === "usable" ? found.url ?? DEFAULT_OPENCODE_SERVER_URL : null;
|
|
15525
|
-
}
|
|
15526
15538
|
|
|
15527
15539
|
// src/safety.ts
|
|
15528
15540
|
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.181",
|
|
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",
|