@cabane/companion 0.6.2 → 0.6.4

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
@@ -52,7 +52,7 @@ On your machine, start the short-code pairing flow:
52
52
 
53
53
  ```sh
54
54
  cabane-companion pair
55
- # Enter this code at https://cabane.ai/settings/companions
55
+ # Enter this code at https://app.cabane.ai/settings/companions
56
56
  #
57
57
  # ABCD-EFGH
58
58
  #
package/dist/cli.js CHANGED
@@ -900,7 +900,7 @@ async function postJson(baseUrl, path3, body) {
900
900
  if (res.status >= 400) {
901
901
  if (res.status === 404 && path3.endsWith("/code")) {
902
902
  throw new CompanionError(
903
- `this cabane server (${baseUrl}) doesn't support device-flow pairing yet. Update the server to a version that supports \`cabane-companion pair\`.`
903
+ `no device-flow pairing endpoint at ${baseUrl}. Either that server predates \`cabane-companion pair\`, or it isn't a Cabane API origin \u2014 the hosted app is https://app.cabane.ai (pass \`--server <url>\` for your own instance).`
904
904
  );
905
905
  }
906
906
  const msg = parsed && typeof parsed === "object" && "error" in parsed ? String(parsed.error) : `${res.status}`;
@@ -959,7 +959,7 @@ async function runDeviceFlow(baseUrl, print, opts = {}) {
959
959
  }
960
960
 
961
961
  // src/pairing-config.ts
962
- var DEFAULT_BASE_URL = "https://cabane.ai";
962
+ var DEFAULT_BASE_URL = "https://app.cabane.ai";
963
963
  function resolvePairBaseUrl(server) {
964
964
  const raw = (server ?? process.env.CABANE_BASE_URL ?? DEFAULT_BASE_URL).trim();
965
965
  if (!isAllowedBaseUrl(raw)) {
@@ -7331,7 +7331,10 @@ ${reason}`,
7331
7331
  ...this.opts.local.claudeCode ? { claudeCode: this.opts.local.claudeCode } : {}
7332
7332
  });
7333
7333
  const onWarn = (msg, meta) => turnLog.warn(meta ?? {}, msg);
7334
- const adapters = [createClaudeCodeAdapter({ queryFn: this.opts.queryFn, onWarn })];
7334
+ const adapters = [];
7335
+ if (this.opts.claudeCodeAvailable?.() ?? true) {
7336
+ adapters.push(createClaudeCodeAdapter({ queryFn: this.opts.queryFn, onWarn }));
7337
+ }
7335
7338
  if (this.opts.opencodeServerUrl) {
7336
7339
  adapters.push(createOpencodeAdapter({ serverUrl: this.opts.opencodeServerUrl, onWarn }));
7337
7340
  }
@@ -8384,7 +8387,7 @@ var CompanionSupervisor = class {
8384
8387
  // until the first re-probe lands. Same exit-0 `claude --version` signal
8385
8388
  // either way, so the manifest's claude-code advertising is unchanged in
8386
8389
  // meaning — just refreshed on the beat instead of frozen at boot.
8387
- claudeCode: this.harnessSignals?.claudeOnPath ?? this.claudeCode,
8390
+ claudeCode: this.claudeCodePresent(),
8388
8391
  opencode: !!this.config.opencode?.serverUrl,
8389
8392
  // CT481: advertise codex when the operator enabled it (config-gated,
8390
8393
  // like opencode — the CLI's presence is the operator's responsibility;
@@ -8607,6 +8610,13 @@ var CompanionSupervisor = class {
8607
8610
  "companion: stopped agent (unassigned)"
8608
8611
  );
8609
8612
  }
8613
+ // CT833: is Claude Code on this machine right now? The ONE signal both the
8614
+ // heartbeat manifest and the dispatcher's adapter registry read, so what the
8615
+ // device advertises and what it can actually select can't disagree. Live (the
8616
+ // per-beat re-probe), falling back to the boot probe until the first one lands.
8617
+ claudeCodePresent() {
8618
+ return this.harnessSignals?.claudeOnPath ?? this.claudeCode;
8619
+ }
8610
8620
  buildDispatcher(ctx) {
8611
8621
  if (this.dispatcherFactory) return this.dispatcherFactory(ctx);
8612
8622
  return new Dispatcher({
@@ -8624,6 +8634,10 @@ var CompanionSupervisor = class {
8624
8634
  }),
8625
8635
  runConfig: ctx.runConfig,
8626
8636
  log: this.log,
8637
+ // CT833: register the claude-code adapter only when `claude` is actually on
8638
+ // this machine — read per turn (not captured here), so a harness installed
8639
+ // after boot works on the next turn exactly as it appears on the next beat.
8640
+ claudeCodeAvailable: () => this.claudeCodePresent(),
8627
8641
  // CT270: the opencode server URL (operator-configured), when this device
8628
8642
  // offers the opencode runtime. Threaded so an opencode turn selects the
8629
8643
  // opencode adapter; unset leaves the device claude-code-only.
@@ -9801,7 +9815,7 @@ program.name("cabane-companion").description(
9801
9815
  ).version(COMPANION_VERSION);
9802
9816
  program.command("pair").description(
9803
9817
  "pair this device with cabane \u2014 shows a short code you confirm in Settings \u2192 Devices."
9804
- ).allowExcessArguments(false).option("--server <url>", "the cabane instance to pair with (default https://cabane.ai)").action(async (opts) => {
9818
+ ).allowExcessArguments(false).option("--server <url>", "the cabane instance to pair with (default https://app.cabane.ai)").action(async (opts) => {
9805
9819
  await pair({
9806
9820
  ...opts.server !== void 0 ? { server: opts.server } : {}
9807
9821
  });
@@ -292,7 +292,7 @@ async function postJson(baseUrl, path, body) {
292
292
  if (res.status >= 400) {
293
293
  if (res.status === 404 && path.endsWith("/code")) {
294
294
  throw new CompanionError(
295
- `this cabane server (${baseUrl}) doesn't support device-flow pairing yet. Update the server to a version that supports \`cabane-companion pair\`.`
295
+ `no device-flow pairing endpoint at ${baseUrl}. Either that server predates \`cabane-companion pair\`, or it isn't a Cabane API origin \u2014 the hosted app is https://app.cabane.ai (pass \`--server <url>\` for your own instance).`
296
296
  );
297
297
  }
