@cabane/companion 0.6.237 → 0.6.238
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 +23 -245
- package/dist/launch.js +3 -4
- package/dist/postinstall.js +3 -4
- package/package.json +1 -3
- package/dist/pairing-config.js +0 -591
- package/dist/runtime.js +0 -9663
package/dist/cli.js
CHANGED
|
@@ -724,7 +724,7 @@ var init_config = __esm({
|
|
|
724
724
|
// the rest of the config; `pair` always writes one.
|
|
725
725
|
deviceToken: z2.string().optional(),
|
|
726
726
|
// Identity hints, learned from the device flow and refreshed on the first
|
|
727
|
-
// assignments pull. Cosmetic — used for `status
|
|
727
|
+
// assignments pull. Cosmetic — used for `status` display only.
|
|
728
728
|
deviceId: z2.string().optional(),
|
|
729
729
|
deviceLabel: z2.string().optional(),
|
|
730
730
|
// Optional per-agent machine-local overrides (cwd / prepareHook), keyed by
|
|
@@ -736,9 +736,8 @@ var init_config = __esm({
|
|
|
736
736
|
// silent roster: an agent nobody listed gets no hook and no error, and starts
|
|
737
737
|
// in the operator's `$HOME`.
|
|
738
738
|
prepareHook: prepareHookSchema.optional(),
|
|
739
|
-
//
|
|
740
|
-
//
|
|
741
|
-
// startup. `logLevel` is pino's level, live-editable.
|
|
739
|
+
// Nothing reads either dashboard setting any more; both stay parseable so an
|
|
740
|
+
// older config file still loads. `logLevel` is pino's level, live-editable.
|
|
742
741
|
dashboardPort: z2.number().int().min(1).max(65535).optional(),
|
|
743
742
|
autoOpen: z2.boolean().optional(),
|
|
744
743
|
logLevel: z2.enum(["warn", "info", "debug"]).optional(),
|
|
@@ -7434,10 +7433,6 @@ var init_turn_committer = __esm({
|
|
|
7434
7433
|
get lastMessageSeq() {
|
|
7435
7434
|
return this.pump.lastMessageSeq;
|
|
7436
7435
|
}
|
|
7437
|
-
// The turn's final reply text, or null if none landed.
|
|
7438
|
-
get replyBody() {
|
|
7439
|
-
return this.pump.replyBody;
|
|
7440
|
-
}
|
|
7441
7436
|
get finalSource() {
|
|
7442
7437
|
return this.pump.finalSource;
|
|
7443
7438
|
}
|
|
@@ -7815,7 +7810,6 @@ var init_turn_execution = __esm({
|
|
|
7815
7810
|
);
|
|
7816
7811
|
}
|
|
7817
7812
|
const durationMs = Date.now() - startedAt;
|
|
7818
|
-
this.supervisor.notifyEnd({ id: payload.messageId, ok: false, durationMs, reason });
|
|
7819
7813
|
return { ok: false, durationMs, reason, runtime: this.turnContext?.runtime };
|
|
7820
7814
|
}
|
|
7821
7815
|
// The admitted turn holds the conversation's lease, so the clear must NAME the
|
|
@@ -7854,7 +7848,6 @@ var init_turn_execution = __esm({
|
|
|
7854
7848
|
}
|
|
7855
7849
|
}
|
|
7856
7850
|
const durationMs = Date.now() - startedAt;
|
|
7857
|
-
this.supervisor.notifyEnd({ id: payload.messageId, ok: false, durationMs, reason });
|
|
7858
7851
|
return { ok: false, durationMs, reason, runtime: this.turnContext?.runtime };
|
|
7859
7852
|
}
|
|
7860
7853
|
async fetchContext() {
|
|
@@ -7963,11 +7956,7 @@ var init_turn_execution = __esm({
|
|
|
7963
7956
|
turnLog.debug({ role: message2.role }, "dispatcher: trigger role not dispatchable \u2014 skipping");
|
|
7964
7957
|
throw this.concluded("unexpected_role", UNEXPECTED_ROLE_REASON);
|
|
7965
7958
|
}
|
|
7966
|
-
this.supervisor.notifyStart({
|
|
7967
|
-
id: this.dispatchId,
|
|
7968
|
-
conversationId: payload.conversationId,
|
|
7969
|
-
message: message2.body
|
|
7970
|
-
});
|
|
7959
|
+
this.supervisor.notifyStart({ id: this.dispatchId, conversationId: payload.conversationId });
|
|
7971
7960
|
}
|
|
7972
7961
|
async resolveSecrets() {
|
|
7973
7962
|
const { turnLog } = this;
|
|
@@ -8736,7 +8725,6 @@ var init_turn_execution = __esm({
|
|
|
8736
8725
|
const o = this.outcome;
|
|
8737
8726
|
const { startedAt, turnLog } = this;
|
|
8738
8727
|
const durationMs = Date.now() - startedAt;
|
|
8739
|
-
const finalReplyBody = this.committer.replyBody;
|
|
8740
8728
|
if (this.transcript) {
|
|
8741
8729
|
this.transcript.close({
|
|
8742
8730
|
ok: o.okResult,
|
|
@@ -8749,21 +8737,9 @@ var init_turn_execution = __esm({
|
|
|
8749
8737
|
}
|
|
8750
8738
|
if (o.okResult) {
|
|
8751
8739
|
turnLog.debug({ durationMs }, "dispatcher: turn end (ok)");
|
|
8752
|
-
this.supervisor.notifyEnd({
|
|
8753
|
-
id: this.dispatchId,
|
|
8754
|
-
ok: true,
|
|
8755
|
-
durationMs,
|
|
8756
|
-
...finalReplyBody ? { reply: finalReplyBody.trim() } : {}
|
|
8757
|
-
});
|
|
8758
8740
|
return { ok: true, durationMs };
|
|
8759
8741
|
}
|
|
8760
8742
|
turnLog.debug({ durationMs, reason: o.resultReason }, "dispatcher: turn end (not ok)");
|
|
8761
|
-
this.supervisor.notifyEnd({
|
|
8762
|
-
id: this.dispatchId,
|
|
8763
|
-
ok: false,
|
|
8764
|
-
durationMs,
|
|
8765
|
-
...o.resultReason ? { reason: o.resultReason } : {}
|
|
8766
|
-
});
|
|
8767
8743
|
return {
|
|
8768
8744
|
ok: false,
|
|
8769
8745
|
durationMs,
|
|
@@ -9269,8 +9245,7 @@ async function runTurn(env, deps) {
|
|
|
9269
9245
|
emit({ cabaneRunner: "session_write_notice" });
|
|
9270
9246
|
return true;
|
|
9271
9247
|
},
|
|
9272
|
-
notifyStart: (info) => emit({ cabaneRunner: "start", ...info })
|
|
9273
|
-
notifyEnd: (info) => emit({ cabaneRunner: "end", ...info })
|
|
9248
|
+
notifyStart: (info) => emit({ cabaneRunner: "start", ...info })
|
|
9274
9249
|
};
|
|
9275
9250
|
let outbox;
|
|
9276
9251
|
const opts = runnerTurnOptions(input, log2, emit, {
|
|
@@ -10322,7 +10297,6 @@ init_config();
|
|
|
10322
10297
|
init_pairing();
|
|
10323
10298
|
init_errors();
|
|
10324
10299
|
init_install_kind();
|
|
10325
|
-
init_errors();
|
|
10326
10300
|
function resolvePairBaseUrl(server) {
|
|
10327
10301
|
const raw = (server ?? process.env.CABANE_BASE_URL ?? "").trim();
|
|
10328
10302
|
if (!raw) throw new NoPairAddressError();
|
|
@@ -10371,7 +10345,6 @@ function isDevicePaired() {
|
|
|
10371
10345
|
init_config();
|
|
10372
10346
|
init_cabane_command();
|
|
10373
10347
|
import { randomUUID as randomUUID7 } from "crypto";
|
|
10374
|
-
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
10375
10348
|
|
|
10376
10349
|
// src/prereqs.ts
|
|
10377
10350
|
init_config();
|
|
@@ -10388,71 +10361,37 @@ function warnAboutHarnessReadiness(cfg, deps = {}) {
|
|
|
10388
10361
|
}
|
|
10389
10362
|
|
|
10390
10363
|
// src/state.ts
|
|
10391
|
-
import { EventEmitter } from "events";
|
|
10392
|
-
function dispatchToWire(r) {
|
|
10393
|
-
return {
|
|
10394
|
-
id: r.id,
|
|
10395
|
-
timestamp: r.timestamp,
|
|
10396
|
-
workspace_slug: r.workspaceSlug,
|
|
10397
|
-
...r.agentUsername ? { agent_username: r.agentUsername } : {},
|
|
10398
|
-
message: r.message,
|
|
10399
|
-
status: r.status,
|
|
10400
|
-
...r.durationMs !== void 0 ? { duration_ms: r.durationMs } : {},
|
|
10401
|
-
...r.error ? { error: r.error } : {},
|
|
10402
|
-
...r.reply ? { reply: r.reply } : {}
|
|
10403
|
-
};
|
|
10404
|
-
}
|
|
10405
|
-
var MAX_DISPATCHES = 50;
|
|
10406
10364
|
function today() {
|
|
10407
10365
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
10408
10366
|
}
|
|
10409
10367
|
var CompanionStateHub = class {
|
|
10410
10368
|
constructor(opts) {
|
|
10411
10369
|
this.opts = opts;
|
|
10412
|
-
this.emitter.setMaxListeners(0);
|
|
10413
10370
|
}
|
|
10414
10371
|
opts;
|
|
10415
|
-
emitter = new EventEmitter();
|
|
10416
10372
|
workspaces = /* @__PURE__ */ new Map();
|
|
10417
|
-
dispatches = [];
|
|
10418
|
-
dashboardUrl = null;
|
|
10419
10373
|
deviceId = null;
|
|
10420
10374
|
deviceLabel = null;
|
|
10421
10375
|
deviceError = null;
|
|
10422
10376
|
// The latest harness snapshot the supervisor probed, or null before the
|
|
10423
10377
|
// first probe (see CompanionStatusJson.harnesses).
|
|
10424
10378
|
harnesses = null;
|
|
10425
|
-
// ---- subscription (SSE) ----
|
|
10426
|
-
on(listener) {
|
|
10427
|
-
this.emitter.on("event", listener);
|
|
10428
|
-
return () => this.emitter.off("event", listener);
|
|
10429
|
-
}
|
|
10430
|
-
emit(type, data) {
|
|
10431
|
-
this.emitter.emit("event", { type, data });
|
|
10432
|
-
}
|
|
10433
10379
|
// ---- device ----
|
|
10434
10380
|
setDevice(info) {
|
|
10435
10381
|
if (info.deviceId !== void 0) this.deviceId = info.deviceId;
|
|
10436
10382
|
if (info.deviceLabel !== void 0) this.deviceLabel = info.deviceLabel;
|
|
10437
|
-
this.emitStatus();
|
|
10438
10383
|
}
|
|
10439
10384
|
setDeviceError(message2) {
|
|
10440
|
-
if (this.deviceError === message2) return;
|
|
10441
10385
|
this.deviceError = message2;
|
|
10442
|
-
this.emitStatus();
|
|
10443
10386
|
}
|
|
10444
10387
|
clearDeviceError() {
|
|
10445
|
-
if (this.deviceError === null) return;
|
|
10446
10388
|
this.deviceError = null;
|
|
10447
|
-
this.emitStatus();
|
|
10448
10389
|
}
|
|
10449
10390
|
// ---- harnesses ----
|
|
10450
|
-
// Replace the harness snapshot
|
|
10451
|
-
// the Companion's Harnesses surface live). The supervisor calls this on each
|
|
10391
|
+
// Replace the harness snapshot. The supervisor calls this on each
|
|
10452
10392
|
// heartbeat-cadence probe and on an on-demand recheck.
|
|
10453
10393
|
setHarnesses(harnesses) {
|
|
10454
10394
|
this.harnesses = harnesses;
|
|
10455
|
-
this.emitStatus();
|
|
10456
10395
|
}
|
|
10457
10396
|
// ---- workspace lifecycle ----
|
|
10458
10397
|
registerWorkspace(ws) {
|
|
@@ -10473,29 +10412,21 @@ var CompanionStateHub = class {
|
|
|
10473
10412
|
countDate: today(),
|
|
10474
10413
|
agents: /* @__PURE__ */ new Map()
|
|
10475
10414
|
});
|
|
10476
|
-
this.emitStatus();
|
|
10477
10415
|
}
|
|
10478
10416
|
removeWorkspace(workspaceId) {
|
|
10479
|
-
const ws = this.workspaces.get(workspaceId);
|
|
10480
|
-
if (!ws) return;
|
|
10481
10417
|
this.workspaces.delete(workspaceId);
|
|
10482
|
-
this.emit("workspace:disconnected", { slug: ws.slug });
|
|
10483
|
-
this.emitStatus();
|
|
10484
10418
|
}
|
|
10485
10419
|
setConnected(workspaceId, connected) {
|
|
10486
10420
|
const ws = this.workspaces.get(workspaceId);
|
|
10487
10421
|
if (!ws || ws.connected === connected) return;
|
|
10488
10422
|
ws.connected = connected;
|
|
10489
10423
|
if (connected) ws.authFailed = false;
|
|
10490
|
-
this.emitStatus();
|
|
10491
10424
|
}
|
|
10492
10425
|
setAuthFailed(workspaceId) {
|
|
10493
10426
|
const ws = this.workspaces.get(workspaceId);
|
|
10494
10427
|
if (!ws) return;
|
|
10495
|
-
if (ws.authFailed && !ws.connected) return;
|
|
10496
10428
|
ws.authFailed = true;
|
|
10497
10429
|
ws.connected = false;
|
|
10498
|
-
this.emitStatus();
|
|
10499
10430
|
}
|
|
10500
10431
|
recordEvent(workspaceId) {
|
|
10501
10432
|
const ws = this.workspaces.get(workspaceId);
|
|
@@ -10508,22 +10439,15 @@ var CompanionStateHub = class {
|
|
|
10508
10439
|
const ws = this.workspaces.get(workspaceId);
|
|
10509
10440
|
if (!ws) return;
|
|
10510
10441
|
ws.agents.set(agent.agentId, agent);
|
|
10511
|
-
this.emitStatus();
|
|
10512
10442
|
}
|
|
10513
10443
|
removeAgent(workspaceId, agentId) {
|
|
10514
|
-
|
|
10515
|
-
if (!ws) return;
|
|
10516
|
-
if (ws.agents.delete(agentId)) this.emitStatus();
|
|
10444
|
+
this.workspaces.get(workspaceId)?.agents.delete(agentId);
|
|
10517
10445
|
}
|
|
10518
|
-
// ---- dispatch
|
|
10519
|
-
// A DispatchObserver bound to one
|
|
10520
|
-
//
|
|
10521
|
-
observerFor(workspaceId
|
|
10522
|
-
|
|
10523
|
-
return {
|
|
10524
|
-
onStart: (info) => this.dispatchStarted(workspaceId, slug, username(), info),
|
|
10525
|
-
onEnd: (info) => this.dispatchEnded(slug, username(), info)
|
|
10526
|
-
};
|
|
10446
|
+
// ---- dispatch count ----
|
|
10447
|
+
// A DispatchObserver bound to one workspace, handed to each of its agents'
|
|
10448
|
+
// Dispatchers by the supervisor: a turn counts toward the day when it starts.
|
|
10449
|
+
observerFor(workspaceId) {
|
|
10450
|
+
return { onStart: () => this.bumpCount(workspaceId) };
|
|
10527
10451
|
}
|
|
10528
10452
|
bumpCount(workspaceId) {
|
|
10529
10453
|
const ws = this.workspaces.get(workspaceId);
|
|
@@ -10535,52 +10459,6 @@ var CompanionStateHub = class {
|
|
|
10535
10459
|
}
|
|
10536
10460
|
ws.dispatchCountToday += 1;
|
|
10537
10461
|
}
|
|
10538
|
-
dispatchStarted(workspaceId, slug, agentUsername, info) {
|
|
10539
|
-
this.bumpCount(workspaceId);
|
|
10540
|
-
const record = {
|
|
10541
|
-
id: info.id,
|
|
10542
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
10543
|
-
workspaceSlug: slug,
|
|
10544
|
-
...agentUsername ? { agentUsername } : {},
|
|
10545
|
-
message: info.message,
|
|
10546
|
-
status: "running"
|
|
10547
|
-
};
|
|
10548
|
-
this.upsertDispatch(record);
|
|
10549
|
-
this.emit("dispatch:started", dispatchToWire(record));
|
|
10550
|
-
this.emitStatus();
|
|
10551
|
-
}
|
|
10552
|
-
dispatchEnded(slug, agentUsername, info) {
|
|
10553
|
-
const existing = this.dispatches.find((d) => d.id === info.id);
|
|
10554
|
-
const record = {
|
|
10555
|
-
id: info.id,
|
|
10556
|
-
timestamp: existing?.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
10557
|
-
workspaceSlug: existing?.workspaceSlug ?? slug,
|
|
10558
|
-
...existing?.agentUsername ?? agentUsername ? { agentUsername: existing?.agentUsername ?? agentUsername } : {},
|
|
10559
|
-
message: existing?.message ?? "",
|
|
10560
|
-
status: info.ok ? "replied" : "error",
|
|
10561
|
-
durationMs: info.durationMs,
|
|
10562
|
-
...info.reason ? { error: info.reason } : {},
|
|
10563
|
-
...info.reply ? { reply: info.reply } : {}
|
|
10564
|
-
};
|
|
10565
|
-
this.upsertDispatch(record);
|
|
10566
|
-
this.emit(info.ok ? "dispatch:completed" : "dispatch:error", dispatchToWire(record));
|
|
10567
|
-
}
|
|
10568
|
-
upsertDispatch(record) {
|
|
10569
|
-
const idx = this.dispatches.findIndex((d) => d.id === record.id);
|
|
10570
|
-
if (idx >= 0) {
|
|
10571
|
-
this.dispatches[idx] = record;
|
|
10572
|
-
return;
|
|
10573
|
-
}
|
|
10574
|
-
this.dispatches.unshift(record);
|
|
10575
|
-
if (this.dispatches.length > MAX_DISPATCHES) this.dispatches.length = MAX_DISPATCHES;
|
|
10576
|
-
}
|
|
10577
|
-
// ---- snapshots for the HTTP routes ----
|
|
10578
|
-
setDashboardUrl(url) {
|
|
10579
|
-
this.dashboardUrl = url;
|
|
10580
|
-
}
|
|
10581
|
-
recentDispatches(limit = 20) {
|
|
10582
|
-
return this.dispatches.slice(0, Math.max(0, limit));
|
|
10583
|
-
}
|
|
10584
10462
|
statusJson() {
|
|
10585
10463
|
const list = [...this.workspaces.values()].sort((a, b) => a.name.localeCompare(b.name));
|
|
10586
10464
|
const lastOverall = list.reduce((acc, ws) => {
|
|
@@ -10610,15 +10488,11 @@ var CompanionStateHub = class {
|
|
|
10610
10488
|
}))
|
|
10611
10489
|
})),
|
|
10612
10490
|
last_event_at_overall: lastOverall,
|
|
10613
|
-
dashboard_url: this.dashboardUrl,
|
|
10614
10491
|
companion_version: this.opts.companionVersion,
|
|
10615
10492
|
instance_id: this.opts.instanceId ?? null,
|
|
10616
10493
|
harnesses: this.harnesses
|
|
10617
10494
|
};
|
|
10618
10495
|
}
|
|
10619
|
-
emitStatus() {
|
|
10620
|
-
this.emit("status:changed", this.statusJson());
|
|
10621
|
-
}
|
|
10622
10496
|
};
|
|
10623
10497
|
|
|
10624
10498
|
// src/supervisor.ts
|
|
@@ -11387,7 +11261,6 @@ async function runTurnInRunner(opts, launch, duties, payload, handleOpts) {
|
|
|
11387
11261
|
duties.releaseAbort(turnId, controller);
|
|
11388
11262
|
const durationMs2 = Date.now() - startedAt;
|
|
11389
11263
|
await settleUnstarted(opts, payload, turnId, minted.errorReason, log2);
|
|
11390
|
-
duties.notifyEnd({ id: payload.messageId, ok: false, durationMs: durationMs2, reason: minted.reason });
|
|
11391
11264
|
return { ok: false, durationMs: durationMs2, reason: minted.reason };
|
|
11392
11265
|
}
|
|
11393
11266
|
let result;
|
|
@@ -11418,7 +11291,6 @@ async function runTurnInRunner(opts, launch, duties, payload, handleOpts) {
|
|
|
11418
11291
|
reason: "provider_failed"
|
|
11419
11292
|
});
|
|
11420
11293
|
const durationMs2 = Date.now() - startedAt;
|
|
11421
|
-
duties.notifyEnd({ id: payload.messageId, ok: false, durationMs: durationMs2, reason: reason2 });
|
|
11422
11294
|
return { ok: false, durationMs: durationMs2, reason: reason2 };
|
|
11423
11295
|
}
|
|
11424
11296
|
try {
|
|
@@ -11482,17 +11354,8 @@ async function runTurnInRunner(opts, launch, duties, payload, handleOpts) {
|
|
|
11482
11354
|
}
|
|
11483
11355
|
return;
|
|
11484
11356
|
case "start":
|
|
11485
|
-
duties.notifyStart({
|
|
11486
|
-
id: event.id,
|
|
11487
|
-
conversationId: event.conversationId,
|
|
11488
|
-
message: event.message
|
|
11489
|
-
});
|
|
11490
|
-
return;
|
|
11491
|
-
case "end": {
|
|
11492
|
-
const { cabaneRunner: _kind, ...info } = event;
|
|
11493
|
-
duties.notifyEnd(info);
|
|
11357
|
+
duties.notifyStart({ id: event.id, conversationId: event.conversationId });
|
|
11494
11358
|
return;
|
|
11495
|
-
}
|
|
11496
11359
|
case "session_write_notice":
|
|
11497
11360
|
duties.markSessionWriteNotice();
|
|
11498
11361
|
return;
|
|
@@ -11596,7 +11459,6 @@ async function runTurnInRunner(opts, launch, duties, payload, handleOpts) {
|
|
|
11596
11459
|
if (thrown !== void 0) throw new Error(thrown);
|
|
11597
11460
|
if (stopped) log2.info({ turnId, code }, "runner: stopped before it could report");
|
|
11598
11461
|
else log2.warn({ turnId, code }, "runner: exited without reporting a result");
|
|
11599
|
-
duties.notifyEnd({ id: payload.messageId, ok: false, durationMs, reason });
|
|
11600
11462
|
return { ok: false, durationMs, reason };
|
|
11601
11463
|
}
|
|
11602
11464
|
|
|
@@ -11623,12 +11485,6 @@ var Dispatcher = class {
|
|
|
11623
11485
|
} catch {
|
|
11624
11486
|
}
|
|
11625
11487
|
}
|
|
11626
|
-
notifyEnd(info) {
|
|
11627
|
-
try {
|
|
11628
|
-
this.opts.observer?.onEnd(info);
|
|
11629
|
-
} catch {
|
|
11630
|
-
}
|
|
11631
|
-
}
|
|
11632
11488
|
// The supervisor supplies a stable turnId on both fresh and resumed dispatch.
|
|
11633
11489
|
// resumed is separate: only replay seeds sequence/speech recovery from the
|
|
11634
11490
|
// prior span. A direct caller omitting turnId gets a fresh id.
|
|
@@ -11656,8 +11512,7 @@ var Dispatcher = class {
|
|
|
11656
11512
|
markSessionWriteNotice: () => {
|
|
11657
11513
|
this.sessionWriteNotified.add(key);
|
|
11658
11514
|
},
|
|
11659
|
-
notifyStart: (info) => this.notifyStart(info)
|
|
11660
|
-
notifyEnd: (info) => this.notifyEnd(info)
|
|
11515
|
+
notifyStart: (info) => this.notifyStart(info)
|
|
11661
11516
|
},
|
|
11662
11517
|
payload,
|
|
11663
11518
|
{
|
|
@@ -12756,7 +12611,6 @@ var CompanionSupervisor = class {
|
|
|
12756
12611
|
runHarnessCheck;
|
|
12757
12612
|
probeOpencode;
|
|
12758
12613
|
exitFn;
|
|
12759
|
-
reexecFn;
|
|
12760
12614
|
dispatcherFactory;
|
|
12761
12615
|
runnerCommand;
|
|
12762
12616
|
runnerEnv;
|
|
@@ -12767,8 +12621,8 @@ var CompanionSupervisor = class {
|
|
|
12767
12621
|
host = hostReport();
|
|
12768
12622
|
deviceApi = null;
|
|
12769
12623
|
deviceSub = null;
|
|
12770
|
-
// Whether the device stream is open, which is what every workspace's link
|
|
12771
|
-
// the
|
|
12624
|
+
// Whether the device stream is open, which is what every workspace's link in
|
|
12625
|
+
// the status snapshot reports.
|
|
12772
12626
|
deviceConnected = false;
|
|
12773
12627
|
// Set when the device stream ended on a 403: the device was deactivated, not
|
|
12774
12628
|
// unpaired. The next accepted heartbeat proves it was reactivated, and
|
|
@@ -12829,7 +12683,6 @@ var CompanionSupervisor = class {
|
|
|
12829
12683
|
this.probeOpencode = opts.probeOpencode;
|
|
12830
12684
|
this.harnessVersions = opts.harnessVersions ?? emptyHarnessVersions();
|
|
12831
12685
|
this.exitFn = opts.exit ?? ((code) => process.exit(code));
|
|
12832
|
-
this.reexecFn = opts.reexec ?? defaultReexec;
|
|
12833
12686
|
this.restartForUpdate = opts.restartForUpdate ?? (async () => {
|
|
12834
12687
|
await this.shutdown();
|
|
12835
12688
|
this.exitFn(0);
|
|
@@ -13463,7 +13316,7 @@ var CompanionSupervisor = class {
|
|
|
13463
13316
|
locks: this.runnerLocks,
|
|
13464
13317
|
gzipBodies: this.gzipBodies
|
|
13465
13318
|
},
|
|
13466
|
-
observer: this.hub.observerFor(ctx2.workspaceId
|
|
13319
|
+
observer: this.hub.observerFor(ctx2.workspaceId),
|
|
13467
13320
|
aborts: ctx2.aborts
|
|
13468
13321
|
});
|
|
13469
13322
|
}
|
|
@@ -13917,36 +13770,9 @@ var CompanionSupervisor = class {
|
|
|
13917
13770
|
};
|
|
13918
13771
|
return { kick, cancel: cancel2 };
|
|
13919
13772
|
}
|
|
13920
|
-
// ---- dashboard-facing operations ----
|
|
13921
|
-
// Re-read `~/.cabane/config.json` (the operator may have edited the `agents`
|
|
13922
|
-
// overrides or dashboard prefs), apply the log level live, and re-pull
|
|
13923
|
-
// assignments so any structural change is reflected. A device-token change
|
|
13924
|
-
// means re-pairing, which `pair` + a restart handle.
|
|
13925
|
-
reloadConfig() {
|
|
13926
|
-
const next = loadConfig();
|
|
13927
|
-
if (!next) return;
|
|
13928
|
-
this.config = next;
|
|
13929
|
-
configureLogger(this.log, next);
|
|
13930
|
-
this.rebuildDispatchers();
|
|
13931
|
-
void this.refreshAssignments();
|
|
13932
|
-
}
|
|
13933
|
-
// The dashboard "refresh assignments" control — an immediate pull.
|
|
13934
|
-
refresh() {
|
|
13935
|
-
void this.refreshAssignments();
|
|
13936
|
-
}
|
|
13937
|
-
applySettings(patch) {
|
|
13938
|
-
const next = {
|
|
13939
|
-
...this.config,
|
|
13940
|
-
...patch.logLevel ? { logLevel: patch.logLevel } : {},
|
|
13941
|
-
...patch.autoOpen !== void 0 ? { autoOpen: patch.autoOpen } : {}
|
|
13942
|
-
};
|
|
13943
|
-
this.config = next;
|
|
13944
|
-
saveConfig(next);
|
|
13945
|
-
configureLogger(this.log, next);
|
|
13946
|
-
}
|
|
13947
13773
|
// ---- harnesses ----
|
|
13948
13774
|
// Look at every agent, in this process: the one whose environment turns run
|
|
13949
|
-
// in. Cached for the heartbeat and the
|
|
13775
|
+
// in. Cached for the heartbeat and the status snapshot; coalesced, so a re-detect
|
|
13950
13776
|
// during the timer's own run waits for that one. Never throws.
|
|
13951
13777
|
async detect() {
|
|
13952
13778
|
if (this.detecting) return this.detecting;
|
|
@@ -13974,8 +13800,8 @@ var CompanionSupervisor = class {
|
|
|
13974
13800
|
});
|
|
13975
13801
|
return this.detecting;
|
|
13976
13802
|
}
|
|
13977
|
-
// A re-detect asked for over the control socket (`setup`, `connect`)
|
|
13978
|
-
//
|
|
13803
|
+
// A re-detect asked for over the control socket (`setup`, `connect`): read
|
|
13804
|
+
// the config file again first — this process owns it, so an
|
|
13979
13805
|
// edit made on disk (the allowlist, the OpenCode address) is adopted here
|
|
13980
13806
|
// rather than overwritten by its next save — then detect now, and beat at
|
|
13981
13807
|
// once so Cabane shows it promptly.
|
|
@@ -14111,9 +13937,6 @@ var CompanionSupervisor = class {
|
|
|
14111
13937
|
await this.shutdown();
|
|
14112
13938
|
this.exitFn(0);
|
|
14113
13939
|
}
|
|
14114
|
-
requestRestart() {
|
|
14115
|
-
this.reexecFn();
|
|
14116
|
-
}
|
|
14117
13940
|
};
|
|
14118
13941
|
async function waitForBoundedHeartbeat(heartbeat) {
|
|
14119
13942
|
let timer = null;
|
|
@@ -14127,21 +13950,6 @@ async function waitForBoundedHeartbeat(heartbeat) {
|
|
|
14127
13950
|
if (timer) clearTimeout(timer);
|
|
14128
13951
|
}
|
|
14129
13952
|
}
|
|
14130
|
-
function defaultReexec() {
|
|
14131
|
-
clearRuntimeState();
|
|
14132
|
-
void import("child_process").then(({ spawn: spawn8 }) => {
|
|
14133
|
-
try {
|
|
14134
|
-
const child = spawn8(process.execPath, process.argv.slice(1), {
|
|
14135
|
-
stdio: "inherit",
|
|
14136
|
-
detached: false
|
|
14137
|
-
});
|
|
14138
|
-
child.on("spawn", () => process.exit(0));
|
|
14139
|
-
child.on("error", () => {
|
|
14140
|
-
});
|
|
14141
|
-
} catch {
|
|
14142
|
-
}
|
|
14143
|
-
});
|
|
14144
|
-
}
|
|
14145
13953
|
|
|
14146
13954
|
// src/safety.ts
|
|
14147
13955
|
var RECOVERABLE_CODES = /* @__PURE__ */ new Set([
|
|
@@ -14313,15 +14121,6 @@ function strayCompanionLines(strays, retry) {
|
|
|
14313
14121
|
}
|
|
14314
14122
|
|
|
14315
14123
|
// src/runtime.ts
|
|
14316
|
-
init_errors();
|
|
14317
|
-
function embeddedRunner(host) {
|
|
14318
|
-
if (!host.electron) return null;
|
|
14319
|
-
const cli = fileURLToPath5(new URL("./cli.js", host.moduleUrl));
|
|
14320
|
-
return {
|
|
14321
|
-
runnerCommand: [host.execPath, cli, "run-turn"],
|
|
14322
|
-
runnerEnv: { ...host.env, ELECTRON_RUN_AS_NODE: "1" }
|
|
14323
|
-
};
|
|
14324
|
-
}
|
|
14325
14124
|
async function createCompanionRuntime(opts = {}) {
|
|
14326
14125
|
const log2 = getLogger();
|
|
14327
14126
|
installProcessSafetyNet(log2);
|
|
@@ -14361,7 +14160,7 @@ async function createCompanionRuntime(opts = {}) {
|
|
|
14361
14160
|
const clearRuntimeOnExit = () => clearRuntimeStateIfOurs(instanceId);
|
|
14362
14161
|
process.on("exit", clearRuntimeOnExit);
|
|
14363
14162
|
const hub = new CompanionStateHub({
|
|
14364
|
-
//
|
|
14163
|
+
// `status` names the Cabane it is paired with.
|
|
14365
14164
|
baseUrl: cfg.baseUrl,
|
|
14366
14165
|
companionVersion: COMPANION_VERSION,
|
|
14367
14166
|
// Surfaced on `/api/status` so `stop`/`status` can confirm the
|
|
@@ -14372,7 +14171,6 @@ async function createCompanionRuntime(opts = {}) {
|
|
|
14372
14171
|
};
|
|
14373
14172
|
let supervisor;
|
|
14374
14173
|
let control = null;
|
|
14375
|
-
let dashboard = null;
|
|
14376
14174
|
let stopped = false;
|
|
14377
14175
|
const stop2 = async () => {
|
|
14378
14176
|
if (stopped) return;
|
|
@@ -14381,8 +14179,7 @@ async function createCompanionRuntime(opts = {}) {
|
|
|
14381
14179
|
process.removeListener("exit", clearRuntimeOnExit);
|
|
14382
14180
|
await Promise.allSettled([
|
|
14383
14181
|
...supervisor ? [supervisor.shutdown()] : [],
|
|
14384
|
-
...control ? [control.close()] : []
|
|
14385
|
-
...dashboard ? [dashboard.close()] : []
|
|
14182
|
+
...control ? [control.close()] : []
|
|
14386
14183
|
]);
|
|
14387
14184
|
};
|
|
14388
14185
|
try {
|
|
@@ -14391,12 +14188,6 @@ async function createCompanionRuntime(opts = {}) {
|
|
|
14391
14188
|
log: log2,
|
|
14392
14189
|
hub,
|
|
14393
14190
|
...opts.checkHarness ? { checkHarness: opts.checkHarness } : {},
|
|
14394
|
-
...embeddedRunner({
|
|
14395
|
-
electron: Boolean(process.versions.electron),
|
|
14396
|
-
execPath: process.execPath,
|
|
14397
|
-
moduleUrl: import.meta.url,
|
|
14398
|
-
env: process.env
|
|
14399
|
-
}) ?? {},
|
|
14400
14191
|
restartForUpdate: () => restartForUpdate()
|
|
14401
14192
|
});
|
|
14402
14193
|
const active2 = supervisor;
|
|
@@ -14411,21 +14202,10 @@ async function createCompanionRuntime(opts = {}) {
|
|
|
14411
14202
|
update: (auto) => active2.update(auto),
|
|
14412
14203
|
stop: () => void stop2().then(() => active2.requestStop())
|
|
14413
14204
|
});
|
|
14414
|
-
if (opts.startDashboard) {
|
|
14415
|
-
const preferredPort = cfg.dashboardPort;
|
|
14416
|
-
dashboard = await opts.startDashboard({
|
|
14417
|
-
supervisor,
|
|
14418
|
-
hub,
|
|
14419
|
-
logPath: companionLogPath(),
|
|
14420
|
-
...preferredPort !== void 0 ? { port: preferredPort } : {}
|
|
14421
|
-
});
|
|
14422
|
-
hub.setDashboardUrl(dashboard.url);
|
|
14423
|
-
}
|
|
14424
14205
|
if (stopped) throw new Error("The companion was stopped during startup.");
|
|
14425
14206
|
writeRuntimeState({
|
|
14426
14207
|
pid: process.pid,
|
|
14427
14208
|
socket: control.path,
|
|
14428
|
-
...dashboard ? { url: dashboard.url, port: dashboard.port } : {},
|
|
14429
14209
|
startedAt,
|
|
14430
14210
|
// The daemon launcher sets this env on the detached child, so the
|
|
14431
14211
|
// marker records whether this companion is backgrounded (foreground start
|
|
@@ -14440,8 +14220,7 @@ async function createCompanionRuntime(opts = {}) {
|
|
|
14440
14220
|
process.removeListener("exit", clearRuntimeOnExit);
|
|
14441
14221
|
await Promise.allSettled([
|
|
14442
14222
|
...supervisor ? [supervisor.shutdown()] : [],
|
|
14443
|
-
...control ? [control.close()] : []
|
|
14444
|
-
...dashboard ? [dashboard.close()] : []
|
|
14223
|
+
...control ? [control.close()] : []
|
|
14445
14224
|
]);
|
|
14446
14225
|
recordCrash({
|
|
14447
14226
|
reason: err instanceof Error ? err.message : String(err),
|
|
@@ -14465,7 +14244,6 @@ async function createCompanionRuntime(opts = {}) {
|
|
|
14465
14244
|
return {
|
|
14466
14245
|
ok: true,
|
|
14467
14246
|
runtime: {
|
|
14468
|
-
...dashboard ? { url: dashboard.url, port: dashboard.port } : {},
|
|
14469
14247
|
socketPath: control.path,
|
|
14470
14248
|
config: cfg,
|
|
14471
14249
|
stop: stop2,
|
package/dist/launch.js
CHANGED
|
@@ -133,7 +133,7 @@ var companionConfigSchema = z2.object({
|
|
|
133
133
|
// the rest of the config; `pair` always writes one.
|
|
134
134
|
deviceToken: z2.string().optional(),
|
|
135
135
|
// Identity hints, learned from the device flow and refreshed on the first
|
|
136
|
-
// assignments pull. Cosmetic — used for `status
|
|
136
|
+
// assignments pull. Cosmetic — used for `status` display only.
|
|
137
137
|
deviceId: z2.string().optional(),
|
|
138
138
|
deviceLabel: z2.string().optional(),
|
|
139
139
|
// Optional per-agent machine-local overrides (cwd / prepareHook), keyed by
|
|
@@ -145,9 +145,8 @@ var companionConfigSchema = z2.object({
|
|
|
145
145
|
// silent roster: an agent nobody listed gets no hook and no error, and starts
|
|
146
146
|
// in the operator's `$HOME`.
|
|
147
147
|
prepareHook: prepareHookSchema.optional(),
|
|
148
|
-
//
|
|
149
|
-
//
|
|
150
|
-
// startup. `logLevel` is pino's level, live-editable.
|
|
148
|
+
// Nothing reads either dashboard setting any more; both stay parseable so an
|
|
149
|
+
// older config file still loads. `logLevel` is pino's level, live-editable.
|
|
151
150
|
dashboardPort: z2.number().int().min(1).max(65535).optional(),
|
|
152
151
|
autoOpen: z2.boolean().optional(),
|
|
153
152
|
logLevel: z2.enum(["warn", "info", "debug"]).optional(),
|
package/dist/postinstall.js
CHANGED
|
@@ -183,7 +183,7 @@ var companionConfigSchema = z2.object({
|
|
|
183
183
|
// the rest of the config; `pair` always writes one.
|
|
184
184
|
deviceToken: z2.string().optional(),
|
|
185
185
|
// Identity hints, learned from the device flow and refreshed on the first
|
|
186
|
-
// assignments pull. Cosmetic — used for `status
|
|
186
|
+
// assignments pull. Cosmetic — used for `status` display only.
|
|
187
187
|
deviceId: z2.string().optional(),
|
|
188
188
|
deviceLabel: z2.string().optional(),
|
|
189
189
|
// Optional per-agent machine-local overrides (cwd / prepareHook), keyed by
|
|
@@ -195,9 +195,8 @@ var companionConfigSchema = z2.object({
|
|
|
195
195
|
// silent roster: an agent nobody listed gets no hook and no error, and starts
|
|
196
196
|
// in the operator's `$HOME`.
|
|
197
197
|
prepareHook: prepareHookSchema.optional(),
|
|
198
|
-
//
|
|
199
|
-
//
|
|
200
|
-
// startup. `logLevel` is pino's level, live-editable.
|
|
198
|
+
// Nothing reads either dashboard setting any more; both stay parseable so an
|
|
199
|
+
// older config file still loads. `logLevel` is pino's level, live-editable.
|
|
201
200
|
dashboardPort: z2.number().int().min(1).max(65535).optional(),
|
|
202
201
|
autoOpen: z2.boolean().optional(),
|
|
203
202
|
logLevel: z2.enum(["warn", "info", "debug"]).optional(),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cabane/companion",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.238",
|
|
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",
|
|
@@ -16,8 +16,6 @@
|
|
|
16
16
|
"main": "./dist/cli.js",
|
|
17
17
|
"exports": {
|
|
18
18
|
".": "./dist/cli.js",
|
|
19
|
-
"./runtime": "./dist/runtime.js",
|
|
20
|
-
"./pairing": "./dist/pairing-config.js",
|
|
21
19
|
"./credential-broker": "./dist/credential-broker.js",
|
|
22
20
|
"./package.json": "./package.json",
|
|
23
21
|
"./*": "./*"
|