@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 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/what-the-companion-does), then [Mac setup](https://cabane.ai/docs/on-a-mac), [Windows setup](https://cabane.ai/docs/on-windows) or [Server and VPS setup](https://cabane.ai/docs/on-a-server). [FAQ and Help](https://cabane.ai/docs/faq) covers sign-in and troubleshooting. This README is the device-side reference: commands, configuration and local state.
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/what-the-companion-does) explains the layers, records and access.
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/on-a-mac#3-sign-in-inside-the-environment), [Windows setup](https://cabane.ai/docs/on-windows#3-sign-in-inside-the-environment) or [Server and VPS setup](https://cabane.ai/docs/on-a-server#3-sign-in-without-a-browser), then check `cabane status`.
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/on-a-server) 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.
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/on-a-server#4-keep-it-running-and-update).
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/on-a-server#rotate-a-docker-devices-token).
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/how-much-access-agents-get), and configure the tools through [Harness sandboxes](https://cabane.ai/docs/harness-sandboxes).
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("PATCH", path, body);
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 randomUUID2 } from "crypto";
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: randomUUID2(),
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: randomUUID2(),
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: randomUUID2(),
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: randomUUID2() }),
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: randomUUID2() }),
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 randomUUID3 } from "crypto";
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 ?? randomUUID3();
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:${randomUUID3()}`, seq: this.nextSeq() };
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) => this.freshRequest(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 randomUUID6 } from "crypto";
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 randomUUID5 } from "crypto";
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 randomUUID4 } from "crypto";
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 ?? randomUUID4(), resumed: opts.resumed === true }
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) ?? randomUUID5(),
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 ?? randomUUID5();
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 = randomUUID6();
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 randomUUID6 } from "crypto";
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 randomUUID5 } from "crypto";
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("PATCH", path, body);
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 randomUUID4 } from "crypto";
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 randomUUID3 } from "crypto";
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 randomUUID2 } from "crypto";
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 ?? randomUUID4(), resumed: opts.resumed === true }
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) ?? randomUUID5(),
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 ?? randomUUID5();
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 = randomUUID6();
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.209",
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",