298
298
  const msg = parsed && typeof parsed === "object" && "error" in parsed ? String(parsed.error) : `${res.status}`;
@@ -351,7 +351,7 @@ async function runDeviceFlow(baseUrl, print, opts = {}) {
351
351
  }
352
352
 
353
353
  // src/pairing-config.ts
354
- var DEFAULT_BASE_URL = "https://cabane.ai";
354
+ var DEFAULT_BASE_URL = "https://app.cabane.ai";
355
355
  function resolvePairBaseUrl(server) {
356
356
  const raw = (server ?? process.env.CABANE_BASE_URL ?? DEFAULT_BASE_URL).trim();
357
357
  if (!isAllowedBaseUrl(raw)) {
package/dist/runtime.js CHANGED
@@ -6984,7 +6984,10 @@ ${reason}`,
6984
6984
  ...this.opts.local.claudeCode ? { claudeCode: this.opts.local.claudeCode } : {}
6985
6985
  });
6986
6986
  const onWarn = (msg, meta) => turnLog.warn(meta ?? {}, msg);
6987
- const adapters = [createClaudeCodeAdapter({ queryFn: this.opts.queryFn, onWarn })];
6987
+ const adapters = [];
6988
+ if (this.opts.claudeCodeAvailable?.() ?? true) {
6989
+ adapters.push(createClaudeCodeAdapter({ queryFn: this.opts.queryFn, onWarn }));
6990
+ }
6988
6991
  if (this.opts.opencodeServerUrl) {
6989
6992
  adapters.push(createOpencodeAdapter({ serverUrl: this.opts.opencodeServerUrl, onWarn }));
6990
6993
  }
@@ -8037,7 +8040,7 @@ var CompanionSupervisor = class {
8037
8040
  // until the first re-probe lands. Same exit-0 `claude --version` signal
8038
8041
  // either way, so the manifest's claude-code advertising is unchanged in
8039
8042
  // meaning — just refreshed on the beat instead of frozen at boot.
8040
- claudeCode: this.harnessSignals?.claudeOnPath ?? this.claudeCode,
8043
+ claudeCode: this.claudeCodePresent(),
8041
8044
  opencode: !!this.config.opencode?.serverUrl,
8042
8045
  // CT481: advertise codex when the operator enabled it (config-gated,
8043
8046
  // like opencode — the CLI's presence is the operator's responsibility;
@@ -8260,6 +8263,13 @@ var CompanionSupervisor = class {
8260
8263
  "companion: stopped agent (unassigned)"
8261
8264
  );
8262
8265
  }
8266
+ // CT833: is Claude Code on this machine right now? The ONE signal both the
8267
+ // heartbeat manifest and the dispatcher's adapter registry read, so what the
8268
+ // device advertises and what it can actually select can't disagree. Live (the
8269
+ // per-beat re-probe), falling back to the boot probe until the first one lands.
8270
+ claudeCodePresent() {
8271
+ return this.harnessSignals?.claudeOnPath ?? this.claudeCode;
8272
+ }
8263
8273
  buildDispatcher(ctx) {
8264
8274
  if (this.dispatcherFactory) return this.dispatcherFactory(ctx);
8265
8275
  return new Dispatcher({
@@ -8277,6 +8287,10 @@ var CompanionSupervisor = class {
8277
8287
  }),
8278
8288
  runConfig: ctx.runConfig,
8279
8289
  log: this.log,
8290
+ // CT833: register the claude-code adapter only when `claude` is actually on
8291
+ // this machine — read per turn (not captured here), so a harness installed
8292
+ // after boot works on the next turn exactly as it appears on the next beat.
8293
+ claudeCodeAvailable: () => this.claudeCodePresent(),
8280
8294
  // CT270: the opencode server URL (operator-configured), when this device
8281
8295
  // offers the opencode runtime. Threaded so an opencode turn selects the
8282
8296
  // opencode adapter; unset leaves the device claude-code-only.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cabane/companion",
3
- "version": "0.6.2",
3
+ "version": "0.6.4",
4
4
  "type": "module",
5
5
  "description": "The Cabane Companion (headless): connect a coding 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",