@sequence0/blockclaw 2.0.0

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 (190) hide show
  1. package/README.md +97 -0
  2. package/dist/agent/binary.d.ts +15 -0
  3. package/dist/agent/binary.d.ts.map +1 -0
  4. package/dist/agent/binary.js +172 -0
  5. package/dist/agent/binary.js.map +1 -0
  6. package/dist/agent/chains.d.ts +26 -0
  7. package/dist/agent/chains.d.ts.map +1 -0
  8. package/dist/agent/chains.js +123 -0
  9. package/dist/agent/chains.js.map +1 -0
  10. package/dist/agent/client.d.ts +484 -0
  11. package/dist/agent/client.d.ts.map +1 -0
  12. package/dist/agent/client.js +448 -0
  13. package/dist/agent/client.js.map +1 -0
  14. package/dist/agent/config.d.ts +75 -0
  15. package/dist/agent/config.d.ts.map +1 -0
  16. package/dist/agent/config.js +133 -0
  17. package/dist/agent/config.js.map +1 -0
  18. package/dist/agent/process.d.ts +36 -0
  19. package/dist/agent/process.d.ts.map +1 -0
  20. package/dist/agent/process.js +208 -0
  21. package/dist/agent/process.js.map +1 -0
  22. package/dist/agent/wallet.d.ts +43 -0
  23. package/dist/agent/wallet.d.ts.map +1 -0
  24. package/dist/agent/wallet.js +146 -0
  25. package/dist/agent/wallet.js.map +1 -0
  26. package/dist/ai/brain.d.ts +21 -0
  27. package/dist/ai/brain.d.ts.map +1 -0
  28. package/dist/ai/brain.js +117 -0
  29. package/dist/ai/brain.js.map +1 -0
  30. package/dist/ai/prompts.d.ts +15 -0
  31. package/dist/ai/prompts.d.ts.map +1 -0
  32. package/dist/ai/prompts.js +67 -0
  33. package/dist/ai/prompts.js.map +1 -0
  34. package/dist/ai/rules.d.ts +19 -0
  35. package/dist/ai/rules.d.ts.map +1 -0
  36. package/dist/ai/rules.js +143 -0
  37. package/dist/ai/rules.js.map +1 -0
  38. package/dist/core/detector.d.ts +16 -0
  39. package/dist/core/detector.d.ts.map +1 -0
  40. package/dist/core/detector.js +90 -0
  41. package/dist/core/detector.js.map +1 -0
  42. package/dist/core/healer.d.ts +62 -0
  43. package/dist/core/healer.d.ts.map +1 -0
  44. package/dist/core/healer.js +355 -0
  45. package/dist/core/healer.js.map +1 -0
  46. package/dist/core/heartbeat.d.ts +67 -0
  47. package/dist/core/heartbeat.d.ts.map +1 -0
  48. package/dist/core/heartbeat.js +426 -0
  49. package/dist/core/heartbeat.js.map +1 -0
  50. package/dist/core/memory.d.ts +57 -0
  51. package/dist/core/memory.d.ts.map +1 -0
  52. package/dist/core/memory.js +149 -0
  53. package/dist/core/memory.js.map +1 -0
  54. package/dist/core/updater.d.ts +16 -0
  55. package/dist/core/updater.d.ts.map +1 -0
  56. package/dist/core/updater.js +107 -0
  57. package/dist/core/updater.js.map +1 -0
  58. package/dist/index.d.ts +3 -0
  59. package/dist/index.d.ts.map +1 -0
  60. package/dist/index.js +97 -0
  61. package/dist/index.js.map +1 -0
  62. package/dist/interface/commands/ask.d.ts +3 -0
  63. package/dist/interface/commands/ask.d.ts.map +1 -0
  64. package/dist/interface/commands/ask.js +39 -0
  65. package/dist/interface/commands/ask.js.map +1 -0
  66. package/dist/interface/commands/backup.d.ts +3 -0
  67. package/dist/interface/commands/backup.d.ts.map +1 -0
  68. package/dist/interface/commands/backup.js +576 -0
  69. package/dist/interface/commands/backup.js.map +1 -0
  70. package/dist/interface/commands/config.d.ts +3 -0
  71. package/dist/interface/commands/config.d.ts.map +1 -0
  72. package/dist/interface/commands/config.js +107 -0
  73. package/dist/interface/commands/config.js.map +1 -0
  74. package/dist/interface/commands/daemon.d.ts +3 -0
  75. package/dist/interface/commands/daemon.d.ts.map +1 -0
  76. package/dist/interface/commands/daemon.js +162 -0
  77. package/dist/interface/commands/daemon.js.map +1 -0
  78. package/dist/interface/commands/doctor.d.ts +3 -0
  79. package/dist/interface/commands/doctor.d.ts.map +1 -0
  80. package/dist/interface/commands/doctor.js +143 -0
  81. package/dist/interface/commands/doctor.js.map +1 -0
  82. package/dist/interface/commands/earnings.d.ts +3 -0
  83. package/dist/interface/commands/earnings.d.ts.map +1 -0
  84. package/dist/interface/commands/earnings.js +165 -0
  85. package/dist/interface/commands/earnings.js.map +1 -0
  86. package/dist/interface/commands/health.d.ts +3 -0
  87. package/dist/interface/commands/health.d.ts.map +1 -0
  88. package/dist/interface/commands/health.js +48 -0
  89. package/dist/interface/commands/health.js.map +1 -0
  90. package/dist/interface/commands/history.d.ts +3 -0
  91. package/dist/interface/commands/history.d.ts.map +1 -0
  92. package/dist/interface/commands/history.js +113 -0
  93. package/dist/interface/commands/history.js.map +1 -0
  94. package/dist/interface/commands/info.d.ts +3 -0
  95. package/dist/interface/commands/info.d.ts.map +1 -0
  96. package/dist/interface/commands/info.js +82 -0
  97. package/dist/interface/commands/info.js.map +1 -0
  98. package/dist/interface/commands/logs.d.ts +3 -0
  99. package/dist/interface/commands/logs.d.ts.map +1 -0
  100. package/dist/interface/commands/logs.js +98 -0
  101. package/dist/interface/commands/logs.js.map +1 -0
  102. package/dist/interface/commands/menu.d.ts +4 -0
  103. package/dist/interface/commands/menu.d.ts.map +1 -0
  104. package/dist/interface/commands/menu.js +156 -0
  105. package/dist/interface/commands/menu.js.map +1 -0
  106. package/dist/interface/commands/receive.d.ts +3 -0
  107. package/dist/interface/commands/receive.d.ts.map +1 -0
  108. package/dist/interface/commands/receive.js +81 -0
  109. package/dist/interface/commands/receive.js.map +1 -0
  110. package/dist/interface/commands/register.d.ts +3 -0
  111. package/dist/interface/commands/register.d.ts.map +1 -0
  112. package/dist/interface/commands/register.js +231 -0
  113. package/dist/interface/commands/register.js.map +1 -0
  114. package/dist/interface/commands/restart.d.ts +3 -0
  115. package/dist/interface/commands/restart.d.ts.map +1 -0
  116. package/dist/interface/commands/restart.js +154 -0
  117. package/dist/interface/commands/restart.js.map +1 -0
  118. package/dist/interface/commands/send.d.ts +3 -0
  119. package/dist/interface/commands/send.d.ts.map +1 -0
  120. package/dist/interface/commands/send.js +108 -0
  121. package/dist/interface/commands/send.js.map +1 -0
  122. package/dist/interface/commands/service.d.ts +3 -0
  123. package/dist/interface/commands/service.d.ts.map +1 -0
  124. package/dist/interface/commands/service.js +474 -0
  125. package/dist/interface/commands/service.js.map +1 -0
  126. package/dist/interface/commands/setup.d.ts +5 -0
  127. package/dist/interface/commands/setup.d.ts.map +1 -0
  128. package/dist/interface/commands/setup.js +410 -0
  129. package/dist/interface/commands/setup.js.map +1 -0
  130. package/dist/interface/commands/start.d.ts +3 -0
  131. package/dist/interface/commands/start.d.ts.map +1 -0
  132. package/dist/interface/commands/start.js +171 -0
  133. package/dist/interface/commands/start.js.map +1 -0
  134. package/dist/interface/commands/status.d.ts +3 -0
  135. package/dist/interface/commands/status.d.ts.map +1 -0
  136. package/dist/interface/commands/status.js +77 -0
  137. package/dist/interface/commands/status.js.map +1 -0
  138. package/dist/interface/commands/stop.d.ts +3 -0
  139. package/dist/interface/commands/stop.d.ts.map +1 -0
  140. package/dist/interface/commands/stop.js +62 -0
  141. package/dist/interface/commands/stop.js.map +1 -0
  142. package/dist/interface/commands/update.d.ts +3 -0
  143. package/dist/interface/commands/update.d.ts.map +1 -0
  144. package/dist/interface/commands/update.js +53 -0
  145. package/dist/interface/commands/update.js.map +1 -0
  146. package/dist/interface/commands/wallet.d.ts +3 -0
  147. package/dist/interface/commands/wallet.d.ts.map +1 -0
  148. package/dist/interface/commands/wallet.js +446 -0
  149. package/dist/interface/commands/wallet.js.map +1 -0
  150. package/dist/interface/commands/webhook.d.ts +3 -0
  151. package/dist/interface/commands/webhook.d.ts.map +1 -0
  152. package/dist/interface/commands/webhook.js +99 -0
  153. package/dist/interface/commands/webhook.js.map +1 -0
  154. package/dist/interface/commands/withdraw.d.ts +3 -0
  155. package/dist/interface/commands/withdraw.d.ts.map +1 -0
  156. package/dist/interface/commands/withdraw.js +261 -0
  157. package/dist/interface/commands/withdraw.js.map +1 -0
  158. package/dist/interface/interactive.d.ts +43 -0
  159. package/dist/interface/interactive.d.ts.map +1 -0
  160. package/dist/interface/interactive.js +276 -0
  161. package/dist/interface/interactive.js.map +1 -0
  162. package/dist/interface/logo.d.ts +2 -0
  163. package/dist/interface/logo.d.ts.map +1 -0
  164. package/dist/interface/logo.js +21 -0
  165. package/dist/interface/logo.js.map +1 -0
  166. package/dist/interface/webhooks.d.ts +19 -0
  167. package/dist/interface/webhooks.d.ts.map +1 -0
  168. package/dist/interface/webhooks.js +172 -0
  169. package/dist/interface/webhooks.js.map +1 -0
  170. package/dist/utils/format.d.ts +19 -0
  171. package/dist/utils/format.d.ts.map +1 -0
  172. package/dist/utils/format.js +107 -0
  173. package/dist/utils/format.js.map +1 -0
  174. package/dist/utils/logger.d.ts +20 -0
  175. package/dist/utils/logger.d.ts.map +1 -0
  176. package/dist/utils/logger.js +47 -0
  177. package/dist/utils/logger.js.map +1 -0
  178. package/dist/utils/paths.d.ts +35 -0
  179. package/dist/utils/paths.d.ts.map +1 -0
  180. package/dist/utils/paths.js +45 -0
  181. package/dist/utils/paths.js.map +1 -0
  182. package/dist/utils/platform.d.ts +26 -0
  183. package/dist/utils/platform.d.ts.map +1 -0
  184. package/dist/utils/platform.js +72 -0
  185. package/dist/utils/platform.js.map +1 -0
  186. package/dist/version.d.ts +3 -0
  187. package/dist/version.d.ts.map +1 -0
  188. package/dist/version.js +3 -0
  189. package/dist/version.js.map +1 -0
  190. package/package.json +67 -0
