@cabane/companion 0.6.164 → 0.6.165

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 CHANGED
@@ -15403,6 +15403,12 @@ var DeviceApi = class {
15403
15403
  getAssignments() {
15404
15404
  return this.request("GET", "/api/companion/assignments");
15405
15405
  }
15406
+ // Ask again for the credential of an agent assigned to this device, when the saved copy is
15407
+ // gone. The previous credential stops working; any agent not assigned here is a 404, and a
15408
+ // second ask inside a minute a 429.
15409
+ reissueAgentCredential(agentId) {
15410
+ return this.request("POST", `/api/companion/agents/${encodeURIComponent(agentId)}/credential`);
15411
+ }
15406
15412
  getRuns(cursor) {
15407
15413
  const query = new URLSearchParams({ limit: "100", order: "asc" });
15408
15414
  if (cursor) query.set("cursor", cursor);
@@ -17608,6 +17614,7 @@ var CompanionSupervisor = class {
17608
17614
  for (const it of items) {
17609
17615
  if (it.credential) setCredential(device.id, it.agentId, it.credential);
17610
17616
  }
17617
+ items = await this.restoreMissingCredentials(device.id, items);
17611
17618
  const byWorkspace = /* @__PURE__ */ new Map();
17612
17619
  for (const it of items) {
17613
17620
  const list = byWorkspace.get(it.workspaceId) ?? [];
@@ -17640,6 +17647,42 @@ var CompanionSupervisor = class {
17640
17647
  this.inFlightRefresh = null;
17641
17648
  }
17642
17649
  }
17650
+ // An assigned agent whose saved credential is gone (the file wiped or edited, a crash between
17651
+ // delivery and write) gets it back here, before reconciling. A runner still holding it in
17652
+ // memory writes it back; otherwise Cabane is asked for a new one, which revokes the old. The
17653
+ // result rides the item as a fresh delivery, so reconcile builds the runner on it. A refused
17654
+ // ask leaves the item as it was, and reconcile reports the agent can't run.
17655
+ async restoreMissingCredentials(deviceId, items) {
17656
+ const restored = [];
17657
+ for (const it of items) {
17658
+ if (it.credential || getCredential(deviceId, it.agentId)) {
17659
+ restored.push(it);
17660
+ continue;
17661
+ }
17662
+ const held = this.workspaces.get(it.workspaceId)?.agents.get(it.agentId)?.credential;
17663
+ if (held) {
17664
+ setCredential(deviceId, it.agentId, held);
17665
+ restored.push(it);
17666
+ continue;
17667
+ }
17668
+ try {
17669
+ const { credential } = await this.deviceApi.reissueAgentCredential(it.agentId);
17670
+ setCredential(deviceId, it.agentId, credential);
17671
+ this.log.info(
17672
+ { agentId: it.agentId, agentName: it.agentDisplayName },
17673
+ `Restored ${it.agentDisplayName}'s sign-in to Cabane: it was missing on this device.`
17674
+ );
17675
+ restored.push({ ...it, credential });
17676
+ } catch (err) {
17677
+ this.log.warn(
17678
+ { agentId: it.agentId, agentName: it.agentDisplayName, ...apiErrorLogFields(err) },
17679
+ `Couldn't restore ${it.agentDisplayName}'s sign-in to Cabane.`
17680
+ );
17681
+ restored.push(it);
17682
+ }
17683
+ }
17684
+ return restored;
17685
+ }
17643
17686
  // ---- reconciliation ----
17644
17687
  reconcileWorkspace(deviceId, workspaceId, list) {
17645
17688
  const first = list[0];
package/dist/runtime.js CHANGED
@@ -2496,6 +2496,12 @@ var DeviceApi = class {
2496
2496
  getAssignments() {
2497
2497
  return this.request("GET", "/api/companion/assignments");
2498
2498
  }
2499
+ // Ask again for the credential of an agent assigned to this device, when the saved copy is
2500
+ // gone. The previous credential stops working; any agent not assigned here is a 404, and a
2501
+ // second ask inside a minute a 429.
2502
+ reissueAgentCredential(agentId) {
2503
+ return this.request("POST", `/api/companion/agents/${encodeURIComponent(agentId)}/credential`);
2504
+ }
2499
2505
  getRuns(cursor) {
2500
2506
  const query = new URLSearchParams({ limit: "100", order: "asc" });
2501
2507
  if (cursor) query.set("cursor", cursor);
@@ -14174,6 +14180,7 @@ var CompanionSupervisor = class {
14174
14180
  for (const it of items) {
14175
14181
  if (it.credential) setCredential(device.id, it.agentId, it.credential);
14176
14182
  }
14183
+ items = await this.restoreMissingCredentials(device.id, items);
14177
14184
  const byWorkspace = /* @__PURE__ */ new Map();
14178
14185
  for (const it of items) {
14179
14186
  const list = byWorkspace.get(it.workspaceId) ?? [];
@@ -14206,6 +14213,42 @@ var CompanionSupervisor = class {
14206
14213
  this.inFlightRefresh = null;
14207
14214
  }
14208
14215
  }
14216
+ // An assigned agent whose saved credential is gone (the file wiped or edited, a crash between
14217
+ // delivery and write) gets it back here, before reconciling. A runner still holding it in
14218
+ // memory writes it back; otherwise Cabane is asked for a new one, which revokes the old. The
14219
+ // result rides the item as a fresh delivery, so reconcile builds the runner on it. A refused
14220
+ // ask leaves the item as it was, and reconcile reports the agent can't run.
14221
+ async restoreMissingCredentials(deviceId, items) {
14222
+ const restored = [];
14223
+ for (const it of items) {
14224
+ if (it.credential || getCredential(deviceId, it.agentId)) {
14225
+ restored.push(it);
14226
+ continue;
14227
+ }
14228
+ const held = this.workspaces.get(it.workspaceId)?.agents.get(it.agentId)?.credential;
14229
+ if (held) {
14230
+ setCredential(deviceId, it.agentId, held);
14231
+ restored.push(it);
14232
+ continue;
14233
+ }
14234
+ try {
14235
+ const { credential } = await this.deviceApi.reissueAgentCredential(it.agentId);
14236
+ setCredential(deviceId, it.agentId, credential);
14237
+ this.log.info(
14238
+ { agentId: it.agentId, agentName: it.agentDisplayName },
14239
+ `Restored ${it.agentDisplayName}'s sign-in to Cabane: it was missing on this device.`
14240
+ );
14241
+ restored.push({ ...it, credential });
14242
+ } catch (err) {
14243
+ this.log.warn(
14244
+ { agentId: it.agentId, agentName: it.agentDisplayName, ...apiErrorLogFields(err) },
14245
+ `Couldn't restore ${it.agentDisplayName}'s sign-in to Cabane.`
14246
+ );
14247
+ restored.push(it);
14248
+ }
14249
+ }
14250
+ return restored;
14251
+ }
14209
14252
  // ---- reconciliation ----
14210
14253
  reconcileWorkspace(deviceId, workspaceId, list) {
14211
14254
  const first = list[0];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cabane/companion",
3
- "version": "0.6.164",
3
+ "version": "0.6.165",
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",