@cabane/companion 0.6.209 → 0.6.211
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/README.md +7 -7
- package/dist/cli.js +94 -18
- package/dist/runtime.js +18 -10
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,9 +4,9 @@ The Cabane Companion runs your Cabane agents on a device you choose. It receives
|
|
|
4
4
|
|
|
5
5
|
It uses **Claude Code**, **Codex** or **OpenCode**. The package includes Claude Code and Codex execution binaries, but setup does not run a vendor CLI installer or sign you in. OpenCode needs its own running server.
|
|
6
6
|
|
|
7
|
-
Start with [Introduction to the Companion](https://cabane.ai/docs/
|
|
7
|
+
Start with [Introduction to the Companion](https://cabane.ai/docs/introduction-to-the-companion), then [Mac setup](https://cabane.ai/docs/mac-setup), [Windows setup](https://cabane.ai/docs/windows-setup) or [Server and VPS setup](https://cabane.ai/docs/server-and-vps-setup). [FAQ and Help](https://cabane.ai/docs/faq-and-help) covers sign-in and troubleshooting. This README is the device-side reference: commands, configuration and local state.
|
|
8
8
|
|
|
9
|
-
Pairing supplies a device token, not your Cabane password or a full-account token. The device token is for this device's assignments and liveness; assigned agents receive workspace-bound credentials. The [trust guide](https://cabane.ai/docs/
|
|
9
|
+
Pairing supplies a device token, not your Cabane password or a full-account token. The device token is for this device's assignments and liveness; assigned agents receive workspace-bound credentials. The [trust guide](https://cabane.ai/docs/introduction-to-the-companion) explains the layers, records and access.
|
|
10
10
|
|
|
11
11
|
## Install
|
|
12
12
|
|
|
@@ -24,7 +24,7 @@ npm i -g @cabane/companion && cabane setup CODE
|
|
|
24
24
|
|
|
25
25
|
`cabane setup CODE` pairs the device to your account and joins it to that workspace. From an interactive terminal, setup starts the Companion in the background, waits for its first check-in and reports the device's state. Without an interactive terminal, setup can stay attached to the running Companion. The same line on a device that is already paired joins it to the workspace and mints nothing.
|
|
26
26
|
|
|
27
|
-
If no harness is usable, interactive setup asks which one you want to set up. Follow the complete CLI installation and sign-in steps for [Mac setup](https://cabane.ai/docs/
|
|
27
|
+
If no harness is usable, interactive setup asks which one you want to set up. Follow the complete CLI installation and sign-in steps for [Mac setup](https://cabane.ai/docs/mac-setup#2-sign-in), [Windows setup](https://cabane.ai/docs/windows-setup#2-sign-in) or [Server and VPS setup](https://cabane.ai/docs/server-and-vps-setup#2-sign-in-without-a-browser), then check `cabane status`.
|
|
28
28
|
|
|
29
29
|
```
|
|
30
30
|
✓ Paired as "maya-mbp" with Acme.
|
|
@@ -45,7 +45,7 @@ Setup never installs the service. On macOS or Linux, run `cabane service install
|
|
|
45
45
|
|
|
46
46
|
If `cabane` isn't found afterwards, open a new terminal, or run the `source` line setup printed.
|
|
47
47
|
|
|
48
|
-
The [server guide](https://cabane.ai/docs/
|
|
48
|
+
The [server guide](https://cabane.ai/docs/server-and-vps-setup) provides a Dockerfile and Compose example to build locally. Its Dockerfile installs the Companion and all three command-line tools; you sign in inside the container. Follow that guide for pairing and starting the Docker environment.
|
|
49
49
|
|
|
50
50
|
## Commands
|
|
51
51
|
|
|
@@ -69,7 +69,7 @@ For a direct installation, a reboot or a crash leaves the Companion stopped unti
|
|
|
69
69
|
|
|
70
70
|
On native Windows, check the background process with `cabane status` and run `cabane start` after a Windows restart. If you installed OpenCode outside Docker, keep its server running separately; the Companion's service does not supervise it.
|
|
71
71
|
|
|
72
|
-
For the Docker example, keep automatic Companion updates off and rebuild the local image to update the Companion and harness tools. Follow the [server guide's update steps](https://cabane.ai/docs/
|
|
72
|
+
For the Docker example, keep automatic Companion updates off and rebuild the local image to update the Companion and harness tools. Follow the [server guide's update steps](https://cabane.ai/docs/server-and-vps-setup#keep-the-container-running-and-update).
|
|
73
73
|
|
|
74
74
|
Other supervisors: run `cabane start --foreground` with `CABANE_COMPANION_SUPERVISED=1` set, using the absolute paths `~/.cabane/node/bin/node` and `~/.cabane/current/dist/bin.js`, which don't move on an update.
|
|
75
75
|
|
|
@@ -79,7 +79,7 @@ For a direct installation, after **Rotate token** in Cabane, apply the replaceme
|
|
|
79
79
|
2. In `~/.cabane/config.json`, replace `deviceToken` with the replacement token shown by Cabane.
|
|
80
80
|
3. Run `cabane start`.
|
|
81
81
|
|
|
82
|
-
For Docker, follow [Rotate a Docker device's token](https://cabane.ai/docs/
|
|
82
|
+
For Docker, follow [Rotate a Docker device's token](https://cabane.ai/docs/server-and-vps-setup#rotate-a-docker-devices-token).
|
|
83
83
|
|
|
84
84
|
## What's on this device
|
|
85
85
|
|
|
@@ -138,7 +138,7 @@ These names are a contract: changing one would break your command, so none chang
|
|
|
138
138
|
|
|
139
139
|
### Harness permissions
|
|
140
140
|
|
|
141
|
-
The Companion approves Claude Code's tools through a hook and approves OpenCode permission requests; no turn waits for a tool-approval dialog. For Codex it disables approvals and, when your configuration sets a top-level `sandbox_mode`, passes no sandbox flag; without that setting it uses `danger-full-access`. Choose where agents run using [Agent access](https://cabane.ai/docs/
|
|
141
|
+
The Companion approves Claude Code's tools through a hook and approves OpenCode permission requests; no turn waits for a tool-approval dialog. For Codex it disables approvals and, when your configuration sets a top-level `sandbox_mode`, passes no sandbox flag; without that setting it uses `danger-full-access`. Choose where agents run using [Agent access](https://cabane.ai/docs/agent-access), and configure the tools through [Harness sandboxes](https://cabane.ai/docs/harness-sandboxes).
|
|
142
142
|
|
|
143
143
|
## Debugging a turn
|
|
144
144
|
|
package/dist/cli.js
CHANGED
|
@@ -1801,7 +1801,12 @@ var init_api = __esm({
|
|
|
1801
1801
|
this.opts.outbox?.remove(activeRunOutboxKey(conversationId, agentId), ACTIVE_RUN_OUTBOX_SEQ);
|
|
1802
1802
|
return res;
|
|
1803
1803
|
}
|
|
1804
|
-
return this.request(
|
|
1804
|
+
return this.request(
|
|
1805
|
+
"PATCH",
|
|
1806
|
+
path,
|
|
1807
|
+
body,
|
|
1808
|
+
body.responsiveness ? { signal: AbortSignal.timeout(5e3) } : {}
|
|
1809
|
+
);
|
|
1805
1810
|
}
|
|
1806
1811
|
// Send-or-enqueue for an active-run flag write, last-writer-wins per
|
|
1807
1812
|
// (conversation, agent) pair. Like `durableCommit`, except:
|
|
@@ -8020,6 +8025,59 @@ var init_protocol = __esm({
|
|
|
8020
8025
|
}
|
|
8021
8026
|
});
|
|
8022
8027
|
|
|
8028
|
+
// src/turn-responsiveness.ts
|
|
8029
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
8030
|
+
function createTurnResponsiveness(send, source, now = () => performance.now()) {
|
|
8031
|
+
let invocationId = "";
|
|
8032
|
+
let started = 0;
|
|
8033
|
+
let sessionMode = "fresh";
|
|
8034
|
+
let firstEvent = false;
|
|
8035
|
+
let firstText = false;
|
|
8036
|
+
let invocations = 0;
|
|
8037
|
+
const report = (phase, eventKind) => {
|
|
8038
|
+
if (invocations > 8) return;
|
|
8039
|
+
const value = {
|
|
8040
|
+
executionSourceId: source,
|
|
8041
|
+
invocationId,
|
|
8042
|
+
phase,
|
|
8043
|
+
sessionMode,
|
|
8044
|
+
elapsedMs: Math.min(864e5, Math.max(0, Math.round(now() - started))),
|
|
8045
|
+
...eventKind ? { eventKind } : {}
|
|
8046
|
+
};
|
|
8047
|
+
try {
|
|
8048
|
+
void send(value).catch(() => {
|
|
8049
|
+
});
|
|
8050
|
+
} catch {
|
|
8051
|
+
}
|
|
8052
|
+
};
|
|
8053
|
+
return {
|
|
8054
|
+
start(mode) {
|
|
8055
|
+
invocationId = randomUUID2();
|
|
8056
|
+
started = now();
|
|
8057
|
+
sessionMode = mode;
|
|
8058
|
+
firstEvent = false;
|
|
8059
|
+
firstText = false;
|
|
8060
|
+
invocations += 1;
|
|
8061
|
+
report("invocation");
|
|
8062
|
+
},
|
|
8063
|
+
event(event) {
|
|
8064
|
+
if (!firstEvent) {
|
|
8065
|
+
firstEvent = true;
|
|
8066
|
+
report("first_event", event.type);
|
|
8067
|
+
}
|
|
8068
|
+
if (!firstText && event.type === "text" && event.body.trim()) {
|
|
8069
|
+
firstText = true;
|
|
8070
|
+
report("first_text", "text");
|
|
8071
|
+
}
|
|
8072
|
+
}
|
|
8073
|
+
};
|
|
8074
|
+
}
|
|
8075
|
+
var init_turn_responsiveness = __esm({
|
|
8076
|
+
"src/turn-responsiveness.ts"() {
|
|
8077
|
+
"use strict";
|
|
8078
|
+
}
|
|
8079
|
+
});
|
|
8080
|
+
|
|
8023
8081
|
// src/grants.ts
|
|
8024
8082
|
import { existsSync as existsSync9, readFileSync as readFileSync7 } from "fs";
|
|
8025
8083
|
import { join as join14 } from "path";
|
|
@@ -8138,7 +8196,7 @@ var init_work_dir = __esm({
|
|
|
8138
8196
|
});
|
|
8139
8197
|
|
|
8140
8198
|
// src/turn-control-tools.ts
|
|
8141
|
-
import { randomUUID as
|
|
8199
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
8142
8200
|
import { z as z16 } from "zod";
|
|
8143
8201
|
function createSkipState() {
|
|
8144
8202
|
return { skipped: false, reason: null };
|
|
@@ -8237,7 +8295,7 @@ function createTurnControlMcpServer(acts, skipState) {
|
|
|
8237
8295
|
}
|
|
8238
8296
|
return performAct(acts, {
|
|
8239
8297
|
kind: "ask",
|
|
8240
|
-
callId:
|
|
8298
|
+
callId: randomUUID3(),
|
|
8241
8299
|
// The swap rides the ask, so the server commits both halves
|
|
8242
8300
|
// in one transaction — the person never sees neither or both.
|
|
8243
8301
|
...args.replaces ? { replaces: args.replaces } : {},
|
|
@@ -8279,7 +8337,7 @@ function createTurnControlMcpServer(acts, skipState) {
|
|
|
8279
8337
|
}
|
|
8280
8338
|
return performAct(acts, {
|
|
8281
8339
|
kind: "wake",
|
|
8282
|
-
callId:
|
|
8340
|
+
callId: randomUUID3(),
|
|
8283
8341
|
wake: {
|
|
8284
8342
|
...hasAfter ? { afterSeconds: args.afterSeconds } : {},
|
|
8285
8343
|
...hasAt ? { at: args.at } : {},
|
|
@@ -8303,7 +8361,7 @@ function createTurnControlMcpServer(acts, skipState) {
|
|
|
8303
8361
|
},
|
|
8304
8362
|
async (args) => performAct(acts, {
|
|
8305
8363
|
kind: "withdraw_ask",
|
|
8306
|
-
callId:
|
|
8364
|
+
callId: randomUUID3(),
|
|
8307
8365
|
withdraw: { askId: args.askId, reason: args.reason }
|
|
8308
8366
|
}),
|
|
8309
8367
|
{ annotations: ACT_TOOL, alwaysLoad: true }
|
|
@@ -8312,7 +8370,7 @@ function createTurnControlMcpServer(acts, skipState) {
|
|
|
8312
8370
|
ANSWER_TOOL2,
|
|
8313
8371
|
TURN_CONTROL_TOOL_DESCRIPTIONS.answer,
|
|
8314
8372
|
{},
|
|
8315
|
-
async () => performAct(acts, { kind: "answer", callId:
|
|
8373
|
+
async () => performAct(acts, { kind: "answer", callId: randomUUID3() }),
|
|
8316
8374
|
{ annotations: ACT_TOOL, alwaysLoad: true }
|
|
8317
8375
|
),
|
|
8318
8376
|
// The inverse. No arguments — it can only ever stand down the
|
|
@@ -8321,7 +8379,7 @@ function createTurnControlMcpServer(acts, skipState) {
|
|
|
8321
8379
|
CANCEL_WAKE_TOOL,
|
|
8322
8380
|
TURN_CONTROL_TOOL_DESCRIPTIONS.cancel_wake,
|
|
8323
8381
|
{},
|
|
8324
|
-
async () => performAct(acts, { kind: "cancel_wake", callId:
|
|
8382
|
+
async () => performAct(acts, { kind: "cancel_wake", callId: randomUUID3() }),
|
|
8325
8383
|
{ annotations: CANCEL_TOOL, alwaysLoad: true }
|
|
8326
8384
|
)
|
|
8327
8385
|
]
|
|
@@ -9143,7 +9201,7 @@ var init_turn_runtime_integrity = __esm({
|
|
|
9143
9201
|
});
|
|
9144
9202
|
|
|
9145
9203
|
// src/turn-execution.ts
|
|
9146
|
-
import { createHash as createHash2, randomUUID as
|
|
9204
|
+
import { createHash as createHash2, randomUUID as randomUUID4 } from "crypto";
|
|
9147
9205
|
import { existsSync as existsSync12, mkdirSync as mkdirSync9 } from "fs";
|
|
9148
9206
|
function resolveIdleTimeoutMs(override) {
|
|
9149
9207
|
return override ?? DEFAULT_AGENT_IDLE_TIMEOUT_MS;
|
|
@@ -9185,6 +9243,7 @@ var PREPARING_TOOL_NAME, HARNESS_UNAVAILABLE_NOTICE, NO_TURN_TOKEN_REASON, UNEXP
|
|
|
9185
9243
|
var init_turn_execution = __esm({
|
|
9186
9244
|
"src/turn-execution.ts"() {
|
|
9187
9245
|
"use strict";
|
|
9246
|
+
init_turn_responsiveness();
|
|
9188
9247
|
init_term();
|
|
9189
9248
|
init_cabane_command();
|
|
9190
9249
|
init_boot_id();
|
|
@@ -9241,7 +9300,7 @@ var init_turn_execution = __esm({
|
|
|
9241
9300
|
agentId: payload.agentId,
|
|
9242
9301
|
messageId: payload.messageId
|
|
9243
9302
|
});
|
|
9244
|
-
this.turnId = handleOpts.turnId ??
|
|
9303
|
+
this.turnId = handleOpts.turnId ?? randomUUID4();
|
|
9245
9304
|
}
|
|
9246
9305
|
opts;
|
|
9247
9306
|
supervisor;
|
|
@@ -9651,7 +9710,7 @@ var init_turn_execution = __esm({
|
|
|
9651
9710
|
let preparing = null;
|
|
9652
9711
|
const executionSourceId = this.executionSourceId;
|
|
9653
9712
|
const reportPreparing = (phase) => {
|
|
9654
|
-
preparing ??= { id: `prepare:${
|
|
9713
|
+
preparing ??= { id: `prepare:${randomUUID4()}`, seq: this.nextSeq() };
|
|
9655
9714
|
const { id, seq } = preparing;
|
|
9656
9715
|
const body = {
|
|
9657
9716
|
turnId,
|
|
@@ -9722,6 +9781,10 @@ var init_turn_execution = __esm({
|
|
|
9722
9781
|
try {
|
|
9723
9782
|
await this.opts.api.setActiveRun(workspaceId, payload.conversationId, payload.agentId, {
|
|
9724
9783
|
activeRunStartedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9784
|
+
...this.turnContext.responsivenessVersion === 1 ? {
|
|
9785
|
+
responsivenessVersion: 1,
|
|
9786
|
+
responsivenessSessionMode: this.request.session ? "resumed" : "fresh"
|
|
9787
|
+
} : {},
|
|
9725
9788
|
// A runner leases under its launcher's boot id, the one the device
|
|
9726
9789
|
// heartbeats, or the lost-run sweep reads it as a restart.
|
|
9727
9790
|
bootId: this.opts.inRunner?.bootId ?? bootId,
|
|
@@ -10066,10 +10129,23 @@ var init_turn_execution = __esm({
|
|
|
10066
10129
|
clearTimeout(totalTimer);
|
|
10067
10130
|
clearInterval(leaseTimer);
|
|
10068
10131
|
};
|
|
10132
|
+
const responsiveness = this.turnContext.responsivenessVersion === 1 && this.executionSourceId ? createTurnResponsiveness(
|
|
10133
|
+
(report) => this.opts.api.setActiveRun(workspaceId, payload.conversationId, payload.agentId, {
|
|
10134
|
+
turnId,
|
|
10135
|
+
responsiveness: report
|
|
10136
|
+
}),
|
|
10137
|
+
this.executionSourceId
|
|
10138
|
+
) : null;
|
|
10139
|
+
responsiveness?.start(this.request.session ? "resumed" : "fresh");
|
|
10069
10140
|
try {
|
|
10070
10141
|
for await (const event of this.adapter.runTurn(this.request, abortController.signal, {
|
|
10071
|
-
fresh: (reason) =>
|
|
10142
|
+
fresh: async (reason) => {
|
|
10143
|
+
const fresh = await this.freshRequest(reason);
|
|
10144
|
+
if (fresh) responsiveness?.start("fallback");
|
|
10145
|
+
return fresh;
|
|
10146
|
+
}
|
|
10072
10147
|
})) {
|
|
10148
|
+
responsiveness?.event(event);
|
|
10073
10149
|
transcript2?.write(event);
|
|
10074
10150
|
o.eventCounts[event.type] += 1;
|
|
10075
10151
|
if (isContentBearingEvent(event)) o.contentBearingEvents += 1;
|
|
@@ -11901,7 +11977,7 @@ function isDevicePaired() {
|
|
|
11901
11977
|
// src/runtime.ts
|
|
11902
11978
|
init_config();
|
|
11903
11979
|
init_cabane_command();
|
|
11904
|
-
import { randomUUID as
|
|
11980
|
+
import { randomUUID as randomUUID7 } from "crypto";
|
|
11905
11981
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
11906
11982
|
|
|
11907
11983
|
// src/dashboard/server.ts
|
|
@@ -12475,7 +12551,7 @@ function turnFailureCopy(reason, runtime) {
|
|
|
12475
12551
|
init_api_error_shape();
|
|
12476
12552
|
init_boot_id();
|
|
12477
12553
|
init_api();
|
|
12478
|
-
import { randomUUID as
|
|
12554
|
+
import { randomUUID as randomUUID6 } from "crypto";
|
|
12479
12555
|
|
|
12480
12556
|
// src/device-api.ts
|
|
12481
12557
|
init_errors();
|
|
@@ -12858,7 +12934,7 @@ var ConnectorHealthStore = class {
|
|
|
12858
12934
|
};
|
|
12859
12935
|
|
|
12860
12936
|
// src/dispatcher.ts
|
|
12861
|
-
import { randomUUID as
|
|
12937
|
+
import { randomUUID as randomUUID5 } from "crypto";
|
|
12862
12938
|
|
|
12863
12939
|
// src/runner/launch.ts
|
|
12864
12940
|
init_src();
|
|
@@ -13348,7 +13424,7 @@ var Dispatcher = class {
|
|
|
13348
13424
|
notifyEnd: (info) => this.notifyEnd(info)
|
|
13349
13425
|
},
|
|
13350
13426
|
payload,
|
|
13351
|
-
{ turnId: opts.turnId ??
|
|
13427
|
+
{ turnId: opts.turnId ?? randomUUID5(), resumed: opts.resumed === true }
|
|
13352
13428
|
);
|
|
13353
13429
|
}
|
|
13354
13430
|
// Cancel the named turn. An older server omits turnId and cancels the pair.
|
|
@@ -15489,7 +15565,7 @@ var CompanionSupervisor = class {
|
|
|
15489
15565
|
workspaceId,
|
|
15490
15566
|
agent,
|
|
15491
15567
|
payload,
|
|
15492
|
-
turnIdForEvent(workspaceId, dispatchId) ??
|
|
15568
|
+
turnIdForEvent(workspaceId, dispatchId) ?? randomUUID6(),
|
|
15493
15569
|
attempt,
|
|
15494
15570
|
dispatchId
|
|
15495
15571
|
);
|
|
@@ -15502,7 +15578,7 @@ var CompanionSupervisor = class {
|
|
|
15502
15578
|
);
|
|
15503
15579
|
}
|
|
15504
15580
|
const resumedTurnId = recoveredTurnId ?? (dispatchId ? turnIdForEvent(workspaceId, dispatchId) : null);
|
|
15505
|
-
const turnId = resumedTurnId ??
|
|
15581
|
+
const turnId = resumedTurnId ?? randomUUID6();
|
|
15506
15582
|
if (dispatchId) {
|
|
15507
15583
|
const liveTurnIds = rememberTurnId(workspaceId, dispatchId, turnId);
|
|
15508
15584
|
if (liveTurnIds > TURN_ID_OVERFLOW_WARN) {
|
|
@@ -16020,7 +16096,7 @@ async function createCompanionRuntime(opts = {}) {
|
|
|
16020
16096
|
throw err;
|
|
16021
16097
|
}
|
|
16022
16098
|
configureLogger(log2, cfg);
|
|
16023
|
-
const instanceId =
|
|
16099
|
+
const instanceId = randomUUID7();
|
|
16024
16100
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
16025
16101
|
const pre = readLiveRuntimeState();
|
|
16026
16102
|
if (pre && await verifyRuntime(pre) === "stale") clearRuntimeState();
|
package/dist/runtime.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/runtime.ts
|
|
2
|
-
import { randomUUID as
|
|
2
|
+
import { randomUUID as randomUUID7 } from "crypto";
|
|
3
3
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
4
4
|
|
|
5
5
|
// src/cabane-command.ts
|
|
@@ -1864,7 +1864,7 @@ import { randomUUID } from "crypto";
|
|
|
1864
1864
|
var bootId = randomUUID();
|
|
1865
1865
|
|
|
1866
1866
|
// src/supervisor.ts
|
|
1867
|
-
import { randomUUID as
|
|
1867
|
+
import { randomUUID as randomUUID6 } from "crypto";
|
|
1868
1868
|
|
|
1869
1869
|
// src/api.ts
|
|
1870
1870
|
import { promisify } from "util";
|
|
@@ -2226,7 +2226,12 @@ var CabaneApi = class {
|
|
|
2226
2226
|
this.opts.outbox?.remove(activeRunOutboxKey(conversationId, agentId), ACTIVE_RUN_OUTBOX_SEQ);
|
|
2227
2227
|
return res;
|
|
2228
2228
|
}
|
|
2229
|
-
return this.request(
|
|
2229
|
+
return this.request(
|
|
2230
|
+
"PATCH",
|
|
2231
|
+
path,
|
|
2232
|
+
body,
|
|
2233
|
+
body.responsiveness ? { signal: AbortSignal.timeout(5e3) } : {}
|
|
2234
|
+
);
|
|
2230
2235
|
}
|
|
2231
2236
|
// Send-or-enqueue for an active-run flag write, last-writer-wins per
|
|
2232
2237
|
// (conversation, agent) pair. Like `durableCommit`, except:
|
|
@@ -7552,7 +7557,7 @@ var ConnectorHealthStore = class {
|
|
|
7552
7557
|
};
|
|
7553
7558
|
|
|
7554
7559
|
// src/dispatcher.ts
|
|
7555
|
-
import { randomUUID as
|
|
7560
|
+
import { randomUUID as randomUUID5 } from "crypto";
|
|
7556
7561
|
|
|
7557
7562
|
// src/runner/launch.ts
|
|
7558
7563
|
import { createInterface } from "readline";
|
|
@@ -8216,8 +8221,11 @@ async function runTurnInRunner(opts, launch, duties, payload, handleOpts) {
|
|
|
8216
8221
|
return { ok: false, durationMs, reason };
|
|
8217
8222
|
}
|
|
8218
8223
|
|
|
8224
|
+
// src/turn-responsiveness.ts
|
|
8225
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
8226
|
+
|
|
8219
8227
|
// src/turn-execution.ts
|
|
8220
|
-
import { createHash as createHash2, randomUUID as
|
|
8228
|
+
import { createHash as createHash2, randomUUID as randomUUID4 } from "crypto";
|
|
8221
8229
|
import { existsSync as existsSync12, mkdirSync as mkdirSync9 } from "fs";
|
|
8222
8230
|
|
|
8223
8231
|
// src/grants.ts
|
|
@@ -8284,7 +8292,7 @@ import { statSync as statSync3 } from "fs";
|
|
|
8284
8292
|
import { join as join14 } from "path";
|
|
8285
8293
|
|
|
8286
8294
|
// src/turn-control-tools.ts
|
|
8287
|
-
import { randomUUID as
|
|
8295
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
8288
8296
|
import { z as z16 } from "zod";
|
|
8289
8297
|
var COMPANION_LOCAL_MCP_SERVER = TURN_CONTROL_MCP_SERVER;
|
|
8290
8298
|
var COMPANION_LOCAL_TOOL_GLOB = `mcp__${COMPANION_LOCAL_MCP_SERVER}__*`;
|
|
@@ -8583,7 +8591,7 @@ var Dispatcher = class {
|
|
|
8583
8591
|
notifyEnd: (info) => this.notifyEnd(info)
|
|
8584
8592
|
},
|
|
8585
8593
|
payload,
|
|
8586
|
-
{ turnId: opts.turnId ??
|
|
8594
|
+
{ turnId: opts.turnId ?? randomUUID5(), resumed: opts.resumed === true }
|
|
8587
8595
|
);
|
|
8588
8596
|
}
|
|
8589
8597
|
// Cancel the named turn. An older server omits turnId and cancels the pair.
|
|
@@ -11102,7 +11110,7 @@ var CompanionSupervisor = class {
|
|
|
11102
11110
|
workspaceId,
|
|
11103
11111
|
agent,
|
|
11104
11112
|
payload,
|
|
11105
|
-
turnIdForEvent(workspaceId, dispatchId) ??
|
|
11113
|
+
turnIdForEvent(workspaceId, dispatchId) ?? randomUUID6(),
|
|
11106
11114
|
attempt,
|
|
11107
11115
|
dispatchId
|
|
11108
11116
|
);
|
|
@@ -11115,7 +11123,7 @@ var CompanionSupervisor = class {
|
|
|
11115
11123
|
);
|
|
11116
11124
|
}
|
|
11117
11125
|
const resumedTurnId = recoveredTurnId ?? (dispatchId ? turnIdForEvent(workspaceId, dispatchId) : null);
|
|
11118
|
-
const turnId = resumedTurnId ??
|
|
11126
|
+
const turnId = resumedTurnId ?? randomUUID6();
|
|
11119
11127
|
if (dispatchId) {
|
|
11120
11128
|
const liveTurnIds = rememberTurnId(workspaceId, dispatchId, turnId);
|
|
11121
11129
|
if (liveTurnIds > TURN_ID_OVERFLOW_WARN) {
|
|
@@ -11631,7 +11639,7 @@ async function createCompanionRuntime(opts = {}) {
|
|
|
11631
11639
|
throw err;
|
|
11632
11640
|
}
|
|
11633
11641
|
configureLogger(log, cfg);
|
|
11634
|
-
const instanceId =
|
|
11642
|
+
const instanceId = randomUUID7();
|
|
11635
11643
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
11636
11644
|
const pre = readLiveRuntimeState();
|
|
11637
11645
|
if (pre && await verifyRuntime(pre) === "stale") clearRuntimeState();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cabane/companion",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.211",
|
|
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",
|