@bivy/bivy 0.5.1-staging.63 → 0.5.1-staging.64

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.
Files changed (2) hide show
  1. package/dist/server.js +34 -0
  2. package/package.json +1 -1
package/dist/server.js CHANGED
@@ -3618,6 +3618,18 @@ function startRelayIfConfigured() {
3618
3618
  clearInterval(advertiseResyncTimer);
3619
3619
  advertiseResyncTimer = setInterval(() => scheduleAdvertise(), 60_000);
3620
3620
  advertiseResyncTimer.unref?.();
3621
+ // Periodic online heartbeat. The relay flips the node's `online` flag
3622
+ // fire-and-forget on socket connect/close with no ordering guard, so a
3623
+ // late/racing `false` can pin a genuinely-connected node offline in the
3624
+ // registry until some later reconnect wins. Re-affirming online on a steady
3625
+ // interval keeps `last_seen_at` fresh and self-heals a lost race (the control
3626
+ // plane treats a recent heartbeat as online — see NODE_ONLINE_TTL_MS). Fire one
3627
+ // immediately so a reconnect corrects a stale `false` without waiting a full tick.
3628
+ if (nodeHeartbeatTimer)
3629
+ clearInterval(nodeHeartbeatTimer);
3630
+ void sendNodeHeartbeat();
3631
+ nodeHeartbeatTimer = setInterval(() => void sendNodeHeartbeat(), NODE_HEARTBEAT_MS);
3632
+ nodeHeartbeatTimer.unref?.();
3621
3633
  }
3622
3634
  console.log("[relay] connector enabled");
3623
3635
  return true;
@@ -4100,6 +4112,28 @@ function startModelAuthWatcher() {
4100
4112
  let sessionAdvertiseTarget;
4101
4113
  let advertiseTimer;
4102
4114
  let advertiseResyncTimer;
4115
+ // How often the node re-affirms it's online to the control plane. Kept well
4116
+ // under the control plane's NODE_ONLINE_TTL_MS (90s) so a missed beat or two
4117
+ // doesn't flap a healthy node's status.
4118
+ const NODE_HEARTBEAT_MS = 30_000;
4119
+ let nodeHeartbeatTimer;
4120
+ /** Re-affirm this node's online status so the registry self-heals a lost
4121
+ * relay connect/close race (see the heartbeat wiring in the relay connector
4122
+ * and NODE_ONLINE_TTL_MS in the control plane). Best-effort: a missed beat is
4123
+ * covered by the next tick and the TTL window. */
4124
+ async function sendNodeHeartbeat() {
4125
+ if (!sessionAdvertiseTarget)
4126
+ return;
4127
+ try {
4128
+ await fetch(`${sessionAdvertiseTarget.controlPlaneUrl.replace(/\/$/, "")}/node/heartbeat`, {
4129
+ method: "POST",
4130
+ headers: { authorization: `Bearer ${sessionAdvertiseTarget.enrollmentToken}` },
4131
+ });
4132
+ }
4133
+ catch {
4134
+ // best effort; the next tick retries
4135
+ }
4136
+ }
4103
4137
  async function advertiseNodeName(name, prevName) {
4104
4138
  if (!sessionAdvertiseTarget)
4105
4139
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bivy/bivy",
3
- "version": "0.5.1-staging.63",
3
+ "version": "0.5.1-staging.64",
4
4
  "type": "module",
5
5
  "license": "FSL-1.1-ALv2",
6
6
  "description": "Run coding agents on machines you own. Source-available, self-hostable agent workspace.",