@cabane/companion 0.6.25 → 0.6.27
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 +731 -174
- package/dist/runtime.js +26 -15
- package/package.json +1 -1
package/dist/runtime.js
CHANGED
|
@@ -7996,6 +7996,7 @@ var CompanionSupervisor = class {
|
|
|
7996
7996
|
refreshing = false;
|
|
7997
7997
|
stopped = false;
|
|
7998
7998
|
draining = false;
|
|
7999
|
+
restartPending = false;
|
|
7999
8000
|
// CT484: latch so the companion/server version-skew warning is logged once, not
|
|
8000
8001
|
// on every 30s heartbeat.
|
|
8001
8002
|
versionSkewWarned = false;
|
|
@@ -8106,7 +8107,8 @@ var CompanionSupervisor = class {
|
|
|
8106
8107
|
// actually landed (`harnessSignals` non-null) — an absent field means "we
|
|
8107
8108
|
// didn't look this beat" and leaves the server's stored suggestion alone,
|
|
8108
8109
|
// the same fail-soft contract `models` keeps.
|
|
8109
|
-
...this.harnessSignals ? { detectedRuntimes: detectedRuntimesFor(deriveHarnessSnapshot(this.harnessSignals)) } : {}
|
|
8110
|
+
...this.harnessSignals ? { detectedRuntimes: detectedRuntimesFor(deriveHarnessSnapshot(this.harnessSignals)) } : {},
|
|
8111
|
+
...this.restartPending ? { restarting: true } : {}
|
|
8110
8112
|
});
|
|
8111
8113
|
this.hub.setDevice({ deviceId: res.deviceId });
|
|
8112
8114
|
this.deviceId = res.deviceId;
|
|
@@ -8744,32 +8746,41 @@ var CompanionSupervisor = class {
|
|
|
8744
8746
|
);
|
|
8745
8747
|
}
|
|
8746
8748
|
async drainForRestart(graceMs) {
|
|
8747
|
-
this.
|
|
8748
|
-
if (this.heartbeatTimer) clearInterval(this.heartbeatTimer);
|
|
8749
|
-
if (this.pollTimer) clearInterval(this.pollTimer);
|
|
8749
|
+
this.restartPending = true;
|
|
8750
8750
|
if (this.inFlightHeartbeat) await this.inFlightHeartbeat;
|
|
8751
8751
|
if (!this.deviceApi) throw new Error("cannot establish deploy drain before pairing");
|
|
8752
|
-
await this.
|
|
8753
|
-
|
|
8754
|
-
const
|
|
8752
|
+
await this.sendHeartbeat();
|
|
8753
|
+
const drainStartedAt = Date.now();
|
|
8754
|
+
const deadline = Date.now() + Math.max(0, graceMs);
|
|
8755
8755
|
let timedOut = false;
|
|
8756
|
-
|
|
8756
|
+
while (true) {
|
|
8757
|
+
const turns = [...this.workspaces.values()].flatMap((wr) => [...wr.chains.values()]);
|
|
8758
|
+
if (turns.length === 0) break;
|
|
8759
|
+
const remainingMs = deadline - Date.now();
|
|
8760
|
+
if (remainingMs <= 0) {
|
|
8761
|
+
timedOut = true;
|
|
8762
|
+
break;
|
|
8763
|
+
}
|
|
8757
8764
|
let timer;
|
|
8758
8765
|
await Promise.race([
|
|
8759
8766
|
Promise.allSettled(turns),
|
|
8760
8767
|
new Promise((resolve) => {
|
|
8761
|
-
timer = setTimeout(
|
|
8762
|
-
() => {
|
|
8763
|
-
timedOut = true;
|
|
8764
|
-
resolve();
|
|
8765
|
-
},
|
|
8766
|
-
Math.max(0, graceMs)
|
|
8767
|
-
);
|
|
8768
|
+
timer = setTimeout(resolve, remainingMs);
|
|
8768
8769
|
timer.unref?.();
|
|
8769
8770
|
})
|
|
8770
8771
|
]);
|
|
8771
8772
|
if (timer) clearTimeout(timer);
|
|
8772
8773
|
}
|
|
8774
|
+
this.log.info(
|
|
8775
|
+
{ waitedMs: Date.now() - drainStartedAt, timedOut },
|
|
8776
|
+
timedOut ? "companion: deploy drain grace elapsed; fencing admission for restart" : "companion: deploy drain reached a quiet point; fencing admission for restart"
|
|
8777
|
+
);
|
|
8778
|
+
this.draining = true;
|
|
8779
|
+
if (this.heartbeatTimer) clearInterval(this.heartbeatTimer);
|
|
8780
|
+
if (this.pollTimer) clearInterval(this.pollTimer);
|
|
8781
|
+
if (this.inFlightHeartbeat) await this.inFlightHeartbeat;
|
|
8782
|
+
await this.deviceApi.beginDrain();
|
|
8783
|
+
for (const wr of this.workspaces.values()) wr.sub?.stop();
|
|
8773
8784
|
await Promise.allSettled(
|
|
8774
8785
|
[...this.workspaces.values()].flatMap(
|
|
8775
8786
|
(wr) => [...wr.agents.values()].map((agent) => agent.api.drainOutbox())
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cabane/companion",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.27",
|
|
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",
|