blitzwing 0.1.9 → 0.1.10
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/package.json +1 -1
- package/src/heartbeat.js +64 -0
- package/src/wizard.js +5 -27
package/package.json
CHANGED
package/src/heartbeat.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { heartbeatHost } from "./api.js";
|
|
5
|
+
import { HOME_DIR } from "./config.js";
|
|
6
|
+
|
|
7
|
+
/** Must be well below mother HEARTBEAT_TTL_SECONDS (default 60). */
|
|
8
|
+
export const DEFAULT_HEARTBEAT_INTERVAL_MS = 20_000;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Start a detached background process that heartbeats the mother orchestrator.
|
|
12
|
+
* @param {{ motherUrl: string, hostId: string, intervalMs?: number }} opts
|
|
13
|
+
*/
|
|
14
|
+
export function startContributorHeartbeatDaemon({
|
|
15
|
+
motherUrl,
|
|
16
|
+
hostId,
|
|
17
|
+
intervalMs = DEFAULT_HEARTBEAT_INTERVAL_MS,
|
|
18
|
+
}) {
|
|
19
|
+
const hbPath = path.join(HOME_DIR, "heartbeat.mjs");
|
|
20
|
+
fs.mkdirSync(HOME_DIR, { recursive: true });
|
|
21
|
+
fs.writeFileSync(
|
|
22
|
+
hbPath,
|
|
23
|
+
`const mother = ${JSON.stringify(motherUrl)};
|
|
24
|
+
const hostId = ${JSON.stringify(hostId)};
|
|
25
|
+
const intervalMs = ${intervalMs};
|
|
26
|
+
async function beat() {
|
|
27
|
+
try {
|
|
28
|
+
await fetch(mother.replace(/\\/$/, "") + "/v1/hosts/heartbeat", {
|
|
29
|
+
method: "POST",
|
|
30
|
+
headers: {
|
|
31
|
+
"Content-Type": "application/json",
|
|
32
|
+
"ngrok-skip-browser-warning": "true",
|
|
33
|
+
},
|
|
34
|
+
body: JSON.stringify({ host_id: hostId }),
|
|
35
|
+
});
|
|
36
|
+
} catch {}
|
|
37
|
+
}
|
|
38
|
+
setInterval(beat, intervalMs);
|
|
39
|
+
beat();
|
|
40
|
+
`
|
|
41
|
+
);
|
|
42
|
+
const child = spawn(process.execPath, [hbPath], {
|
|
43
|
+
detached: true,
|
|
44
|
+
stdio: "ignore",
|
|
45
|
+
});
|
|
46
|
+
child.unref();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** In-process heartbeat loop (for tests or long-running CLI). */
|
|
50
|
+
export async function startContributorHeartbeatLoop({
|
|
51
|
+
motherUrl,
|
|
52
|
+
hostId,
|
|
53
|
+
intervalMs = DEFAULT_HEARTBEAT_INTERVAL_MS,
|
|
54
|
+
}) {
|
|
55
|
+
async function beat() {
|
|
56
|
+
try {
|
|
57
|
+
await heartbeatHost(motherUrl, { host_id: hostId });
|
|
58
|
+
} catch {
|
|
59
|
+
/* mother may be briefly unavailable */
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
setInterval(beat, intervalMs);
|
|
63
|
+
await beat();
|
|
64
|
+
}
|
package/src/wizard.js
CHANGED
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
venvPython,
|
|
19
19
|
} from "./install.js";
|
|
20
20
|
import { saveState, loadState, clearState, ensureHome } from "./state.js";
|
|
21
|
+
import { startContributorHeartbeatDaemon } from "./heartbeat.js";
|
|
21
22
|
|
|
22
23
|
function parseArgs(argv) {
|
|
23
24
|
const out = { cmd: null, discoveryUrl: process.env.BLITZWING_DISCOVERY_URL || DEFAULT_DISCOVERY_URL };
|
|
@@ -322,7 +323,10 @@ async function wizard(args) {
|
|
|
322
323
|
joined_at: new Date().toISOString(),
|
|
323
324
|
};
|
|
324
325
|
saveState(state);
|
|
325
|
-
|
|
326
|
+
startContributorHeartbeatDaemon({
|
|
327
|
+
motherUrl: state.mother_url,
|
|
328
|
+
hostId: state.host_id,
|
|
329
|
+
});
|
|
326
330
|
|
|
327
331
|
p.outro(
|
|
328
332
|
`${color.green("You are online.")} Hosting ${color.cyan(String(state.layers_hosted))} layers of ${color.cyan(state.model)} at ${state.block_indices}\n` +
|
|
@@ -330,32 +334,6 @@ async function wizard(args) {
|
|
|
330
334
|
);
|
|
331
335
|
}
|
|
332
336
|
|
|
333
|
-
function startHeartbeatDaemon(state) {
|
|
334
|
-
const hbPath = path.join(HOME_DIR, "heartbeat.mjs");
|
|
335
|
-
fs.writeFileSync(
|
|
336
|
-
hbPath,
|
|
337
|
-
`const mother = ${JSON.stringify(state.mother_url)};
|
|
338
|
-
const hostId = ${JSON.stringify(state.host_id)};
|
|
339
|
-
async function beat() {
|
|
340
|
-
try {
|
|
341
|
-
await fetch(mother.replace(/\\/$/, "") + "/v1/hosts/heartbeat", {
|
|
342
|
-
method: "POST",
|
|
343
|
-
headers: { "Content-Type": "application/json" },
|
|
344
|
-
body: JSON.stringify({ host_id: hostId }),
|
|
345
|
-
});
|
|
346
|
-
} catch {}
|
|
347
|
-
}
|
|
348
|
-
setInterval(beat, 60000);
|
|
349
|
-
beat();
|
|
350
|
-
`
|
|
351
|
-
);
|
|
352
|
-
const child = spawn(process.execPath, [hbPath], {
|
|
353
|
-
detached: true,
|
|
354
|
-
stdio: "ignore",
|
|
355
|
-
});
|
|
356
|
-
child.unref();
|
|
357
|
-
}
|
|
358
|
-
|
|
359
337
|
async function showStatus() {
|
|
360
338
|
const state = loadState();
|
|
361
339
|
if (!state) {
|