visionclaw 0.1.188-beta.4 → 0.1.188-beta.5

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.
@@ -1,9 +1,25 @@
1
1
  /**
2
- * HeartbeatManager — encapsulates all runtime heartbeat interactions with
3
- * the onboarding service: startup validation, per-wake heartbeats, busy
4
- * keep-alive intervals, and end-of-cycle status updates.
2
+ * HeartbeatManager — owns the always-on heartbeat lifecycle.
5
3
  *
6
- * Extracted from loop.ts to reduce the number of concerns in the main loop.
4
+ * Heartbeats are intentionally decoupled from the wake/sleep cycle so the
5
+ * onboarding service sees an accurate liveness signal even during long
6
+ * sleeps (notably the 2-hour overnight interval). The runtime loop is a
7
+ * single recursive `setTimeout` whose cadence adapts to `agentState.busy`:
8
+ *
9
+ * - busy === true -> 30s (preserves dashboard precision during work)
10
+ * - busy === false -> 5min (idle keep-alive)
11
+ *
12
+ * Every heartbeat (startup, runtime tick, subscription gate, nudge)
13
+ * funnels through one private `sendHeartbeat()` method that owns the
14
+ * mutex, payload build, and full response handling (subscription,
15
+ * billing, shared keys, credential bundle, pending commands, ack
16
+ * confirm/requeue). This eliminates the previously scattered duplicate
17
+ * response-handling blocks in init/onWake/sendHeartbeatForSubscription.
18
+ *
19
+ * The local on-disk heartbeat file is a separate liveness signal
20
+ * consumed by the in-process child watchdog (see heartbeat-watchdog.ts).
21
+ * It is refreshed at the top of every send, so it stays fresh even when
22
+ * cloud heartbeat credentials are absent.
7
23
  */
8
24
  import type { VisionClawConfig } from "../config/types.js";
9
25
  import type { ChannelManager } from "../channels/manager.js";