@@ -0,0 +1,426 @@
1
+ import os from "node:os";
2
+ import fs from "node:fs";
3
+ import dns from "node:dns/promises";
4
+ import { readBlockclawConfig, readAgentConfig } from "../agent/config.js";
5
+ import { logger } from "../utils/logger.js";
6
+ import { EVENTS_LOG, ensureBlockclawDir } from "../utils/paths.js";
7
+ import { getDiskUsage } from "../utils/platform.js";
8
+ // ---------------------------------------------------------------------------
9
+ // Constants
10
+ // ---------------------------------------------------------------------------
11
+ const DEFAULT_INTERVAL_MS = 30_000; // 30 seconds
12
+ const CONSECUTIVE_FAILURES_THRESHOLD = 3;
13
+ const DISK_USAGE_WARNING_PERCENT = 95;
14
+ const MEMORY_USAGE_WARNING_PERCENT = 90;
15
+ const RPC_STALE_THRESHOLD = 3; // consecutive checks with same block number
16
+ const DEFAULT_RPC_URLS = {
17
+ testnet: "https://testnet-rpc.sequence0.network",
18
+ mainnet: "https://rpc.sequence0.network",
19
+ };
20
+ // ---------------------------------------------------------------------------
21
+ // Heartbeat
22
+ // ---------------------------------------------------------------------------
23
+ export class Heartbeat {
24
+ client;
25
+ intervalMs;
26
+ onEvent;
27
+ timer = null;
28
+ consecutiveFailures = 0;
29
+ /** RPC health tracking */
30
+ lastBlockNumber = null;
31
+ staleBlockCount = 0;
32
+ /** Cached RPC URL resolved from config */
33
+ rpcUrl = null;
34
+ /** Optional healer — set externally to enable self-healing */
35
+ healer = null;
36
+ constructor(client, options) {
37
+ this.client = client;
38
+ this.intervalMs = options?.intervalMs ?? DEFAULT_INTERVAL_MS;
39
+ this.onEvent = options?.onEvent;
40
+ }
41
+ // -------------------------------------------------------------------------
42
+ // Lifecycle
43
+ // -------------------------------------------------------------------------
44
+ /** Start the periodic heartbeat loop. */
45
+ start() {
46
+ if (this.timer)
47
+ return; // already running
48
+ logger.debug(`Heartbeat starting (interval=${this.intervalMs}ms)`);
49
+ // Run immediately, then on interval
50
+ void this.runOnce();
51
+ this.timer = setInterval(() => void this.runOnce(), this.intervalMs);
52
+ }
53
+ /** Stop the heartbeat loop. */
54
+ stop() {
55
+ if (this.timer) {
56
+ clearInterval(this.timer);
57
+ this.timer = null;
58
+ logger.debug("Heartbeat stopped");
59
+ }
60
+ }
61
+ /** Whether the heartbeat loop is currently running. */
62
+ isRunning() {
63
+ return this.timer !== null;
64
+ }
65
+ // -------------------------------------------------------------------------
66
+ // Single check cycle
67
+ // -------------------------------------------------------------------------
68
+ /** Run a single heartbeat check cycle. Useful for testing. */
69
+ async runOnce() {
70
+ const events = [];
71
+ // 1. Internet connectivity check (must run FIRST)
72
+ const internetOk = await this._checkInternet(events);
73
+ // 2. RPC health check (only if internet is up)
74
+ if (internetOk) {
75
+ await this._checkRpc(events);
76
+ }
77
+ // 3. Agent health check (skip if internet is down — don't misreport agent_down)
78
+ if (internetOk) {
79
+ await this._checkHealth(events);
80
+ }
81
+ else {
82
+ logger.debug("Skipping agent health check — internet is unreachable");
83
+ }
84
+ // 4. Status check (only if agent is reachable)
85
+ if (this.consecutiveFailures === 0 && internetOk) {
86
+ await this._checkStatus(events);
87
+ await this._checkCommittees(events);
88
+ }
89
+ // 5. System resources
90
+ this._checkMemory(events);
91
+ await this._checkDisk(events);
92
+ // Persist & dispatch events
93
+ for (const event of events) {
94
+ this._persistEvent(event);
95
+ this.onEvent?.(event);
96
+ if (this.healer) {
97
+ try {
98
+ await this.healer.handleEvent(event);
99
+ }
100
+ catch (err) {
101
+ logger.error(`Healer error: ${err instanceof Error ? err.message : String(err)}`);
102
+ }
103
+ }
104
+ }
105
+ return events;
106
+ }
107
+ // -------------------------------------------------------------------------
108
+ // Individual checks
109
+ // -------------------------------------------------------------------------
110
+ /** Resolve the RPC URL from config, caching the result. */
111
+ _getRpcUrl() {
112
+ if (this.rpcUrl)
113
+ return this.rpcUrl;
114
+ const agentCfg = readAgentConfig();
115
+ if (agentCfg?.rpc_url) {
116
+ this.rpcUrl = agentCfg.rpc_url;
117
+ return this.rpcUrl;
118
+ }
119
+ const bcCfg = readBlockclawConfig();
120
+ const network = bcCfg.network ?? "mainnet";
121
+ this.rpcUrl = DEFAULT_RPC_URLS[network] ?? DEFAULT_RPC_URLS["mainnet"];
122
+ return this.rpcUrl;
123
+ }
124
+ /**
125
+ * Check internet connectivity. Tries RPC eth_blockNumber first, falls back
126
+ * to DNS resolution for sequence0.network. Returns true if internet is up.
127
+ */
128
+ async _checkInternet(events) {
129
+ const rpcUrl = this._getRpcUrl();
130
+ // Primary check: try to reach the RPC endpoint
131
+ try {
132
+ const controller = new AbortController();
133
+ const timeout = setTimeout(() => controller.abort(), 5_000);
134
+ const res = await fetch(rpcUrl, {
135
+ method: "POST",
136
+ headers: { "Content-Type": "application/json" },
137
+ body: JSON.stringify({ jsonrpc: "2.0", method: "net_version", params: [], id: 1 }),
138
+ signal: controller.signal,
139
+ });
140
+ clearTimeout(timeout);
141
+ if (res.ok)
142
+ return true;
143
+ }
144
+ catch {
145
+ // RPC unreachable — try DNS as secondary check
146
+ }
147
+ // Secondary check: DNS resolution
148
+ try {
149
+ await dns.resolve4("sequence0.network");
150
+ return true;
151
+ }
152
+ catch {
153
+ // Both checks failed — internet is down
154
+ }
155
+ events.push({
156
+ timestamp: Date.now(),
157
+ type: "network_unreachable",
158
+ message: "Internet connectivity lost — both RPC and DNS resolution failed",
159
+ data: { rpcUrl },
160
+ });
161
+ return false;
162
+ }
163
+ /**
164
+ * Check RPC health by calling eth_blockNumber. Tracks block progression
165
+ * and emits rpc_unreachable or rpc_stale events.
166
+ */
167
+ async _checkRpc(events) {
168
+ const rpcUrl = this._getRpcUrl();
169
+ try {
170
+ const controller = new AbortController();
171
+ const timeout = setTimeout(() => controller.abort(), 10_000);
172
+ const res = await fetch(rpcUrl, {
173
+ method: "POST",
174
+ headers: { "Content-Type": "application/json" },
175
+ body: JSON.stringify({ jsonrpc: "2.0", method: "eth_blockNumber", params: [], id: 1 }),
176
+ signal: controller.signal,
177
+ });
178
+ clearTimeout(timeout);
179
+ if (!res.ok) {
180
+ events.push({
181
+ timestamp: Date.now(),
182
+ type: "rpc_unreachable",
183
+ message: `RPC returned HTTP ${res.status}`,
184
+ data: { rpcUrl, httpStatus: res.status },
185
+ });
186
+ return;
187
+ }
188
+ const json = (await res.json());
189
+ if (!json.result) {
190
+ events.push({
191
+ timestamp: Date.now(),
192
+ type: "rpc_unreachable",
193
+ message: "RPC returned invalid response (no result field)",
194
+ data: { rpcUrl, response: json },
195
+ });
196
+ return;
197
+ }
198
+ const blockNumber = BigInt(json.result);
199
+ if (this.lastBlockNumber !== null && blockNumber === this.lastBlockNumber) {
200
+ this.staleBlockCount++;
201
+ if (this.staleBlockCount >= RPC_STALE_THRESHOLD) {
202
+ events.push({
203
+ timestamp: Date.now(),
204
+ type: "rpc_stale",
205
+ message: `Chain not producing blocks — block ${blockNumber.toString()} unchanged for ${this.staleBlockCount} consecutive checks`,
206
+ data: {
207
+ rpcUrl,
208
+ blockNumber: blockNumber.toString(),
209
+ staleChecks: this.staleBlockCount,
210
+ },
211
+ });
212
+ }
213
+ }
214
+ else {
215
+ this.staleBlockCount = 0;
216
+ }
217
+ this.lastBlockNumber = blockNumber;
218
+ }
219
+ catch (err) {
220
+ events.push({
221
+ timestamp: Date.now(),
222
+ type: "rpc_unreachable",
223
+ message: `RPC unreachable: ${err instanceof Error ? err.message : String(err)}`,
224
+ data: {
225
+ rpcUrl,
226
+ error: err instanceof Error ? err.message : String(err),
227
+ },
228
+ });
229
+ }
230
+ }
231
+ /** GET /health — track latency and consecutive failures. */
232
+ async _checkHealth(events) {
233
+ const start = Date.now();
234
+ try {
235
+ const health = await this.client.health();
236
+ const latencyMs = Date.now() - start;
237
+ this.consecutiveFailures = 0;
238
+ events.push({
239
+ timestamp: Date.now(),
240
+ type: "health_ok",
241
+ message: `Agent healthy (${latencyMs}ms, ${health.connected_peers} peers, uptime ${health.uptime_seconds}s)`,
242
+ data: {
243
+ latencyMs,
244
+ peerId: health.peer_id,
245
+ connectedPeers: health.connected_peers,
246
+ uptimeSeconds: health.uptime_seconds,
247
+ version: health.version ?? null,
248
+ },
249
+ });
250
+ // Check for available update
251
+ if (health.update_available) {
252
+ events.push({
253
+ timestamp: Date.now(),
254
+ type: "update_available",
255
+ message: `Agent update available: ${health.update_available}`,
256
+ data: { version: health.update_available },
257
+ });
258
+ }
259
+ }
260
+ catch (err) {
261
+ this.consecutiveFailures++;
262
+ const message = this.consecutiveFailures >= CONSECUTIVE_FAILURES_THRESHOLD
263
+ ? `Agent unreachable (${this.consecutiveFailures} consecutive failures)`
264
+ : `Health check failed (attempt ${this.consecutiveFailures}/${CONSECUTIVE_FAILURES_THRESHOLD})`;
265
+ if (this.consecutiveFailures >= CONSECUTIVE_FAILURES_THRESHOLD) {
266
+ events.push({
267
+ timestamp: Date.now(),
268
+ type: "agent_down",
269
+ message,
270
+ data: {
271
+ consecutiveFailures: this.consecutiveFailures,
272
+ error: err instanceof Error ? err.message : String(err),
273
+ },
274
+ });
275
+ }
276
+ else {
277
+ logger.warn(message);
278
+ }
279
+ }
280
+ }
281
+ /** GET /status — check peers, sessions, wallets. */
282
+ async _checkStatus(events) {
283
+ try {
284
+ const status = await this.client.status();
285
+ // Detect zero peers
286
+ if (status.connected_peers === 0) {
287
+ events.push({
288
+ timestamp: Date.now(),
289
+ type: "peers_lost",
290
+ message: "Agent has 0 connected peers",
291
+ data: {
292
+ peerId: status.peer_id,
293
+ wallets: status.wallets.length,
294
+ activeDkgSessions: status.active_dkg_sessions,
295
+ activeSigningSessions: status.active_signing_sessions,
296
+ },
297
+ });
298
+ }
299
+ // Check for update in status response too
300
+ if (status.update_available) {
301
+ // Only emit if not already emitted from health check
302
+ events.push({
303
+ timestamp: Date.now(),
304
+ type: "update_available",
305
+ message: `Agent update available: ${status.update_available}`,
306
+ data: { version: status.update_available },
307
+ });
308
+ }
309
+ }
310
+ catch (err) {
311
+ logger.debug(`Status check failed: ${err instanceof Error ? err.message : String(err)}`);
312
+ }
313
+ }
314
+ /** GET /health/committees — detect degraded/critical committees. */
315
+ async _checkCommittees(events) {
316
+ try {
317
+ const committees = await this.client.committeeHealth();
318
+ for (const committee of committees) {
319
+ const status = committee.status.toLowerCase();
320
+ if (status === "degraded" || status === "atrisk" || status === "at_risk") {
321
+ events.push({
322
+ timestamp: Date.now(),
323
+ type: "health_degraded",
324
+ message: `Committee ${committee.wallet_id} is ${committee.status} (${committee.alive}/${committee.total} alive, threshold=${committee.threshold})`,
325
+ data: {
326
+ walletId: committee.wallet_id,
327
+ status: committee.status,
328
+ alive: committee.alive,
329
+ total: committee.total,
330
+ threshold: committee.threshold,
331
+ deadPeers: committee.dead_peers ?? [],
332
+ },
333
+ });
334
+ }
335
+ else if (status === "critical" || status === "dead") {
336
+ events.push({
337
+ timestamp: Date.now(),
338
+ type: "health_critical",
339
+ message: `Committee ${committee.wallet_id} is ${committee.status} (${committee.alive}/${committee.total} alive, threshold=${committee.threshold})`,
340
+ data: {
341
+ walletId: committee.wallet_id,
342
+ status: committee.status,
343
+ alive: committee.alive,
344
+ total: committee.total,
345
+ threshold: committee.threshold,
346
+ deadPeers: committee.dead_peers ?? [],
347
+ },
348
+ });
349
+ }
350
+ }
351
+ }
352
+ catch (err) {
353
+ logger.debug(`Committee health check failed: ${err instanceof Error ? err.message : String(err)}`);
354
+ }
355
+ }
356
+ /** Check system memory usage via os module. */
357
+ _checkMemory(events) {
358
+ const totalMem = os.totalmem();
359
+ const freeMem = os.freemem();
360
+ const usedPercent = ((totalMem - freeMem) / totalMem) * 100;
361
+ if (usedPercent >= MEMORY_USAGE_WARNING_PERCENT) {
362
+ events.push({
363
+ timestamp: Date.now(),
364
+ type: "memory_warning",
365
+ message: `System memory usage at ${usedPercent.toFixed(1)}% (${(freeMem / 1073741824).toFixed(1)} GB free of ${(totalMem / 1073741824).toFixed(1)} GB)`,
366
+ data: {
367
+ totalBytes: totalMem,
368
+ freeBytes: freeMem,
369
+ usedPercent: Math.round(usedPercent * 10) / 10,
370
+ },
371
+ });
372
+ }
373
+ }
374
+ /** Check disk usage via platform utility. */
375
+ async _checkDisk(events) {
376
+ try {
377
+ const disk = await getDiskUsage(os.homedir());
378
+ if (disk.usedPercent >= DISK_USAGE_WARNING_PERCENT) {
379
+ events.push({
380
+ timestamp: Date.now(),
381
+ type: "disk_warning",
382
+ message: `Disk usage at ${disk.usedPercent.toFixed(1)}% (${(disk.free / 1073741824).toFixed(1)} GB free)`,
383
+ data: {
384
+ totalBytes: disk.total,
385
+ freeBytes: disk.free,
386
+ usedBytes: disk.used,
387
+ usedPercent: Math.round(disk.usedPercent * 10) / 10,
388
+ },
389
+ });
390
+ }
391
+ }
392
+ catch (err) {
393
+ logger.debug(`Disk check failed: ${err instanceof Error ? err.message : String(err)}`);
394
+ }
395
+ }
396
+ // -------------------------------------------------------------------------
397
+ // Persistence
398
+ // -------------------------------------------------------------------------
399
+ /** Maximum events.log size in bytes before rotation (10 MB). */
400
+ static MAX_LOG_BYTES = 10 * 1024 * 1024;
401
+ /** Rotate events.log if it exceeds the size limit. */
402
+ _rotateLogIfNeeded() {
403
+ try {
404
+ const stat = fs.statSync(EVENTS_LOG);
405
+ if (stat.size >= Heartbeat.MAX_LOG_BYTES) {
406
+ fs.renameSync(EVENTS_LOG, EVENTS_LOG + ".1");
407
+ }
408
+ }
409
+ catch {
410
+ // File may not exist yet — nothing to rotate.
411
+ }
412
+ }
413
+ /** Append a heartbeat event as a JSON line to the events log file. */
414
+ _persistEvent(event) {
415
+ try {
416
+ ensureBlockclawDir();
417
+ this._rotateLogIfNeeded();
418
+ fs.appendFileSync(EVENTS_LOG, JSON.stringify(event) + "\n", "utf8");
419
+ }
420
+ catch (err) {
421
+ logger.debug(`Failed to persist event: ${err instanceof Error ? err.message : String(err)}`);
422
+ }
423
+ }
424
+ }
425
+ export default Heartbeat;
426
+ //# sourceMappingURL=heartbeat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heartbeat.js","sourceRoot":"","sources":["../../src/core/heartbeat.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ /** A recorded issue or pattern */
2
+ export interface MemoryEntry {
3
+ id: string;
4
+ type: "issue" | "pattern" | "learning" | "metric";
5
+ timestamp: number;
6
+ summary: string;
7
+ details?: Record<string, unknown>;
8
+ /** Number of times this pattern has been seen */
9
+ occurrences: number;
10
+ lastSeen: number;
11
+ resolved?: boolean;
12
+ }
13
+ interface MemoryStore {
14
+ entries: MemoryEntry[];
15
+ stats: {
16
+ totalRestarts: number;
17
+ totalHealActions: number;
18
+ lastStartup: number;
19
+ uptimeRecords: number[];
20
+ };
21
+ }
22
+ /** Persistent memory for tracking issues, patterns, and learnings */
23
+ export declare class Memory {
24
+ private store;
25
+ constructor();
26
+ /** Record an issue */
27
+ recordIssue(summary: string, details?: Record<string, unknown>): void;
28
+ /** Record a pattern observation */
29
+ recordPattern(summary: string, details?: Record<string, unknown>): void;
30
+ /** Record a learning */
31
+ recordLearning(summary: string, details?: Record<string, unknown>): void;
32
+ /** Mark an issue as resolved */
33
+ resolveIssue(id: string): void;
34
+ /** Get recent issues */
35
+ getIssues(limit?: number): MemoryEntry[];
36
+ /** Get all patterns */
37
+ getPatterns(): MemoryEntry[];
38
+ /** Get learnings */
39
+ getLearnings(): MemoryEntry[];
40
+ /** Increment restart counter */
41
+ recordRestart(): void;
42
+ /** Increment heal action counter */
43
+ recordHealAction(): void;
44
+ /** Record startup */
45
+ recordStartup(): void;
46
+ /** Get stats */
47
+ getStats(): MemoryStore["stats"];
48
+ /** Get total entry count */
49
+ get size(): number;
50
+ /** Clean old resolved issues (older than 7 days) */
51
+ cleanup(): number;
52
+ private load;
53
+ private save;
54
+ private generateId;
55
+ }
56
+ export {};
57
+ //# sourceMappingURL=memory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../src/core/memory.ts"],"names":[],"mappings":"AAGA,kCAAkC;AAClC,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,OAAO,GAAG,SAAS,GAAG,UAAU,GAAG,QAAQ,CAAC;IAClD,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,iDAAiD;IACjD,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,UAAU,WAAW;IACnB,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,KAAK,EAAE;QACL,aAAa,EAAE,MAAM,CAAC;QACtB,gBAAgB,EAAE,MAAM,CAAC;QACzB,WAAW,EAAE,MAAM,CAAC;QACpB,aAAa,EAAE,MAAM,EAAE,CAAC;KACzB,CAAC;CACH;AAED,qEAAqE;AACrE,qBAAa,MAAM;IACjB,OAAO,CAAC,KAAK,CAAc;;IAM3B,sBAAsB;IACtB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAwBrE,mCAAmC;IACnC,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAuBvE,wBAAwB;IACxB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAaxE,gCAAgC;IAChC,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAQ9B,wBAAwB;IACxB,SAAS,CAAC,KAAK,GAAE,MAAW,GAAG,WAAW,EAAE;IAO5C,uBAAuB;IACvB,WAAW,IAAI,WAAW,EAAE;IAM5B,oBAAoB;IACpB,YAAY,IAAI,WAAW,EAAE;IAM7B,gCAAgC;IAChC,aAAa,IAAI,IAAI;IAKrB,oCAAoC;IACpC,gBAAgB,IAAI,IAAI;IAKxB,qBAAqB;IACrB,aAAa,IAAI,IAAI;IAKrB,gBAAgB;IAChB,QAAQ,IAAI,WAAW,CAAC,OAAO,CAAC;IAIhC,4BAA4B;IAC5B,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,oDAAoD;IACpD,OAAO,IAAI,MAAM;IAWjB,OAAO,CAAC,IAAI;IAiBZ,OAAO,CAAC,IAAI;IAKZ,OAAO,CAAC,UAAU;CAGnB"}
@@ -0,0 +1,149 @@
1
+ import fs from "node:fs";
2
+ import { MEMORY_FILE, ensureBlockclawDir } from "../utils/paths.js";
3
+ /** Persistent memory for tracking issues, patterns, and learnings */
4
+ export class Memory {
5
+ store;
6
+ constructor() {
7
+ this.store = this.load();
8
+ }
9
+ /** Record an issue */
10
+ recordIssue(summary, details) {
11
+ const existing = this.store.entries.find((e) => e.type === "issue" && e.summary === summary && !e.resolved);
12
+ if (existing) {
13
+ existing.occurrences++;
14
+ existing.lastSeen = Date.now();
15
+ if (details)
16
+ existing.details = { ...existing.details, ...details };
17
+ }
18
+ else {
19
+ this.store.entries.push({
20
+ id: this.generateId(),
21
+ type: "issue",
22
+ timestamp: Date.now(),
23
+ summary,
24
+ details,
25
+ occurrences: 1,
26
+ lastSeen: Date.now(),
27
+ });
28
+ }
29
+ this.save();
30
+ }
31
+ /** Record a pattern observation */
32
+ recordPattern(summary, details) {
33
+ const existing = this.store.entries.find((e) => e.type === "pattern" && e.summary === summary);
34
+ if (existing) {
35
+ existing.occurrences++;
36
+ existing.lastSeen = Date.now();
37
+ }
38
+ else {
39
+ this.store.entries.push({
40
+ id: this.generateId(),
41
+ type: "pattern",
42
+ timestamp: Date.now(),
43
+ summary,
44
+ details,
45
+ occurrences: 1,
46
+ lastSeen: Date.now(),
47
+ });
48
+ }
49
+ this.save();
50
+ }
51
+ /** Record a learning */
52
+ recordLearning(summary, details) {
53
+ this.store.entries.push({
54
+ id: this.generateId(),
55
+ type: "learning",
56
+ timestamp: Date.now(),
57
+ summary,
58
+ details,
59
+ occurrences: 1,
60
+ lastSeen: Date.now(),
61
+ });
62
+ this.save();
63
+ }
64
+ /** Mark an issue as resolved */
65
+ resolveIssue(id) {
66
+ const entry = this.store.entries.find((e) => e.id === id);
67
+ if (entry) {
68
+ entry.resolved = true;
69
+ this.save();
70
+ }
71
+ }
72
+ /** Get recent issues */
73
+ getIssues(limit = 20) {
74
+ return this.store.entries
75
+ .filter((e) => e.type === "issue" && !e.resolved)
76
+ .sort((a, b) => b.lastSeen - a.lastSeen)
77
+ .slice(0, limit);
78
+ }
79
+ /** Get all patterns */
80
+ getPatterns() {
81
+ return this.store.entries
82
+ .filter((e) => e.type === "pattern")
83
+ .sort((a, b) => b.occurrences - a.occurrences);
84
+ }
85
+ /** Get learnings */
86
+ getLearnings() {
87
+ return this.store.entries
88
+ .filter((e) => e.type === "learning")
89
+ .sort((a, b) => b.timestamp - a.timestamp);
90
+ }
91
+ /** Increment restart counter */
92
+ recordRestart() {
93
+ this.store.stats.totalRestarts++;
94
+ this.save();
95
+ }
96
+ /** Increment heal action counter */
97
+ recordHealAction() {
98
+ this.store.stats.totalHealActions++;
99
+ this.save();
100
+ }
101
+ /** Record startup */
102
+ recordStartup() {
103
+ this.store.stats.lastStartup = Date.now();
104
+ this.save();
105
+ }
106
+ /** Get stats */
107
+ getStats() {
108
+ return { ...this.store.stats };
109
+ }
110
+ /** Get total entry count */
111
+ get size() {
112
+ return this.store.entries.length;
113
+ }
114
+ /** Clean old resolved issues (older than 7 days) */
115
+ cleanup() {
116
+ const cutoff = Date.now() - 7 * 24 * 60 * 60 * 1000;
117
+ const before = this.store.entries.length;
118
+ this.store.entries = this.store.entries.filter((e) => !(e.resolved && e.lastSeen < cutoff));
119
+ const removed = before - this.store.entries.length;
120
+ if (removed > 0)
121
+ this.save();
122
+ return removed;
123
+ }
124
+ load() {
125
+ try {
126
+ const content = fs.readFileSync(MEMORY_FILE, "utf8");
127
+ return JSON.parse(content);
128
+ }
129
+ catch {
130
+ return {
131
+ entries: [],
132
+ stats: {
133
+ totalRestarts: 0,
134
+ totalHealActions: 0,
135
+ lastStartup: 0,
136
+ uptimeRecords: [],
137
+ },
138
+ };
139
+ }
140
+ }
141
+ save() {
142
+ ensureBlockclawDir();
143
+ fs.writeFileSync(MEMORY_FILE, JSON.stringify(this.store, null, 2), "utf8");
144
+ }
145
+ generateId() {
146
+ return `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
147
+ }
148
+ }
149
+ //# sourceMappingURL=memory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.js","sourceRoot":"","sources":["../../src/core/memory.ts"],"names":[],"mappings":"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"}