@cabane/companion 0.6.21 → 0.6.23
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 +14 -1
- package/dist/cli.js +46 -13
- package/dist/pairing-config.js +20 -1
- package/dist/runtime.js +38 -12
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -142,7 +142,7 @@ A `coding` agent needs a directory to run in — a path that only exists on your
|
|
|
142
142
|
"agents": {
|
|
143
143
|
"my-coding-agent": {
|
|
144
144
|
"cwd": "/Users/you/code/project", // working directory the agent runs in
|
|
145
|
-
"prepareHook": "
|
|
145
|
+
"prepareHook": { "command": "/Users/you/bin/prepare-turn" }, // optional: resolves the cwd before each turn
|
|
146
146
|
},
|
|
147
147
|
},
|
|
148
148
|
}
|
|
@@ -150,6 +150,19 @@ A `coding` agent needs a directory to run in — a path that only exists on your
|
|
|
150
150
|
|
|
151
151
|
A malformed `agents` block fails `cabane-companion start` immediately with a message pointing at the exact field — it won't silently fall back.
|
|
152
152
|
|
|
153
|
+
**A hook that is the same for every agent goes at the top level instead.** If your hook works out the directory itself — from the conversation and agent ids the Companion hands it — then listing every agent by name is a roster you have to remember to update, and an agent you forget gets no hook at all and starts its turn wherever the Companion happens to be. So `prepareHook` can sit beside `agents` rather than inside it:
|
|
154
|
+
|
|
155
|
+
```jsonc
|
|
156
|
+
{
|
|
157
|
+
"prepareHook": { "command": "/Users/you/bin/prepare-turn" }, // every agent on this device
|
|
158
|
+
"agents": {
|
|
159
|
+
"special-case": { "prepareHook": { "command": "/Users/you/bin/other-hook" } }, // wins for this one
|
|
160
|
+
},
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
The agent's own entry wins when it names a hook; otherwise the device-level one applies. It survives a re-pair along with the rest of your local settings, and `cabane-companion status` prints it. A hook that fails still fails the turn loudly either way.
|
|
165
|
+
|
|
153
166
|
### Auto-memory (off by default)
|
|
154
167
|
|
|
155
168
|
Claude Code's **auto-memory** — where the agent writes notes to a local `~/.claude` memory directory and recalls them on later turns — is **off by default** on every Companion. The stance is that memory-shaped things belong in your Cabane workspace (a shared, versioned `ABOUT.md`-style file or doc), not a private local directory that no one else can see. If you run your own Companion and want your normal Claude Code memory workflow back, set `claudeCode.autoMemory: true` on the agent — the Companion then stops overriding it and your own `~/.claude/settings.json` governs auto-memory as usual (this bites in `coding` mode, where your project settings are read):
|
package/dist/cli.js
CHANGED
|
@@ -278,6 +278,22 @@ var companionConfigSchema = z2.object({
|
|
|
278
278
|
// agentId / username / `slug/username`. Hand-added by the operator; the companion
|
|
279
279
|
// never writes this (it only persists credentials + the device, elsewhere).
|
|
280
280
|
agents: z2.record(z2.string(), localAgentConfigSchema).optional(),
|
|
281
|
+
// CT1095: the DEVICE-LEVEL prepare hook — one entry that applies to every agent
|
|
282
|
+
// assigned to this device, unless that agent's own `agents` row names a hook of
|
|
283
|
+
// its own.
|
|
284
|
+
//
|
|
285
|
+
// Until now `prepareHook` existed only under `agents[<id>]`, which made the
|
|
286
|
+
// config a second silent roster: a device whose provisioning is genuinely
|
|
287
|
+
// per-device (ours resolves a directory from the conversation and agent ids the
|
|
288
|
+
// companion already hands the hook) still had to list every agent by id, and an
|
|
289
|
+
// agent nobody remembered to add got no hook at all — no error, no log, just a
|
|
290
|
+
// turn that started in the operator's `$HOME`. That is how @dale woke in
|
|
291
|
+
// `/home/joshed` on 2026-08-17 with a perfectly correct dispatch.
|
|
292
|
+
//
|
|
293
|
+
// Absent → nothing changes for anyone, which is why this can land inert: a
|
|
294
|
+
// device with no device-level entry behaves exactly as it did before. A hook
|
|
295
|
+
// that fails still fails the dispatch loudly, as now.
|
|
296
|
+
prepareHook: prepareHookSchema.optional(),
|
|
281
297
|
// Dashboard settings (all optional). dashboardPort: preferred bind port (next
|
|
282
298
|
// free one if taken); autoOpen: whether `start` opens the browser (the
|
|
283
299
|
// `--no-open` flag / `COMPANION_NO_OPEN=1` override per-run); logLevel: pino
|
|
@@ -340,7 +356,9 @@ function migrateConnectedHarnesses(cfg, claudeOnPath2) {
|
|
|
340
356
|
}
|
|
341
357
|
function localAgentConfig(cfg, agent) {
|
|
342
358
|
const map = cfg.agents ?? {};
|
|
343
|
-
|
|
359
|
+
const row = map[agent.agentId] ?? map[agent.agentUsername] ?? map[`${agent.workspaceSlug}/${agent.agentUsername}`] ?? {};
|
|
360
|
+
if (!cfg.prepareHook || row.prepareHook) return row;
|
|
361
|
+
return { ...row, prepareHook: cfg.prepareHook };
|
|
344
362
|
}
|
|
345
363
|
function loadConfig() {
|
|
346
364
|
const path = configPath();
|
|
@@ -400,10 +418,11 @@ function loadConfigTolerant() {
|
|
|
400
418
|
}
|
|
401
419
|
const strict = companionConfigSchema.safeParse(parsed);
|
|
402
420
|
if (strict.success) {
|
|
403
|
-
const { agents: agents2, dashboardPort, autoOpen, logLevel, claudeCode: claudeCode2 } = strict.data;
|
|
421
|
+
const { agents: agents2, prepareHook: prepareHook2, dashboardPort, autoOpen, logLevel, claudeCode: claudeCode2 } = strict.data;
|
|
404
422
|
return {
|
|
405
423
|
local: {
|
|
406
424
|
...agents2 !== void 0 ? { agents: agents2 } : {},
|
|
425
|
+
...prepareHook2 !== void 0 ? { prepareHook: prepareHook2 } : {},
|
|
407
426
|
...dashboardPort !== void 0 ? { dashboardPort } : {},
|
|
408
427
|
...autoOpen !== void 0 ? { autoOpen } : {},
|
|
409
428
|
...logLevel !== void 0 ? { logLevel } : {},
|
|
@@ -417,6 +436,8 @@ function loadConfigTolerant() {
|
|
|
417
436
|
const local = {};
|
|
418
437
|
const agents = z2.record(z2.string(), localAgentConfigSchema).safeParse(obj.agents);
|
|
419
438
|
if (agents.success) local.agents = agents.data;
|
|
439
|
+
const prepareHook = prepareHookSchema.safeParse(obj.prepareHook);
|
|
440
|
+
if (prepareHook.success) local.prepareHook = prepareHook.data;
|
|
420
441
|
if (typeof obj.dashboardPort === "number") local.dashboardPort = obj.dashboardPort;
|
|
421
442
|
if (typeof obj.autoOpen === "boolean") local.autoOpen = obj.autoOpen;
|
|
422
443
|
if (obj.logLevel === "warn" || obj.logLevel === "info" || obj.logLevel === "debug") {
|
|
@@ -6834,10 +6855,11 @@ function describeSubAgentError(status2, body) {
|
|
|
6834
6855
|
var Dispatcher = class {
|
|
6835
6856
|
constructor(opts) {
|
|
6836
6857
|
this.opts = opts;
|
|
6858
|
+
this.aborts = opts.aborts ?? /* @__PURE__ */ new Map();
|
|
6837
6859
|
}
|
|
6838
6860
|
opts;
|
|
6839
6861
|
// SJ383: per-(conversation, agent) abort registry.
|
|
6840
|
-
aborts
|
|
6862
|
+
aborts;
|
|
6841
6863
|
notifyStart(info) {
|
|
6842
6864
|
try {
|
|
6843
6865
|
this.opts.observer?.onStart(info);
|
|
@@ -8587,6 +8609,7 @@ var CompanionSupervisor = class {
|
|
|
8587
8609
|
outbox,
|
|
8588
8610
|
log: this.log
|
|
8589
8611
|
});
|
|
8612
|
+
const aborts = /* @__PURE__ */ new Map();
|
|
8590
8613
|
const dispatcher = this.buildDispatcher({
|
|
8591
8614
|
api,
|
|
8592
8615
|
baseUrl: this.config.baseUrl,
|
|
@@ -8595,7 +8618,8 @@ var CompanionSupervisor = class {
|
|
|
8595
8618
|
agentId: it.agentId,
|
|
8596
8619
|
agentUsername: it.agentUsername,
|
|
8597
8620
|
credential,
|
|
8598
|
-
runConfig
|
|
8621
|
+
runConfig,
|
|
8622
|
+
aborts
|
|
8599
8623
|
});
|
|
8600
8624
|
const drain2 = this.makeDrain(api, it.agentId);
|
|
8601
8625
|
wr.agents.set(it.agentId, {
|
|
@@ -8605,6 +8629,7 @@ var CompanionSupervisor = class {
|
|
|
8605
8629
|
credential,
|
|
8606
8630
|
runConfig,
|
|
8607
8631
|
api,
|
|
8632
|
+
aborts,
|
|
8608
8633
|
dispatcher,
|
|
8609
8634
|
cancelDrain: drain2.cancel,
|
|
8610
8635
|
kickDrain: drain2.kick
|
|
@@ -8640,7 +8665,12 @@ var CompanionSupervisor = class {
|
|
|
8640
8665
|
return isClaudeCodeConnected(this.config) && this.claudeCodePresent();
|
|
8641
8666
|
}
|
|
8642
8667
|
buildDispatcher(ctx) {
|
|
8643
|
-
|
|
8668
|
+
const local = localAgentConfig(this.config, {
|
|
8669
|
+
agentId: ctx.agentId,
|
|
8670
|
+
agentUsername: ctx.agentUsername,
|
|
8671
|
+
workspaceSlug: ctx.workspaceSlug
|
|
8672
|
+
});
|
|
8673
|
+
if (this.dispatcherFactory) return this.dispatcherFactory({ ...ctx, local });
|
|
8644
8674
|
return new Dispatcher({
|
|
8645
8675
|
api: ctx.api,
|
|
8646
8676
|
baseUrl: ctx.baseUrl,
|
|
@@ -8649,11 +8679,8 @@ var CompanionSupervisor = class {
|
|
|
8649
8679
|
agentId: ctx.agentId,
|
|
8650
8680
|
agentUsername: ctx.agentUsername,
|
|
8651
8681
|
credential: ctx.credential,
|
|
8652
|
-
local
|
|
8653
|
-
|
|
8654
|
-
agentUsername: ctx.agentUsername,
|
|
8655
|
-
workspaceSlug: ctx.workspaceSlug
|
|
8656
|
-
}),
|
|
8682
|
+
local,
|
|
8683
|
+
aborts: ctx.aborts,
|
|
8657
8684
|
runConfig: ctx.runConfig,
|
|
8658
8685
|
log: this.log,
|
|
8659
8686
|
// CT833: register the claude-code adapter only when this device actually
|
|
@@ -8923,6 +8950,7 @@ var CompanionSupervisor = class {
|
|
|
8923
8950
|
if (!next) return;
|
|
8924
8951
|
this.config = next;
|
|
8925
8952
|
this.log.level = next.logLevel ?? "debug";
|
|
8953
|
+
this.rebuildDispatchers();
|
|
8926
8954
|
void this.refreshAssignments();
|
|
8927
8955
|
}
|
|
8928
8956
|
// The dashboard "refresh assignments" control — an immediate pull.
|
|
@@ -9020,8 +9048,8 @@ var CompanionSupervisor = class {
|
|
|
9020
9048
|
}
|
|
9021
9049
|
// Re-create every running agent's Dispatcher from the CURRENT config, keeping
|
|
9022
9050
|
// the runner (its api/outbox/chains/SSE) intact. Used after a runtime-enabling
|
|
9023
|
-
// config change so
|
|
9024
|
-
//
|
|
9051
|
+
// config change so constructor-captured options — per-agent cwd/prepareHook and
|
|
9052
|
+
// the adapter registry — pick up their new values without an app restart.
|
|
9025
9053
|
rebuildDispatchers() {
|
|
9026
9054
|
for (const wr of this.workspaces.values()) {
|
|
9027
9055
|
for (const runner of wr.agents.values()) {
|
|
@@ -9033,7 +9061,8 @@ var CompanionSupervisor = class {
|
|
|
9033
9061
|
agentId: runner.agentId,
|
|
9034
9062
|
agentUsername: runner.username,
|
|
9035
9063
|
credential: runner.credential,
|
|
9036
|
-
runConfig: runner.runConfig
|
|
9064
|
+
runConfig: runner.runConfig,
|
|
9065
|
+
aborts: runner.aborts
|
|
9037
9066
|
});
|
|
9038
9067
|
}
|
|
9039
9068
|
}
|
|
@@ -9441,6 +9470,10 @@ async function status() {
|
|
|
9441
9470
|
names.length > 0 ? `secrets: ${names.length} declared (${names.join(", ")})
|
|
9442
9471
|
` : "secrets: none declared \u2014 add `${VAR}` values to ~/.cabane/secrets.json for MCP servers that need them\n"
|
|
9443
9472
|
);
|
|
9473
|
+
if (cfg.prepareHook) {
|
|
9474
|
+
process.stdout.write(`prepare hook: ${cfg.prepareHook.command} (device-level, all agents)
|
|
9475
|
+
`);
|
|
9476
|
+
}
|
|
9444
9477
|
const overrides = Object.keys(cfg.agents ?? {});
|
|
9445
9478
|
if (overrides.length > 0) {
|
|
9446
9479
|
process.stdout.write(`local overrides for: ${overrides.join(", ")}
|
package/dist/pairing-config.js
CHANGED
|
@@ -144,6 +144,22 @@ var companionConfigSchema = z2.object({
|
|
|
144
144
|
// agentId / username / `slug/username`. Hand-added by the operator; the companion
|
|
145
145
|
// never writes this (it only persists credentials + the device, elsewhere).
|
|
146
146
|
agents: z2.record(z2.string(), localAgentConfigSchema).optional(),
|
|
147
|
+
// CT1095: the DEVICE-LEVEL prepare hook — one entry that applies to every agent
|
|
148
|
+
// assigned to this device, unless that agent's own `agents` row names a hook of
|
|
149
|
+
// its own.
|
|
150
|
+
//
|
|
151
|
+
// Until now `prepareHook` existed only under `agents[<id>]`, which made the
|
|
152
|
+
// config a second silent roster: a device whose provisioning is genuinely
|
|
153
|
+
// per-device (ours resolves a directory from the conversation and agent ids the
|
|
154
|
+
// companion already hands the hook) still had to list every agent by id, and an
|
|
155
|
+
// agent nobody remembered to add got no hook at all — no error, no log, just a
|
|
156
|
+
// turn that started in the operator's `$HOME`. That is how @dale woke in
|
|
157
|
+
// `/home/joshed` on 2026-08-17 with a perfectly correct dispatch.
|
|
158
|
+
//
|
|
159
|
+
// Absent → nothing changes for anyone, which is why this can land inert: a
|
|
160
|
+
// device with no device-level entry behaves exactly as it did before. A hook
|
|
161
|
+
// that fails still fails the dispatch loudly, as now.
|
|
162
|
+
prepareHook: prepareHookSchema.optional(),
|
|
147
163
|
// Dashboard settings (all optional). dashboardPort: preferred bind port (next
|
|
148
164
|
// free one if taken); autoOpen: whether `start` opens the browser (the
|
|
149
165
|
// `--no-open` flag / `COMPANION_NO_OPEN=1` override per-run); logLevel: pino
|
|
@@ -252,10 +268,11 @@ function loadConfigTolerant() {
|
|
|
252
268
|
}
|
|
253
269
|
const strict = companionConfigSchema.safeParse(parsed);
|
|
254
270
|
if (strict.success) {
|
|
255
|
-
const { agents: agents2, dashboardPort, autoOpen, logLevel, claudeCode: claudeCode2 } = strict.data;
|
|
271
|
+
const { agents: agents2, prepareHook: prepareHook2, dashboardPort, autoOpen, logLevel, claudeCode: claudeCode2 } = strict.data;
|
|
256
272
|
return {
|
|
257
273
|
local: {
|
|
258
274
|
...agents2 !== void 0 ? { agents: agents2 } : {},
|
|
275
|
+
...prepareHook2 !== void 0 ? { prepareHook: prepareHook2 } : {},
|
|
259
276
|
...dashboardPort !== void 0 ? { dashboardPort } : {},
|
|
260
277
|
...autoOpen !== void 0 ? { autoOpen } : {},
|
|
261
278
|
...logLevel !== void 0 ? { logLevel } : {},
|
|
@@ -269,6 +286,8 @@ function loadConfigTolerant() {
|
|
|
269
286
|
const local = {};
|
|
270
287
|
const agents = z2.record(z2.string(), localAgentConfigSchema).safeParse(obj.agents);
|
|
271
288
|
if (agents.success) local.agents = agents.data;
|
|
289
|
+
const prepareHook = prepareHookSchema.safeParse(obj.prepareHook);
|
|
290
|
+
if (prepareHook.success) local.prepareHook = prepareHook.data;
|
|
272
291
|
if (typeof obj.dashboardPort === "number") local.dashboardPort = obj.dashboardPort;
|
|
273
292
|
if (typeof obj.autoOpen === "boolean") local.autoOpen = obj.autoOpen;
|
|
274
293
|
if (obj.logLevel === "warn" || obj.logLevel === "info" || obj.logLevel === "debug") {
|
package/dist/runtime.js
CHANGED
|
@@ -271,6 +271,22 @@ var companionConfigSchema = z2.object({
|
|
|
271
271
|
// agentId / username / `slug/username`. Hand-added by the operator; the companion
|
|
272
272
|
// never writes this (it only persists credentials + the device, elsewhere).
|
|
273
273
|
agents: z2.record(z2.string(), localAgentConfigSchema).optional(),
|
|
274
|
+
// CT1095: the DEVICE-LEVEL prepare hook — one entry that applies to every agent
|
|
275
|
+
// assigned to this device, unless that agent's own `agents` row names a hook of
|
|
276
|
+
// its own.
|
|
277
|
+
//
|
|
278
|
+
// Until now `prepareHook` existed only under `agents[<id>]`, which made the
|
|
279
|
+
// config a second silent roster: a device whose provisioning is genuinely
|
|
280
|
+
// per-device (ours resolves a directory from the conversation and agent ids the
|
|
281
|
+
// companion already hands the hook) still had to list every agent by id, and an
|
|
282
|
+
// agent nobody remembered to add got no hook at all — no error, no log, just a
|
|
283
|
+
// turn that started in the operator's `$HOME`. That is how @dale woke in
|
|
284
|
+
// `/home/joshed` on 2026-08-17 with a perfectly correct dispatch.
|
|
285
|
+
//
|
|
286
|
+
// Absent → nothing changes for anyone, which is why this can land inert: a
|
|
287
|
+
// device with no device-level entry behaves exactly as it did before. A hook
|
|
288
|
+
// that fails still fails the dispatch loudly, as now.
|
|
289
|
+
prepareHook: prepareHookSchema.optional(),
|
|
274
290
|
// Dashboard settings (all optional). dashboardPort: preferred bind port (next
|
|
275
291
|
// free one if taken); autoOpen: whether `start` opens the browser (the
|
|
276
292
|
// `--no-open` flag / `COMPANION_NO_OPEN=1` override per-run); logLevel: pino
|
|
@@ -333,7 +349,9 @@ function migrateConnectedHarnesses(cfg, claudeOnPath2) {
|
|
|
333
349
|
}
|
|
334
350
|
function localAgentConfig(cfg, agent) {
|
|
335
351
|
const map = cfg.agents ?? {};
|
|
336
|
-
|
|
352
|
+
const row = map[agent.agentId] ?? map[agent.agentUsername] ?? map[`${agent.workspaceSlug}/${agent.agentUsername}`] ?? {};
|
|
353
|
+
if (!cfg.prepareHook || row.prepareHook) return row;
|
|
354
|
+
return { ...row, prepareHook: cfg.prepareHook };
|
|
337
355
|
}
|
|
338
356
|
function loadConfig() {
|
|
339
357
|
const path = configPath();
|
|
@@ -6456,10 +6474,11 @@ function describeSubAgentError(status, body) {
|
|
|
6456
6474
|
var Dispatcher = class {
|
|
6457
6475
|
constructor(opts) {
|
|
6458
6476
|
this.opts = opts;
|
|
6477
|
+
this.aborts = opts.aborts ?? /* @__PURE__ */ new Map();
|
|
6459
6478
|
}
|
|
6460
6479
|
opts;
|
|
6461
6480
|
// SJ383: per-(conversation, agent) abort registry.
|
|
6462
|
-
aborts
|
|
6481
|
+
aborts;
|
|
6463
6482
|
notifyStart(info) {
|
|
6464
6483
|
try {
|
|
6465
6484
|
this.opts.observer?.onStart(info);
|
|
@@ -8209,6 +8228,7 @@ var CompanionSupervisor = class {
|
|
|
8209
8228
|
outbox,
|
|
8210
8229
|
log: this.log
|
|
8211
8230
|
});
|
|
8231
|
+
const aborts = /* @__PURE__ */ new Map();
|
|
8212
8232
|
const dispatcher = this.buildDispatcher({
|
|
8213
8233
|
api,
|
|
8214
8234
|
baseUrl: this.config.baseUrl,
|
|
@@ -8217,7 +8237,8 @@ var CompanionSupervisor = class {
|
|
|
8217
8237
|
agentId: it.agentId,
|
|
8218
8238
|
agentUsername: it.agentUsername,
|
|
8219
8239
|
credential,
|
|
8220
|
-
runConfig
|
|
8240
|
+
runConfig,
|
|
8241
|
+
aborts
|
|
8221
8242
|
});
|
|
8222
8243
|
const drain2 = this.makeDrain(api, it.agentId);
|
|
8223
8244
|
wr.agents.set(it.agentId, {
|
|
@@ -8227,6 +8248,7 @@ var CompanionSupervisor = class {
|
|
|
8227
8248
|
credential,
|
|
8228
8249
|
runConfig,
|
|
8229
8250
|
api,
|
|
8251
|
+
aborts,
|
|
8230
8252
|
dispatcher,
|
|
8231
8253
|
cancelDrain: drain2.cancel,
|
|
8232
8254
|
kickDrain: drain2.kick
|
|
@@ -8262,7 +8284,12 @@ var CompanionSupervisor = class {
|
|
|
8262
8284
|
return isClaudeCodeConnected(this.config) && this.claudeCodePresent();
|
|
8263
8285
|
}
|
|
8264
8286
|
buildDispatcher(ctx) {
|
|
8265
|
-
|
|
8287
|
+
const local = localAgentConfig(this.config, {
|
|
8288
|
+
agentId: ctx.agentId,
|
|
8289
|
+
agentUsername: ctx.agentUsername,
|
|
8290
|
+
workspaceSlug: ctx.workspaceSlug
|
|
8291
|
+
});
|
|
8292
|
+
if (this.dispatcherFactory) return this.dispatcherFactory({ ...ctx, local });
|
|
8266
8293
|
return new Dispatcher({
|
|
8267
8294
|
api: ctx.api,
|
|
8268
8295
|
baseUrl: ctx.baseUrl,
|
|
@@ -8271,11 +8298,8 @@ var CompanionSupervisor = class {
|
|
|
8271
8298
|
agentId: ctx.agentId,
|
|
8272
8299
|
agentUsername: ctx.agentUsername,
|
|
8273
8300
|
credential: ctx.credential,
|
|
8274
|
-
local
|
|
8275
|
-
|
|
8276
|
-
agentUsername: ctx.agentUsername,
|
|
8277
|
-
workspaceSlug: ctx.workspaceSlug
|
|
8278
|
-
}),
|
|
8301
|
+
local,
|
|
8302
|
+
aborts: ctx.aborts,
|
|
8279
8303
|
runConfig: ctx.runConfig,
|
|
8280
8304
|
log: this.log,
|
|
8281
8305
|
// CT833: register the claude-code adapter only when this device actually
|
|
@@ -8545,6 +8569,7 @@ var CompanionSupervisor = class {
|
|
|
8545
8569
|
if (!next) return;
|
|
8546
8570
|
this.config = next;
|
|
8547
8571
|
this.log.level = next.logLevel ?? "debug";
|
|
8572
|
+
this.rebuildDispatchers();
|
|
8548
8573
|
void this.refreshAssignments();
|
|
8549
8574
|
}
|
|
8550
8575
|
// The dashboard "refresh assignments" control — an immediate pull.
|
|
@@ -8642,8 +8667,8 @@ var CompanionSupervisor = class {
|
|
|
8642
8667
|
}
|
|
8643
8668
|
// Re-create every running agent's Dispatcher from the CURRENT config, keeping
|
|
8644
8669
|
// the runner (its api/outbox/chains/SSE) intact. Used after a runtime-enabling
|
|
8645
|
-
// config change so
|
|
8646
|
-
//
|
|
8670
|
+
// config change so constructor-captured options — per-agent cwd/prepareHook and
|
|
8671
|
+
// the adapter registry — pick up their new values without an app restart.
|
|
8647
8672
|
rebuildDispatchers() {
|
|
8648
8673
|
for (const wr of this.workspaces.values()) {
|
|
8649
8674
|
for (const runner of wr.agents.values()) {
|
|
@@ -8655,7 +8680,8 @@ var CompanionSupervisor = class {
|
|
|
8655
8680
|
agentId: runner.agentId,
|
|
8656
8681
|
agentUsername: runner.username,
|
|
8657
8682
|
credential: runner.credential,
|
|
8658
|
-
runConfig: runner.runConfig
|
|
8683
|
+
runConfig: runner.runConfig,
|
|
8684
|
+
aborts: runner.aborts
|
|
8659
8685
|
});
|
|
8660
8686
|
}
|
|
8661
8687
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cabane/companion",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.23",
|
|
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",
|