@@ -27,7 +43,6 @@ export interface HeartbeatManagerOptions {
27
43
  export declare class HeartbeatManager {
28
44
  private client;
29
45
  readonly commandDispatcher: CommandDispatcher;
30
- private busyInterval;
31
46
  private readonly config;
32
47
  private channelManager;
33
48
  private _lastSubscriptionStatus;
@@ -40,9 +55,41 @@ export declare class HeartbeatManager {
40
55
  * building the next payload.
41
56
  */
42
57
  private readonly credentialBundle;
58
+ /** Recursive setTimeout handle. `null` when the loop is not armed. */
59
+ private runtimeTimer;
60
+ /** Provider for current `agentState.busy`. Set by `startRuntime`. */
61
+ private getBusy;
62
+ /**
63
+ * Mutex tail — every `sendHeartbeat` awaits this then replaces it
64
+ * with the new in-flight promise so concurrent callers serialise.
65
+ * Initialised to a resolved promise so the first send doesn't block.
66
+ */
67
+ private sendMutex;
43
68
  constructor(config: VisionClawConfig, options?: HeartbeatManagerOptions);
44
69
  /** Build a base heartbeat payload including owner info for server-side backfill. */
45
70
  private buildPayload;
71
+ /**
72
+ * The single place every heartbeat goes through.
73
+ *
74
+ * - Always refreshes the on-disk heartbeat file (cheap, even when no
75
+ * onboarding-service client is configured).
76
+ * - Mutex-serialises concurrent callers (busy ticks, idle ticks,
77
+ * subscription gate polls, nudges) so command acks cannot be
78
+ * double-submitted and response handlers cannot interleave.
79
+ * - In `strict` mode, errors are rethrown after re-queuing acks so
80
+ * `init()` can surface auth failures and disable the client. In
81
+ * non-strict mode errors are caught and acks are requeued for the
82
+ * next attempt, identical to the previous best-effort behaviour.
83
+ * - Does NOT wake the main loop. The `notify` command handler in
84
+ * loop.ts is responsible for waking after it enqueues the message;
85
+ * waking from inside `sendHeartbeat` would race that handler.
86
+ */
87
+ private sendHeartbeat;
88
+ /**
89
+ * Body of a single heartbeat send, executed under the mutex. Split
90
+ * out from `sendHeartbeat` so the locking shell is a thin wrapper.
91
+ */
92
+ private runSend;
46
93
  /**
47
94
  * Initialize the heartbeat client and validate the API key.
48
95
  * Should be called once at startup. If validation fails, heartbeats
@@ -67,30 +114,49 @@ export declare class HeartbeatManager {
67
114
  currentPeriodEnd: string | null;
68
115
  portalUrl?: string;
69
116
  } | null>;
70
- /**
71
- * Send a heartbeat at the start of each wake cycle.
72
- * Dispatches any pending commands from the server and applies shared keys.
73
- */
74
- onWake(busy: boolean): Promise<void>;
75
117
  /**
76
118
  * Send a single heartbeat and return the subscription status from the response.
77
119
  * Used by the subscription gate for fast-polling (10s interval).
78
120
  */
79
121
  sendHeartbeatForSubscription(): Promise<SubscriptionStatus>;
80
122
  /**
81
- * Start periodic keep-alives while the agent is busy processing a cycle.
123
+ * Arm the always-on runtime heartbeat loop.
124
+ *
125
+ * Called once at process startup, after `agentState` is initialised so
126
+ * the `getBusy` provider can read the live busy flag. Does NOT fire
127
+ * an immediate heartbeat — `init()` already sent the strict startup
128
+ * heartbeat, and an immediate runtime tick would just duplicate it.
129
+ * State-change latency is covered by `nudge()`, not by an immediate
130
+ * fire.
131
+ *
132
+ * Calling `startRuntime` while the loop is already armed is a no-op
133
+ * apart from refreshing the `getBusy` reference; this makes the
134
+ * subscription gate's `stop -> poll -> start` pattern safe even if
135
+ * something inside the gate accidentally calls `startRuntime` again.
136
+ */
137
+ startRuntime(getBusy: () => boolean): void;
138
+ /**
139
+ * Stop the runtime heartbeat loop and wait for any in-flight send to
140
+ * finish. Used by graceful shutdown and by the subscription gate
141
+ * before it takes over with its own 10s polling cadence.
82
142
  *
83
- * There are two independent heartbeat sinks here:
84
- * - The on-disk heartbeat file is consumed by the external cron watchdog and
85
- * must update even when cloud/runtime heartbeat credentials are absent.
86
- * - The onboarding service heartbeat keeps the dashboard up to date when a
87
- * service client is configured.
143
+ * IMPORTANT: clearing the timer is not enough on its own — a tick
144
+ * that is already mid-send would still re-arm itself when it
145
+ * completes (see `runRuntimeTick`). We null `getBusy` so the
146
+ * `runRuntimeTick` re-arm guard short-circuits, and `nudge()`
147
+ * (which keys off `getBusy`) becomes a no-op until `startRuntime`
148
+ * is called again. `startRuntime` is the only caller that brings
149
+ * `getBusy` back, so the lifecycle is start/stop-symmetric.
88
150
  */
89
- startBusyInterval(): void;
151
+ stopRuntime(): Promise<void>;
90
152
  /**
91
- * Stop the busy interval and send a final end-of-cycle heartbeat
92
- * to reflect idle state immediately.
153
+ * Fire an out-of-band heartbeat right now via the same mutex path
154
+ * the runtime loop uses. Used by the main loop on busy<->idle
155
+ * transitions to flatten dashboard latency without waiting for the
156
+ * next scheduled tick (up to 5min in the idle case).
93
157
  */
94
- stopBusyInterval(): void;
158
+ nudge(): void;
159
+ private scheduleNextTick;
160
+ private runRuntimeTick;
95
161
  }
96
162
  //# sourceMappingURL=heartbeat-manager.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"heartbeat-manager.d.ts","sourceRoot":"","sources":["../../src/agent/heartbeat-manager.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAEL,KAAK,oBAAoB,EAEzB,KAAK,kBAAkB,EACxB,MAAM,4CAA4C,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAE5D,OAAO,EAA4D,KAAK,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAavH,MAAM,WAAW,uBAAuB;IACtC;;;;;;;;;;OAUG;IACH,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CAC9C;AAsCD,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAwC;IACtD,QAAQ,CAAC,iBAAiB,EAAE,iBAAiB,CAAC;IAC9C,OAAO,CAAC,YAAY,CAA+C;IACnE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmB;IAC1C,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,uBAAuB,CAA8B;IAC7D,OAAO,CAAC,iBAAiB,CAA8B;IACvD,OAAO,CAAC,mBAAmB,CAAqB;IAChD;;;;;OAKG;IACH,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA0B;gBAE/C,MAAM,EAAE,gBAAgB,EAAE,OAAO,CAAC,EAAE,uBAAuB;IAYvE,oFAAoF;IACpF,OAAO,CAAC,YAAY;IAoCpB;;;;OAIG;IACG,IAAI,CACR,cAAc,EAAE,cAAc,EAC9B,cAAc,EAAE,MAAM,GAAG,SAAS,EAClC,YAAY,EAAE,kBAAkB,GAAG,IAAI,GACtC,OAAO,CAAC,IAAI,CAAC;IAgFhB,4CAA4C;IAC5C,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,uEAAuE;IACvE,IAAI,sBAAsB,IAAI,kBAAkB,CAE/C;IAED,sFAAsF;IACtF,IAAI,gBAAgB,IAAI,oBAAoB,EAAE,CAE7C;IAED,wFAAwF;IACxF,IAAI,kBAAkB,IAAI,MAAM,GAAG,SAAS,CAE3C;IAED;;;OAGG;IACG,gBAAgB,IAAI,OAAO,CAAC;QAChC,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QACxB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;QAChC,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,GAAG,IAAI,CAAC;IAKT;;;OAGG;IACG,MAAM,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAgC1C;;;OAGG;IACG,4BAA4B,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAoBjE;;;;;;;;OAQG;IACH,iBAAiB,IAAI,IAAI;IAYzB;;;OAGG;IACH,gBAAgB,IAAI,IAAI;CAYzB"}
1
+ {"version":3,"file":"heartbeat-manager.d.ts","sourceRoot":"","sources":["../../src/agent/heartbeat-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAEL,KAAK,oBAAoB,EAGzB,KAAK,kBAAkB,EACxB,MAAM,4CAA4C,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAE5D,OAAO,EAA4D,KAAK,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAavH,MAAM,WAAW,uBAAuB;IACtC;;;;;;;;;;OAUG;IACH,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CAC9C;AA+CD,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAwC;IACtD,QAAQ,CAAC,iBAAiB,EAAE,iBAAiB,CAAC;IAC9C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmB;IAC1C,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,uBAAuB,CAA8B;IAC7D,OAAO,CAAC,iBAAiB,CAA8B;IACvD,OAAO,CAAC,mBAAmB,CAAqB;IAChD;;;;;OAKG;IACH,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA0B;IAG3D,sEAAsE;IACtE,OAAO,CAAC,YAAY,CAA8C;IAClE,qEAAqE;IACrE,OAAO,CAAC,OAAO,CAAgC;IAC/C;;;;OAIG;IACH,OAAO,CAAC,SAAS,CAAoC;gBAEzC,MAAM,EAAE,gBAAgB,EAAE,OAAO,CAAC,EAAE,uBAAuB;IAYvE,oFAAoF;IACpF,OAAO,CAAC,YAAY;IAoCpB;;;;;;;;;;;;;;;OAeG;YACW,aAAa;IAsB3B;;;OAGG;YACW,OAAO;IAsErB;;;;OAIG;IACG,IAAI,CACR,cAAc,EAAE,cAAc,EAC9B,cAAc,EAAE,MAAM,GAAG,SAAS,EAClC,YAAY,EAAE,kBAAkB,GAAG,IAAI,GACtC,OAAO,CAAC,IAAI,CAAC;IAoEhB,4CAA4C;IAC5C,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,uEAAuE;IACvE,IAAI,sBAAsB,IAAI,kBAAkB,CAE/C;IAED,sFAAsF;IACtF,IAAI,gBAAgB,IAAI,oBAAoB,EAAE,CAE7C;IAED,wFAAwF;IACxF,IAAI,kBAAkB,IAAI,MAAM,GAAG,SAAS,CAE3C;IAED;;;OAGG;IACG,gBAAgB,IAAI,OAAO,CAAC;QAChC,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QACxB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;QAChC,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,GAAG,IAAI,CAAC;IAKT;;;OAGG;IACG,4BAA4B,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAMjE;;;;;;;;;;;;;;OAcG;IACH,YAAY,CAAC,OAAO,EAAE,MAAM,OAAO,GAAG,IAAI;IAY1C;;;;;;;;;;;;OAYG;IACG,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAYlC;;;;;OAKG;IACH,KAAK,IAAI,IAAI;IAOb,OAAO,CAAC,gBAAgB;YAaV,cAAc;CAY7B"}
@@ -1,9 +1,25 @@
1
1
  /**
2
- * HeartbeatManager — encapsulates all runtime heartbeat interactions with
3
- * the onboarding service: startup validation, per-wake heartbeats, busy
4
- * keep-alive intervals, and end-of-cycle status updates.
2
+ * HeartbeatManager — owns the always-on heartbeat lifecycle.
5
3
  *
6
- * Extracted from loop.ts to reduce the number of concerns in the main loop.
4
+ * Heartbeats are intentionally decoupled from the wake/sleep cycle so the
5
+ * onboarding service sees an accurate liveness signal even during long
6
+ * sleeps (notably the 2-hour overnight interval). The runtime loop is a
7
+ * single recursive `setTimeout` whose cadence adapts to `agentState.busy`:
8
+ *
9
+ * - busy === true -> 30s (preserves dashboard precision during work)
10
+ * - busy === false -> 5min (idle keep-alive)
11
+ *
12
+ * Every heartbeat (startup, runtime tick, subscription gate, nudge)
13
+ * funnels through one private `sendHeartbeat()` method that owns the
14
+ * mutex, payload build, and full response handling (subscription,
15
+ * billing, shared keys, credential bundle, pending commands, ack
16
+ * confirm/requeue). This eliminates the previously scattered duplicate
17
+ * response-handling blocks in init/onWake/sendHeartbeatForSubscription.
18
+ *
19
+ * The local on-disk heartbeat file is a separate liveness signal
20
+ * consumed by the in-process child watchdog (see heartbeat-watchdog.ts).
21
+ * It is refreshed at the top of every send, so it stays fresh even when
22
+ * cloud heartbeat credentials are absent.
7
23
  */
8
24
  import { OnboardingServiceClient, } from "../onboarding/onboarding-service-client.js";
9
25
  import { CommandDispatcher } from "./command-dispatcher.js";
@@ -20,7 +36,15 @@ import { resetArchiveConfigCache } from "./image-archive.js";
20
36
  import { CredentialBundleHandler } from "./credential-bundle-handler.js";
21
37
  import { writeHeartbeatFile } from "./heartbeat-file.js";
22
38
  import { logger } from "../logger.js";
39
+ /** Cadence while the agent is processing a wake cycle. */
23
40
  const BUSY_HEARTBEAT_INTERVAL_MS = 30_000;
41
+ /**
42
+ * Cadence while the agent is idle (sleeping between wake cycles or
43
+ * waiting on input). Sized so two missed idle heartbeats + slack stay
44
+ * inside the server's `HEARTBEAT_ONLINE_MS` threshold (10 min) — see
45
+ * `services/onboarding/src/lib/db.ts` for the corresponding constant.
46
+ */
47
+ const IDLE_HEARTBEAT_INTERVAL_MS = 5 * 60_000;
24
48
  function applySharedKeysFromHeartbeat(config, _channelManager, sharedKeys) {
25
49
  if (!sharedKeys)
26
50
  return false;
@@ -44,7 +68,6 @@ function applySharedKeysFromHeartbeat(config, _channelManager, sharedKeys) {
44
68
  export class HeartbeatManager {
45
69
  client = null;
46
70
  commandDispatcher;
47
- busyInterval = null;
48
71
  config;
49
72
  channelManager = null;
50
73
  _lastSubscriptionStatus = "skip";
@@ -57,6 +80,17 @@ export class HeartbeatManager {
57
80
  * building the next payload.
58
81
  */
59
82
  credentialBundle;
83
+ // ── Runtime loop state ──
84
+ /** Recursive setTimeout handle. `null` when the loop is not armed. */
85
+ runtimeTimer = null;
86
+ /** Provider for current `agentState.busy`. Set by `startRuntime`. */
87
+ getBusy = null;
88
+ /**
89
+ * Mutex tail — every `sendHeartbeat` awaits this then replaces it
90
+ * with the new in-flight promise so concurrent callers serialise.
91
+ * Initialised to a resolved promise so the first send doesn't block.
92
+ */
93
+ sendMutex = Promise.resolve();
60
94
  constructor(config, options) {
61
95
  this.config = config;
62
96
  this.credentialBundle = new CredentialBundleHandler({
@@ -107,6 +141,109 @@ export class HeartbeatManager {
107
141
  }
108
142
  return payload;
109
143
  }
144
+ /**
145
+ * The single place every heartbeat goes through.
146
+ *
147
+ * - Always refreshes the on-disk heartbeat file (cheap, even when no
148
+ * onboarding-service client is configured).
149
+ * - Mutex-serialises concurrent callers (busy ticks, idle ticks,
150
+ * subscription gate polls, nudges) so command acks cannot be
151
+ * double-submitted and response handlers cannot interleave.
152
+ * - In `strict` mode, errors are rethrown after re-queuing acks so
153
+ * `init()` can surface auth failures and disable the client. In
154
+ * non-strict mode errors are caught and acks are requeued for the
155
+ * next attempt, identical to the previous best-effort behaviour.
156
+ * - Does NOT wake the main loop. The `notify` command handler in
157
+ * loop.ts is responsible for waking after it enqueues the message;
158
+ * waking from inside `sendHeartbeat` would race that handler.
159
+ */
160
+ async sendHeartbeat(options) {
161
+ // Acquire the mutex by waiting on the previous tail and installing
162
+ // a new one. Even if `prev` rejected we still want to proceed —
163
+ // `await prev` swallowing nothing here would allow an unhandled
164
+ // rejection from a previous send to propagate out of an unrelated
165
+ // call, so guard with `.catch(() => undefined)`.
166
+ const prev = this.sendMutex;
167
+ let release;
168
+ this.sendMutex = new Promise((resolve) => {
169
+ release = resolve;
170
+ });
171
+ try {
172
+ await prev.catch(() => undefined);
173
+ return await this.runSend(options);
174
+ }
175
+ finally {
176
+ release();
177
+ }
178
+ }
179
+ /**
180
+ * Body of a single heartbeat send, executed under the mutex. Split
181
+ * out from `sendHeartbeat` so the locking shell is a thin wrapper.
182
+ */
183
+ async runSend(options) {
184
+ // Refresh the local liveness file before any network work. This is
185
+ // unconditional and runs even when no client is configured, so the
186
+ // child watchdog (when enabled) sees a heartbeat regardless.
187
+ writeHeartbeatFile();
188
+ if (!this.client)
189
+ return null;
190
+ const acks = this.commandDispatcher.drainAcks();
191
+ const payload = this.buildPayload(options.busy);
192
+ if (acks.length > 0)
193
+ payload.commandAcks = acks;
194
+ let resp;
195
+ try {
196
+ resp = options.strict
197
+ ? await this.client.heartbeatStrict(payload)
198
+ : await this.client.heartbeat(payload);
199
+ }
200
+ catch (err) {
201
+ // Put undelivered acks back so the next heartbeat can retry them.
202
+ if (acks.length > 0)
203
+ this.commandDispatcher.requeueAcks(acks);
204
+ if (options.strict) {
205
+ // Strict callers (init) want auth failures to bubble up so they
206
+ // can disable the client and notify the owner.
207
+ throw err;
208
+ }
209
+ // Non-strict: best-effort, swallow.
210
+ return null;
211
+ }
212
+ // The non-strict client swallows network/HTTP errors and returns
213
+ // `null` instead of throwing, so we must treat a null response as
214
+ // "delivery failed" and requeue acks. Without this, an offline
215
+ // server window silently drops every command ack drained during
216
+ // it. (heartbeatStrict only ever returns null when the server
217
+ // reports a non-auth non-2xx, which is the same delivery-failed
218
+ // case — strict callers care about auth, not delivery.)
219
+ if (resp === null) {
220
+ if (acks.length > 0)
221
+ this.commandDispatcher.requeueAcks(acks);
222
+ return null;
223
+ }
224
+ // ── Response side-effects (single source of truth) ──
225
+ // `resp` is non-null past the guard above.
226
+ if (resp.subscriptionStatus) {
227
+ this._lastSubscriptionStatus = resp.subscriptionStatus;
228
+ }
229
+ if (resp.billingPlans) {
230
+ this._lastBillingPlans = resp.billingPlans;
231
+ }
232
+ if (resp.billingMessage !== undefined) {
233
+ this._lastBillingMessage = resp.billingMessage;
234
+ }
235
+ if (applySharedKeysFromHeartbeat(this.config, this.channelManager, resp.sharedKeys)) {
236
+ logger.debug("Shared keys updated from heartbeat");
237
+ }
238
+ this.credentialBundle.handle(resp.credentialBundle);
239
+ // Acks were delivered successfully — clear their completed-set entries.
240
+ if (acks.length > 0)
241
+ this.commandDispatcher.confirmAcksDelivered(acks);
242
+ if (resp.pendingCommands && resp.pendingCommands.length > 0) {
243
+ this.commandDispatcher.dispatch(resp.pendingCommands);
244
+ }
245
+ return resp;
246
+ }
110
247
  /**
111
248
  * Initialize the heartbeat client and validate the API key.
112
249
  * Should be called once at startup. If validation fails, heartbeats
@@ -126,15 +263,12 @@ export class HeartbeatManager {
126
263
  logger.system(`Queued auto-ack for upgrade command ${justUpgraded.commandId} (${justUpgraded.fromVersion} → ${justUpgraded.toVersion})`);
127
264
  }
128
265
  if (!this.config.onboardingServiceUrl || !this.config.visionclawServiceApiKey) {
266
+ // No client to validate; still refresh the local heartbeat file so
267
+ // the watchdog sees a fresh timestamp from process start.
268
+ await this.sendHeartbeat({ busy: false });
129
269
  return;
130
270
  }
131
271
  this.client = new OnboardingServiceClient(this.config.onboardingServiceUrl, this.config.agentName, this.config.visionclawServiceApiKey);
132
- // The startup heartbeat carries whatever signature we have on disk
133
- // (or none, on a fresh install). The server returns a
134
- // `credentialBundle` only on signature mismatch, so the steady-state
135
- // restart costs nothing extra; first installs and recovery cases
136
- // get the full bundle automatically.
137
- const startupPayload = this.buildPayload(false);
138
272
  // Register billing handler for bundle purchases.
139
273
  // Subscription payment is handled by the subscription gate (subscription-gate.ts),
140
274
  // not via a command — the gate reads plans from the heartbeat response directly.
@@ -142,22 +276,14 @@ export class HeartbeatManager {
142
276
  const billing = new BillingHandler(channelManager, telegramChatId, this.client);
143
277
  this.commandDispatcher.registerHandler("bundle_purchase", billing.handleBundlePurchase);
144
278
  }
279
+ // The startup heartbeat carries whatever signature we have on disk
280
+ // (or none, on a fresh install). The server returns a
281
+ // `credentialBundle` only on signature mismatch, so the steady-state
282
+ // restart costs nothing extra; first installs and recovery cases
283
+ // get the full bundle automatically.
145
284
  try {
146
- const startupResp = await this.client.heartbeatStrict(startupPayload);
285
+ await this.sendHeartbeat({ busy: false, strict: true });
147
286
  logger.system("Runtime heartbeat: initial key validation succeeded");
148
- if (startupResp?.subscriptionStatus) {
149
- this._lastSubscriptionStatus = startupResp.subscriptionStatus;
150
- }
151
- if (startupResp?.billingPlans) {
152
- this._lastBillingPlans = startupResp.billingPlans;
153
- }
154
- if (startupResp?.billingMessage !== undefined) {
155
- this._lastBillingMessage = startupResp.billingMessage;
156
- }
157
- if (applySharedKeysFromHeartbeat(this.config, this.channelManager, startupResp?.sharedKeys)) {
158
- logger.debug("Shared keys applied from startup heartbeat");
159
- }
160
- this.credentialBundle.handle(startupResp?.credentialBundle);
161
287
  }
162
288
  catch (err) {
163
289
  logger.err(`Runtime heartbeat: API key validation failed: ${err instanceof Error ? err.message : String(err)}`);
@@ -197,45 +323,6 @@ export class HeartbeatManager {
197
323
  return null;
198
324
  return this.client.getBillingPortal();
199
325
  }
200
- /**
201
- * Send a heartbeat at the start of each wake cycle.
202
- * Dispatches any pending commands from the server and applies shared keys.
203
- */
204
- async onWake(busy) {
205
- if (!this.client)
206
- return;
207
- const acks = this.commandDispatcher.drainAcks();
208
- try {
209
- const payload = this.buildPayload(busy);
210
- if (acks.length > 0)
211
- payload.commandAcks = acks;
212
- const resp = await this.client.heartbeat(payload);
213
- if (resp?.subscriptionStatus) {
214
- this._lastSubscriptionStatus = resp.subscriptionStatus;
215
- }
216
- if (resp?.billingPlans) {
217
- this._lastBillingPlans = resp.billingPlans;
218
- }
219
- if (resp?.billingMessage !== undefined) {
220
- this._lastBillingMessage = resp.billingMessage;
221
- }
222
- // Acks were delivered successfully — clear their completed-set entries.
223
- if (acks.length > 0)
224
- this.commandDispatcher.confirmAcksDelivered(acks);
225
- if (resp?.pendingCommands && resp.pendingCommands.length > 0) {
226
- this.commandDispatcher.dispatch(resp.pendingCommands);
227
- }
228
- if (applySharedKeysFromHeartbeat(this.config, this.channelManager, resp?.sharedKeys)) {
229
- logger.debug("Shared keys updated from heartbeat");
230
- }
231
- this.credentialBundle.handle(resp?.credentialBundle);
232
- }
233
- catch {
234
- // Put undelivered acks back so the next heartbeat can retry them.
235
- if (acks.length > 0)
236
- this.commandDispatcher.requeueAcks(acks);
237
- }
238
- }
239
326
  /**
240
327
  * Send a single heartbeat and return the subscription status from the response.
241
328
  * Used by the subscription gate for fast-polling (10s interval).
@@ -243,57 +330,96 @@ export class HeartbeatManager {
243
330
  async sendHeartbeatForSubscription() {
244
331
  if (!this.client)
245
332
  return this._lastSubscriptionStatus;
246
- try {
247
- const resp = await this.client.heartbeat(this.buildPayload(false));
248
- if (resp?.subscriptionStatus) {
249
- this._lastSubscriptionStatus = resp.subscriptionStatus;
250
- }
251
- if (resp?.billingPlans) {
252
- this._lastBillingPlans = resp.billingPlans;
253
- }
254
- if (resp?.billingMessage !== undefined) {
255
- this._lastBillingMessage = resp.billingMessage;
256
- }
257
- }
258
- catch {
259
- // best-effort — keep last known status
260
- }
333
+ await this.sendHeartbeat({ busy: false });
261
334
  return this._lastSubscriptionStatus;
262
335
  }
263
336
  /**
264
- * Start periodic keep-alives while the agent is busy processing a cycle.
337
+ * Arm the always-on runtime heartbeat loop.
265
338
  *
266
- * There are two independent heartbeat sinks here:
267
- * - The on-disk heartbeat file is consumed by the external cron watchdog and
268
- * must update even when cloud/runtime heartbeat credentials are absent.
269
- * - The onboarding service heartbeat keeps the dashboard up to date when a
270
- * service client is configured.
339
+ * Called once at process startup, after `agentState` is initialised so
340
+ * the `getBusy` provider can read the live busy flag. Does NOT fire
341
+ * an immediate heartbeat `init()` already sent the strict startup
342
+ * heartbeat, and an immediate runtime tick would just duplicate it.
343
+ * State-change latency is covered by `nudge()`, not by an immediate
344
+ * fire.
345
+ *
346
+ * Calling `startRuntime` while the loop is already armed is a no-op
347
+ * apart from refreshing the `getBusy` reference; this makes the
348
+ * subscription gate's `stop -> poll -> start` pattern safe even if
349
+ * something inside the gate accidentally calls `startRuntime` again.
271
350
  */
272
- startBusyInterval() {
273
- const hbClient = this.client;
274
- this.busyInterval = setInterval(() => {
275
- // Refresh the on-disk heartbeat file so the external watchdog does not
276
- // mistake a long-but-healthy wake cycle for a blocked event loop.
277
- writeHeartbeatFile();
278
- hbClient?.heartbeat(this.buildPayload(true)).catch(() => {
279
- /* best-effort */
280
- });
281
- }, BUSY_HEARTBEAT_INTERVAL_MS);
351
+ startRuntime(getBusy) {
352
+ this.getBusy = getBusy;
353
+ // Synchronously refresh the local heartbeat file so a freshly armed
354
+ // watchdog (when enabled) sees a current timestamp from the moment
355
+ // the runtime loop is in charge.
356
+ writeHeartbeatFile();
357
+ if (this.runtimeTimer !== null)
358
+ return;
359
+ this.scheduleNextTick();
282
360
  }
283
361
  /**
284
- * Stop the busy interval and send a final end-of-cycle heartbeat
285
- * to reflect idle state immediately.
362
+ * Stop the runtime heartbeat loop and wait for any in-flight send to
363
+ * finish. Used by graceful shutdown and by the subscription gate
364
+ * before it takes over with its own 10s polling cadence.
365
+ *
366
+ * IMPORTANT: clearing the timer is not enough on its own — a tick
367
+ * that is already mid-send would still re-arm itself when it
368
+ * completes (see `runRuntimeTick`). We null `getBusy` so the
369
+ * `runRuntimeTick` re-arm guard short-circuits, and `nudge()`
370
+ * (which keys off `getBusy`) becomes a no-op until `startRuntime`
371
+ * is called again. `startRuntime` is the only caller that brings
372
+ * `getBusy` back, so the lifecycle is start/stop-symmetric.
286
373
  */
287
- stopBusyInterval() {
288
- if (this.busyInterval !== null) {
289
- clearInterval(this.busyInterval);
290
- this.busyInterval = null;
374
+ async stopRuntime() {
375
+ if (this.runtimeTimer !== null) {
376
+ clearTimeout(this.runtimeTimer);
377
+ this.runtimeTimer = null;
291
378
  }
292
- if (this.client) {
293
- this.client.heartbeat(this.buildPayload(false)).catch(() => {
294
- /* best-effort */
295
- });
379
+ this.getBusy = null;
380
+ // Drain any in-flight send so the caller can rely on a quiet
381
+ // post-stop state (no surprise heartbeats firing during gate
382
+ // polling or during graceful shutdown).
383
+ await this.sendMutex.catch(() => undefined);
384
+ }
385
+ /**
386
+ * Fire an out-of-band heartbeat right now via the same mutex path
387
+ * the runtime loop uses. Used by the main loop on busy<->idle
388
+ * transitions to flatten dashboard latency without waiting for the
389
+ * next scheduled tick (up to 5min in the idle case).
390
+ */
391
+ nudge() {
392
+ if (!this.getBusy)
393
+ return;
394
+ void this.sendHeartbeat({ busy: this.getBusy() }).catch(() => {
395
+ /* best-effort */
396
+ });
397
+ }
398
+ scheduleNextTick() {
399
+ const interval = this.getBusy?.() === true
400
+ ? BUSY_HEARTBEAT_INTERVAL_MS
401
+ : IDLE_HEARTBEAT_INTERVAL_MS;
402
+ this.runtimeTimer = setTimeout(() => {
403
+ // Detach from the timer slot before sending so a re-entrant
404
+ // `startRuntime` (e.g. subscription gate teardown racing the
405
+ // tick fire) sees `runtimeTimer === null` and re-arms cleanly.
406
+ this.runtimeTimer = null;
407
+ void this.runRuntimeTick();
408
+ }, interval);
409
+ }
410
+ async runRuntimeTick() {
411
+ try {
412
+ await this.sendHeartbeat({ busy: this.getBusy?.() === true });
296
413
  }
414
+ catch {
415
+ // sendHeartbeat already logs / requeues on error in non-strict mode;
416
+ // belt-and-suspenders catch in case future strict ticks slip in.
417
+ }
418
+ // If the loop was stopped (or about to be stopped) during the
419
+ // send, don't re-arm.
420
+ if (this.getBusy === null)
421
+ return;
422
+ this.scheduleNextTick();
297
423
  }
298
424
  }
299
425
  //# sourceMappingURL=heartbeat-manager.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"heartbeat-manager.js","sourceRoot":"","sources":["../../src/agent/heartbeat-manager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"heartbeat-manager.js","sourceRoot":"","sources":["../../src/agent/heartbeat-manager.ts"],"names":[],"mappings":"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"}