@cabane/companion 0.6.153 → 0.6.155
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 +67 -30
- package/dist/postinstall.js +18 -5
- package/dist/runtime.js +65 -28
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -585,7 +585,8 @@ var init_config = __esm({
|
|
|
585
585
|
// src/bundled-binaries.ts
|
|
586
586
|
import { realpathSync, statSync } from "fs";
|
|
587
587
|
import { createRequire } from "module";
|
|
588
|
-
import {
|
|
588
|
+
import { homedir as homedir2 } from "os";
|
|
589
|
+
import { dirname as dirname2, join as join3, sep } from "path";
|
|
589
590
|
import { fileURLToPath } from "url";
|
|
590
591
|
function nodeResolveSelf(specifier) {
|
|
591
592
|
const here = fileURLToPath(import.meta.url);
|
|
@@ -741,25 +742,36 @@ function resolveBundledBinary(runtime, env = defaultResolveEnv()) {
|
|
|
741
742
|
function missingNoun(status2) {
|
|
742
743
|
return status2 === "executable_missing" ? "executable" : "platform package";
|
|
743
744
|
}
|
|
744
|
-
function
|
|
745
|
-
|
|
745
|
+
function companionInstall(execPath = process.execPath, home = homedir2()) {
|
|
746
|
+
const real = (path) => {
|
|
747
|
+
try {
|
|
748
|
+
return realpathSync(path);
|
|
749
|
+
} catch {
|
|
750
|
+
return path;
|
|
751
|
+
}
|
|
752
|
+
};
|
|
753
|
+
const scriptNode = join3(real(home), ".cabane", "node") + sep;
|
|
754
|
+
return real(execPath).startsWith(scriptNode) ? "script" : "npm";
|
|
755
|
+
}
|
|
756
|
+
function repairCommands(install = companionInstall()) {
|
|
757
|
+
return install === "script" ? [INSTALL_SCRIPT_COMMAND] : ["npm i -g @cabane/companion --include=optional"];
|
|
746
758
|
}
|
|
747
|
-
function repairAction() {
|
|
748
|
-
return `Reinstall with \`${repairCommands()[0]}\`.`;
|
|
759
|
+
function repairAction(install = companionInstall()) {
|
|
760
|
+
return `Reinstall with \`${repairCommands(install)[0]}\`.`;
|
|
749
761
|
}
|
|
750
762
|
function startupWarning(r) {
|
|
751
763
|
const label = HARNESS_LABEL[r.runtime];
|
|
752
764
|
return `${label} is ${HARNESS_INTENT_WORD[r.runtime]}, but its installation is incomplete (${missingNoun(r.status)} is missing). It cannot run turns until repaired. ${repairAction()} Then restart the companion.`;
|
|
753
765
|
}
|
|
754
|
-
function harnessIssueNote(runtime, status2) {
|
|
766
|
+
function harnessIssueNote(runtime, status2, install = companionInstall()) {
|
|
755
767
|
const intent = HARNESS_INTENT_WORD[runtime];
|
|
756
768
|
const capitalized = `${intent[0].toUpperCase()}${intent.slice(1)}`;
|
|
757
|
-
return `${capitalized}, but @cabane/companion's bundled ${HARNESS_LABEL[runtime]} ${missingNoun(status2)} is missing. ${repairAction()} Then restart the companion.`;
|
|
769
|
+
return `${capitalized}, but @cabane/companion's bundled ${HARNESS_LABEL[runtime]} ${missingNoun(status2)} is missing. ${repairAction(install)} Then restart the companion.`;
|
|
758
770
|
}
|
|
759
771
|
function turnIncompleteCopy(runtime) {
|
|
760
772
|
return `**This device's ${HARNESS_LABEL[runtime]} runtime is incomplete.** ${repairAction()} Restart it, then try again.`;
|
|
761
773
|
}
|
|
762
|
-
var CLAUDE_SDK, CODEX_SDK, CODEX_CLI, CODEX_PACKAGE_BY_TRIPLE, HARNESS_LABEL, HARNESS_INTENT_WORD;
|
|
774
|
+
var CLAUDE_SDK, CODEX_SDK, CODEX_CLI, CODEX_PACKAGE_BY_TRIPLE, HARNESS_LABEL, HARNESS_INTENT_WORD, INSTALL_SCRIPT_COMMAND;
|
|
763
775
|
var init_bundled_binaries = __esm({
|
|
764
776
|
"src/bundled-binaries.ts"() {
|
|
765
777
|
"use strict";
|
|
@@ -782,12 +794,13 @@ var init_bundled_binaries = __esm({
|
|
|
782
794
|
"claude-code": "connected",
|
|
783
795
|
codex: "enabled"
|
|
784
796
|
};
|
|
797
|
+
INSTALL_SCRIPT_COMMAND = "curl -fsSL https://cabane.ai/install.sh | bash";
|
|
785
798
|
}
|
|
786
799
|
});
|
|
787
800
|
|
|
788
801
|
// src/term.ts
|
|
789
802
|
import { createInterface } from "readline";
|
|
790
|
-
import { homedir as
|
|
803
|
+
import { homedir as homedir3 } from "os";
|
|
791
804
|
import pc from "picocolors";
|
|
792
805
|
function isInteractive() {
|
|
793
806
|
return Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
@@ -800,7 +813,7 @@ function blank() {
|
|
|
800
813
|
process.stdout.write("\n");
|
|
801
814
|
}
|
|
802
815
|
function tildePath(path) {
|
|
803
|
-
const home =
|
|
816
|
+
const home = homedir3();
|
|
804
817
|
if (home && path.startsWith(home + "/")) return `~${path.slice(home.length)}`;
|
|
805
818
|
return path;
|
|
806
819
|
}
|
|
@@ -2543,8 +2556,8 @@ var init_policy = __esm({
|
|
|
2543
2556
|
// packages/agent-runtime/src/claude-code/model.ts
|
|
2544
2557
|
function parseClaudeCodeModel(model) {
|
|
2545
2558
|
if (!model) return null;
|
|
2546
|
-
const
|
|
2547
|
-
const bare =
|
|
2559
|
+
const sep4 = model.indexOf("/");
|
|
2560
|
+
const bare = sep4 === -1 || model.slice(0, sep4) !== "anthropic" ? model : model.slice(sep4 + 1);
|
|
2548
2561
|
return bare === CLAUDE_CODE_DEFAULT_MODEL_BARE ? null : model;
|
|
2549
2562
|
}
|
|
2550
2563
|
var CLAUDE_CODE_DEFAULT_MODEL_BARE;
|
|
@@ -4097,9 +4110,9 @@ var init_policy2 = __esm({
|
|
|
4097
4110
|
|
|
4098
4111
|
// packages/agent-runtime/src/opencode/model.ts
|
|
4099
4112
|
function parseOpencodeModel(model) {
|
|
4100
|
-
const
|
|
4101
|
-
if (
|
|
4102
|
-
return { providerID: model.slice(0,
|
|
4113
|
+
const sep4 = model.indexOf("/");
|
|
4114
|
+
if (sep4 === -1) return { providerID: "", modelID: model };
|
|
4115
|
+
return { providerID: model.slice(0, sep4), modelID: model.slice(sep4 + 1) };
|
|
4103
4116
|
}
|
|
4104
4117
|
var init_model2 = __esm({
|
|
4105
4118
|
"packages/agent-runtime/src/opencode/model.ts"() {
|
|
@@ -4400,10 +4413,10 @@ async function* parseSseStream(body, sessionId, signal) {
|
|
|
4400
4413
|
const { value, done } = await reader.read();
|
|
4401
4414
|
if (done) return;
|
|
4402
4415
|
buf += decoder.decode(value, { stream: true });
|
|
4403
|
-
let
|
|
4404
|
-
while ((
|
|
4405
|
-
const frame = buf.slice(0,
|
|
4406
|
-
buf = buf.slice(
|
|
4416
|
+
let sep4;
|
|
4417
|
+
while ((sep4 = buf.indexOf("\n\n")) !== -1) {
|
|
4418
|
+
const frame = buf.slice(0, sep4);
|
|
4419
|
+
buf = buf.slice(sep4 + 2);
|
|
4407
4420
|
const data = frame.split("\n").filter((l) => l.startsWith("data:")).map((l) => l.slice(5).trim()).join("");
|
|
4408
4421
|
if (!data) continue;
|
|
4409
4422
|
let ev;
|
|
@@ -5414,8 +5427,8 @@ var init_policy3 = __esm({
|
|
|
5414
5427
|
|
|
5415
5428
|
// packages/agent-runtime/src/codex/model.ts
|
|
5416
5429
|
function parseCodexModel(model) {
|
|
5417
|
-
const
|
|
5418
|
-
const bare =
|
|
5430
|
+
const sep4 = model.indexOf("/");
|
|
5431
|
+
const bare = sep4 === -1 || model.slice(0, sep4) !== "openai" ? model : model.slice(sep4 + 1);
|
|
5419
5432
|
return CODEX_DEFAULT_MODEL_BARES.has(bare) ? null : bare;
|
|
5420
5433
|
}
|
|
5421
5434
|
var CODEX_DEFAULT_MODEL_BARES;
|
|
@@ -10232,6 +10245,23 @@ var init_dispatcher = __esm({
|
|
|
10232
10245
|
}
|
|
10233
10246
|
return true;
|
|
10234
10247
|
}
|
|
10248
|
+
// Abort every run in flight in THIS process, whatever its conversation. For
|
|
10249
|
+
// an agent taken off this device: nothing it is still running here is
|
|
10250
|
+
// legitimate, and a cancel frame that arrives after it is dropped from the
|
|
10251
|
+
// roster finds no dispatcher to reach. True if any was aborted.
|
|
10252
|
+
cancelAll() {
|
|
10253
|
+
let aborted = false;
|
|
10254
|
+
for (const pair2 of this.aborts.values()) {
|
|
10255
|
+
for (const ac of [...pair2.values()]) {
|
|
10256
|
+
try {
|
|
10257
|
+
ac.abort();
|
|
10258
|
+
aborted = true;
|
|
10259
|
+
} catch {
|
|
10260
|
+
}
|
|
10261
|
+
}
|
|
10262
|
+
}
|
|
10263
|
+
return aborted;
|
|
10264
|
+
}
|
|
10235
10265
|
};
|
|
10236
10266
|
}
|
|
10237
10267
|
});
|
|
@@ -10493,8 +10523,8 @@ import {
|
|
|
10493
10523
|
} from "fs";
|
|
10494
10524
|
import { createRequire as createRequire2 } from "module";
|
|
10495
10525
|
import { isIP } from "net";
|
|
10496
|
-
import { homedir as
|
|
10497
|
-
import { dirname as dirname8, join as join19, sep as
|
|
10526
|
+
import { homedir as homedir4, networkInterfaces, tmpdir as tmpdir4, userInfo as userInfo2 } from "os";
|
|
10527
|
+
import { dirname as dirname8, join as join19, sep as sep3 } from "path";
|
|
10498
10528
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
10499
10529
|
import { SandboxManager } from "@anthropic-ai/sandbox-runtime";
|
|
10500
10530
|
function accountHome() {
|
|
@@ -10620,13 +10650,13 @@ function companionStoreWatch(log) {
|
|
|
10620
10650
|
return new CompanionStoreWatch({
|
|
10621
10651
|
log,
|
|
10622
10652
|
roots: () => {
|
|
10623
|
-
const home =
|
|
10653
|
+
const home = homedir4();
|
|
10624
10654
|
return storeWalkRoots([.../* @__PURE__ */ new Set([home, accountHome() ?? home])], cabaneDir());
|
|
10625
10655
|
}
|
|
10626
10656
|
});
|
|
10627
10657
|
}
|
|
10628
10658
|
function isAtOrUnder(path, dir2) {
|
|
10629
|
-
return path === dir2 || path.startsWith(dir2 +
|
|
10659
|
+
return path === dir2 || path.startsWith(dir2 + sep3);
|
|
10630
10660
|
}
|
|
10631
10661
|
function expandHome(path, home) {
|
|
10632
10662
|
if (path === "~") return home;
|
|
@@ -10765,7 +10795,7 @@ async function prepareHarnessSandbox(input) {
|
|
|
10765
10795
|
baseUrl: input.baseUrl,
|
|
10766
10796
|
resolved: await resolvedAddresses(input.baseUrl),
|
|
10767
10797
|
ownAddresses: ownAddresses(),
|
|
10768
|
-
home:
|
|
10798
|
+
home: homedir4(),
|
|
10769
10799
|
accountHome: accountHome(),
|
|
10770
10800
|
tmp: tmpdir4(),
|
|
10771
10801
|
cabaneDir: cabaneDir(),
|
|
@@ -11797,7 +11827,7 @@ function runtimeIssuesFor(gates) {
|
|
|
11797
11827
|
for (const name of ["claude-code", "codex"]) {
|
|
11798
11828
|
const gate = name === "codex" ? gates.codex : gates.claudeCode;
|
|
11799
11829
|
if (!gate.intended || gate.bundled === "present") continue;
|
|
11800
|
-
issues.push({ name, reason: gate.bundled });
|
|
11830
|
+
issues.push({ name, reason: gate.bundled, install: gates.install });
|
|
11801
11831
|
}
|
|
11802
11832
|
return issues;
|
|
11803
11833
|
}
|
|
@@ -13994,7 +14024,7 @@ function publishStaged(from, to, move = atomicMove) {
|
|
|
13994
14024
|
// src/providers/runner-base.ts
|
|
13995
14025
|
import { createHash as createHash3 } from "crypto";
|
|
13996
14026
|
import { existsSync as existsSync12, realpathSync as realpathSync2 } from "fs";
|
|
13997
|
-
import { dirname as dirname7, join as join17, sep } from "path";
|
|
14027
|
+
import { dirname as dirname7, join as join17, sep as sep2 } from "path";
|
|
13998
14028
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
13999
14029
|
var COMPANION_MOUNT = "/opt/cabane/companion";
|
|
14000
14030
|
var BASE_DOCKERFILE = `FROM node:22-slim
|
|
@@ -14049,7 +14079,7 @@ function ownInstall(moduleFile = fileURLToPath3(import.meta.url)) {
|
|
|
14049
14079
|
const sdk = join17(dir2, "node_modules", "@anthropic-ai", "claude-agent-sdk");
|
|
14050
14080
|
if (!existsSync12(sdk)) return null;
|
|
14051
14081
|
const root = realpathSync2(dir2);
|
|
14052
|
-
return realpathSync2(sdk).startsWith(root +
|
|
14082
|
+
return realpathSync2(sdk).startsWith(root + sep2) ? root : null;
|
|
14053
14083
|
}
|
|
14054
14084
|
function companionSource(input) {
|
|
14055
14085
|
if (input.configured) {
|
|
@@ -15738,6 +15768,12 @@ var CompanionSupervisor = class {
|
|
|
15738
15768
|
removeAgent(wr, agentId) {
|
|
15739
15769
|
const runner = wr.agents.get(agentId);
|
|
15740
15770
|
if (!runner) return;
|
|
15771
|
+
if (runner.dispatcher.cancelAll()) {
|
|
15772
|
+
this.log.info(
|
|
15773
|
+
{ workspaceId: wr.workspaceId, agentId },
|
|
15774
|
+
`Stopped ${runner.displayName}'s running turns (no longer on this device)`
|
|
15775
|
+
);
|
|
15776
|
+
}
|
|
15741
15777
|
runner.cancelDrain();
|
|
15742
15778
|
wr.agents.delete(agentId);
|
|
15743
15779
|
this.hub.removeAgent(wr.workspaceId, agentId);
|
|
@@ -15778,7 +15814,8 @@ var CompanionSupervisor = class {
|
|
|
15778
15814
|
intended: isClaudeCodeConnected(this.config),
|
|
15779
15815
|
bundled: this.bundledStatus("claude-code")
|
|
15780
15816
|
},
|
|
15781
|
-
codex: { intended: isCodexEnabled(this.config), bundled: this.bundledStatus("codex") }
|
|
15817
|
+
codex: { intended: isCodexEnabled(this.config), bundled: this.bundledStatus("codex") },
|
|
15818
|
+
install: companionInstall()
|
|
15782
15819
|
});
|
|
15783
15820
|
}
|
|
15784
15821
|
// A missing binary is reported ONCE, and again only when the answer CHANGES,
|
package/dist/postinstall.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// src/bundled-binaries.ts
|
|
2
2
|
import { realpathSync, statSync } from "fs";
|
|
3
3
|
import { createRequire } from "module";
|
|
4
|
-
import {
|
|
4
|
+
import { homedir } from "os";
|
|
5
|
+
import { dirname, join, sep } from "path";
|
|
5
6
|
import { fileURLToPath } from "url";
|
|
6
7
|
function nodeResolveSelf(specifier) {
|
|
7
8
|
const here = fileURLToPath(import.meta.url);
|
|
@@ -178,11 +179,23 @@ var HARNESS_LABEL = {
|
|
|
178
179
|
function missingNoun(status) {
|
|
179
180
|
return status === "executable_missing" ? "executable" : "platform package";
|
|
180
181
|
}
|
|
181
|
-
|
|
182
|
-
|
|
182
|
+
var INSTALL_SCRIPT_COMMAND = "curl -fsSL https://cabane.ai/install.sh | bash";
|
|
183
|
+
function companionInstall(execPath = process.execPath, home = homedir()) {
|
|
184
|
+
const real = (path) => {
|
|
185
|
+
try {
|
|
186
|
+
return realpathSync(path);
|
|
187
|
+
} catch {
|
|
188
|
+
return path;
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
const scriptNode = join(real(home), ".cabane", "node") + sep;
|
|
192
|
+
return real(execPath).startsWith(scriptNode) ? "script" : "npm";
|
|
193
|
+
}
|
|
194
|
+
function repairCommands(install = companionInstall()) {
|
|
195
|
+
return install === "script" ? [INSTALL_SCRIPT_COMMAND] : ["npm i -g @cabane/companion --include=optional"];
|
|
183
196
|
}
|
|
184
|
-
function repairAction() {
|
|
185
|
-
return `Reinstall with \`${repairCommands()[0]}\`.`;
|
|
197
|
+
function repairAction(install = companionInstall()) {
|
|
198
|
+
return `Reinstall with \`${repairCommands(install)[0]}\`.`;
|
|
186
199
|
}
|
|
187
200
|
function installWarning(r) {
|
|
188
201
|
return `warning: @cabane/companion is incomplete: its bundled ${HARNESS_LABEL[r.runtime]} ${missingNoun(r.status)} for ${r.platform}-${r.arch} is missing. ${repairAction()}`;
|
package/dist/runtime.js
CHANGED
|
@@ -602,7 +602,8 @@ async function safe(fn) {
|
|
|
602
602
|
// src/bundled-binaries.ts
|
|
603
603
|
import { realpathSync, statSync } from "fs";
|
|
604
604
|
import { createRequire } from "module";
|
|
605
|
-
import {
|
|
605
|
+
import { homedir as homedir2 } from "os";
|
|
606
|
+
import { dirname as dirname2, join as join2, sep } from "path";
|
|
606
607
|
import { fileURLToPath } from "url";
|
|
607
608
|
function nodeResolveSelf(specifier) {
|
|
608
609
|
const here = fileURLToPath(import.meta.url);
|
|
@@ -777,20 +778,32 @@ var HARNESS_INTENT_WORD = {
|
|
|
777
778
|
function missingNoun(status) {
|
|
778
779
|
return status === "executable_missing" ? "executable" : "platform package";
|
|
779
780
|
}
|
|
780
|
-
|
|
781
|
-
|
|
781
|
+
var INSTALL_SCRIPT_COMMAND = "curl -fsSL https://cabane.ai/install.sh | bash";
|
|
782
|
+
function companionInstall(execPath = process.execPath, home = homedir2()) {
|
|
783
|
+
const real = (path) => {
|
|
784
|
+
try {
|
|
785
|
+
return realpathSync(path);
|
|
786
|
+
} catch {
|
|
787
|
+
return path;
|
|
788
|
+
}
|
|
789
|
+
};
|
|
790
|
+
const scriptNode = join2(real(home), ".cabane", "node") + sep;
|
|
791
|
+
return real(execPath).startsWith(scriptNode) ? "script" : "npm";
|
|
792
|
+
}
|
|
793
|
+
function repairCommands(install = companionInstall()) {
|
|
794
|
+
return install === "script" ? [INSTALL_SCRIPT_COMMAND] : ["npm i -g @cabane/companion --include=optional"];
|
|
782
795
|
}
|
|
783
|
-
function repairAction() {
|
|
784
|
-
return `Reinstall with \`${repairCommands()[0]}\`.`;
|
|
796
|
+
function repairAction(install = companionInstall()) {
|
|
797
|
+
return `Reinstall with \`${repairCommands(install)[0]}\`.`;
|
|
785
798
|
}
|
|
786
799
|
function startupWarning(r) {
|
|
787
800
|
const label = HARNESS_LABEL[r.runtime];
|
|
788
801
|
return `${label} is ${HARNESS_INTENT_WORD[r.runtime]}, but its installation is incomplete (${missingNoun(r.status)} is missing). It cannot run turns until repaired. ${repairAction()} Then restart the companion.`;
|
|
789
802
|
}
|
|
790
|
-
function harnessIssueNote(runtime, status) {
|
|
803
|
+
function harnessIssueNote(runtime, status, install = companionInstall()) {
|
|
791
804
|
const intent = HARNESS_INTENT_WORD[runtime];
|
|
792
805
|
const capitalized = `${intent[0].toUpperCase()}${intent.slice(1)}`;
|
|
793
|
-
return `${capitalized}, but @cabane/companion's bundled ${HARNESS_LABEL[runtime]} ${missingNoun(status)} is missing. ${repairAction()} Then restart the companion.`;
|
|
806
|
+
return `${capitalized}, but @cabane/companion's bundled ${HARNESS_LABEL[runtime]} ${missingNoun(status)} is missing. ${repairAction(install)} Then restart the companion.`;
|
|
794
807
|
}
|
|
795
808
|
function turnIncompleteCopy(runtime) {
|
|
796
809
|
return `**This device's ${HARNESS_LABEL[runtime]} runtime is incomplete.** ${repairAction()} Restart it, then try again.`;
|
|
@@ -819,7 +832,7 @@ function runtimeIssuesFor(gates) {
|
|
|
819
832
|
for (const name of ["claude-code", "codex"]) {
|
|
820
833
|
const gate = name === "codex" ? gates.codex : gates.claudeCode;
|
|
821
834
|
if (!gate.intended || gate.bundled === "present") continue;
|
|
822
|
-
issues.push({ name, reason: gate.bundled });
|
|
835
|
+
issues.push({ name, reason: gate.bundled, install: gates.install });
|
|
823
836
|
}
|
|
824
837
|
return issues;
|
|
825
838
|
}
|
|
@@ -3951,8 +3964,8 @@ function readThinking(runtimeOptions) {
|
|
|
3951
3964
|
var CLAUDE_CODE_DEFAULT_MODEL_BARE = "default";
|
|
3952
3965
|
function parseClaudeCodeModel(model) {
|
|
3953
3966
|
if (!model) return null;
|
|
3954
|
-
const
|
|
3955
|
-
const bare =
|
|
3967
|
+
const sep4 = model.indexOf("/");
|
|
3968
|
+
const bare = sep4 === -1 || model.slice(0, sep4) !== "anthropic" ? model : model.slice(sep4 + 1);
|
|
3956
3969
|
return bare === CLAUDE_CODE_DEFAULT_MODEL_BARE ? null : model;
|
|
3957
3970
|
}
|
|
3958
3971
|
|
|
@@ -5407,9 +5420,9 @@ function readOpencodeDialect(runtimeOptions) {
|
|
|
5407
5420
|
|
|
5408
5421
|
// packages/agent-runtime/src/opencode/model.ts
|
|
5409
5422
|
function parseOpencodeModel(model) {
|
|
5410
|
-
const
|
|
5411
|
-
if (
|
|
5412
|
-
return { providerID: model.slice(0,
|
|
5423
|
+
const sep4 = model.indexOf("/");
|
|
5424
|
+
if (sep4 === -1) return { providerID: "", modelID: model };
|
|
5425
|
+
return { providerID: model.slice(0, sep4), modelID: model.slice(sep4 + 1) };
|
|
5413
5426
|
}
|
|
5414
5427
|
|
|
5415
5428
|
// packages/agent-runtime/src/opencode/run-spec.ts
|
|
@@ -5697,10 +5710,10 @@ async function* parseSseStream(body, sessionId, signal) {
|
|
|
5697
5710
|
const { value, done } = await reader.read();
|
|
5698
5711
|
if (done) return;
|
|
5699
5712
|
buf += decoder.decode(value, { stream: true });
|
|
5700
|
-
let
|
|
5701
|
-
while ((
|
|
5702
|
-
const frame = buf.slice(0,
|
|
5703
|
-
buf = buf.slice(
|
|
5713
|
+
let sep4;
|
|
5714
|
+
while ((sep4 = buf.indexOf("\n\n")) !== -1) {
|
|
5715
|
+
const frame = buf.slice(0, sep4);
|
|
5716
|
+
buf = buf.slice(sep4 + 2);
|
|
5704
5717
|
const data = frame.split("\n").filter((l) => l.startsWith("data:")).map((l) => l.slice(5).trim()).join("");
|
|
5705
5718
|
if (!data) continue;
|
|
5706
5719
|
let ev;
|
|
@@ -6640,8 +6653,8 @@ function readCodexDialect(runtimeOptions) {
|
|
|
6640
6653
|
// packages/agent-runtime/src/codex/model.ts
|
|
6641
6654
|
var CODEX_DEFAULT_MODEL_BARES = /* @__PURE__ */ new Set(["default"]);
|
|
6642
6655
|
function parseCodexModel(model) {
|
|
6643
|
-
const
|
|
6644
|
-
const bare =
|
|
6656
|
+
const sep4 = model.indexOf("/");
|
|
6657
|
+
const bare = sep4 === -1 || model.slice(0, sep4) !== "openai" ? model : model.slice(sep4 + 1);
|
|
6645
6658
|
return CODEX_DEFAULT_MODEL_BARES.has(bare) ? null : bare;
|
|
6646
6659
|
}
|
|
6647
6660
|
|
|
@@ -9158,10 +9171,10 @@ async function runTurnInRunner(opts, launch, duties, payload, handleOpts) {
|
|
|
9158
9171
|
|
|
9159
9172
|
// src/term.ts
|
|
9160
9173
|
import { createInterface as createInterface2 } from "readline";
|
|
9161
|
-
import { homedir as
|
|
9174
|
+
import { homedir as homedir3 } from "os";
|
|
9162
9175
|
import pc from "picocolors";
|
|
9163
9176
|
function tildePath(path) {
|
|
9164
|
-
const home =
|
|
9177
|
+
const home = homedir3();
|
|
9165
9178
|
if (home && path.startsWith(home + "/")) return `~${path.slice(home.length)}`;
|
|
9166
9179
|
return path;
|
|
9167
9180
|
}
|
|
@@ -11196,6 +11209,23 @@ var Dispatcher = class {
|
|
|
11196
11209
|
}
|
|
11197
11210
|
return true;
|
|
11198
11211
|
}
|
|
11212
|
+
// Abort every run in flight in THIS process, whatever its conversation. For
|
|
11213
|
+
// an agent taken off this device: nothing it is still running here is
|
|
11214
|
+
// legitimate, and a cancel frame that arrives after it is dropped from the
|
|
11215
|
+
// roster finds no dispatcher to reach. True if any was aborted.
|
|
11216
|
+
cancelAll() {
|
|
11217
|
+
let aborted = false;
|
|
11218
|
+
for (const pair of this.aborts.values()) {
|
|
11219
|
+
for (const ac of [...pair.values()]) {
|
|
11220
|
+
try {
|
|
11221
|
+
ac.abort();
|
|
11222
|
+
aborted = true;
|
|
11223
|
+
} catch {
|
|
11224
|
+
}
|
|
11225
|
+
}
|
|
11226
|
+
}
|
|
11227
|
+
return aborted;
|
|
11228
|
+
}
|
|
11199
11229
|
};
|
|
11200
11230
|
|
|
11201
11231
|
// src/providers/local-process.ts
|
|
@@ -11570,7 +11600,7 @@ function publishStaged(from, to, move = atomicMove) {
|
|
|
11570
11600
|
// src/providers/runner-base.ts
|
|
11571
11601
|
import { createHash as createHash3 } from "crypto";
|
|
11572
11602
|
import { existsSync as existsSync12, realpathSync as realpathSync2 } from "fs";
|
|
11573
|
-
import { dirname as dirname7, join as join17, sep } from "path";
|
|
11603
|
+
import { dirname as dirname7, join as join17, sep as sep2 } from "path";
|
|
11574
11604
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
11575
11605
|
var COMPANION_MOUNT = "/opt/cabane/companion";
|
|
11576
11606
|
var BASE_DOCKERFILE = `FROM node:22-slim
|
|
@@ -11625,7 +11655,7 @@ function ownInstall(moduleFile = fileURLToPath3(import.meta.url)) {
|
|
|
11625
11655
|
const sdk = join17(dir2, "node_modules", "@anthropic-ai", "claude-agent-sdk");
|
|
11626
11656
|
if (!existsSync12(sdk)) return null;
|
|
11627
11657
|
const root = realpathSync2(dir2);
|
|
11628
|
-
return realpathSync2(sdk).startsWith(root +
|
|
11658
|
+
return realpathSync2(sdk).startsWith(root + sep2) ? root : null;
|
|
11629
11659
|
}
|
|
11630
11660
|
function companionSource(input) {
|
|
11631
11661
|
if (input.configured) {
|
|
@@ -12659,8 +12689,8 @@ import {
|
|
|
12659
12689
|
} from "fs";
|
|
12660
12690
|
import { createRequire as createRequire2 } from "module";
|
|
12661
12691
|
import { isIP } from "net";
|
|
12662
|
-
import { homedir as
|
|
12663
|
-
import { dirname as dirname8, join as join19, sep as
|
|
12692
|
+
import { homedir as homedir4, networkInterfaces, tmpdir as tmpdir4, userInfo as userInfo2 } from "os";
|
|
12693
|
+
import { dirname as dirname8, join as join19, sep as sep3 } from "path";
|
|
12664
12694
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
12665
12695
|
import { SandboxManager } from "@anthropic-ai/sandbox-runtime";
|
|
12666
12696
|
function accountHome() {
|
|
@@ -12757,13 +12787,13 @@ function companionStoreWatch(log) {
|
|
|
12757
12787
|
return new CompanionStoreWatch({
|
|
12758
12788
|
log,
|
|
12759
12789
|
roots: () => {
|
|
12760
|
-
const home =
|
|
12790
|
+
const home = homedir4();
|
|
12761
12791
|
return storeWalkRoots([.../* @__PURE__ */ new Set([home, accountHome() ?? home])], cabaneDir());
|
|
12762
12792
|
}
|
|
12763
12793
|
});
|
|
12764
12794
|
}
|
|
12765
12795
|
function isAtOrUnder(path, dir2) {
|
|
12766
|
-
return path === dir2 || path.startsWith(dir2 +
|
|
12796
|
+
return path === dir2 || path.startsWith(dir2 + sep3);
|
|
12767
12797
|
}
|
|
12768
12798
|
function osSandboxUsable(log) {
|
|
12769
12799
|
if (!SandboxManager.isSupportedPlatform()) {
|
|
@@ -13612,6 +13642,12 @@ var CompanionSupervisor = class {
|
|
|
13612
13642
|
removeAgent(wr, agentId) {
|
|
13613
13643
|
const runner = wr.agents.get(agentId);
|
|
13614
13644
|
if (!runner) return;
|
|
13645
|
+
if (runner.dispatcher.cancelAll()) {
|
|
13646
|
+
this.log.info(
|
|
13647
|
+
{ workspaceId: wr.workspaceId, agentId },
|
|
13648
|
+
`Stopped ${runner.displayName}'s running turns (no longer on this device)`
|
|
13649
|
+
);
|
|
13650
|
+
}
|
|
13615
13651
|
runner.cancelDrain();
|
|
13616
13652
|
wr.agents.delete(agentId);
|
|
13617
13653
|
this.hub.removeAgent(wr.workspaceId, agentId);
|
|
@@ -13652,7 +13688,8 @@ var CompanionSupervisor = class {
|
|
|
13652
13688
|
intended: isClaudeCodeConnected(this.config),
|
|
13653
13689
|
bundled: this.bundledStatus("claude-code")
|
|
13654
13690
|
},
|
|
13655
|
-
codex: { intended: isCodexEnabled(this.config), bundled: this.bundledStatus("codex") }
|
|
13691
|
+
codex: { intended: isCodexEnabled(this.config), bundled: this.bundledStatus("codex") },
|
|
13692
|
+
install: companionInstall()
|
|
13656
13693
|
});
|
|
13657
13694
|
}
|
|
13658
13695
|
// A missing binary is reported ONCE, and again only when the answer CHANGES,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cabane/companion",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.155",
|
|
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",
|