benchworks 0.4.0 → 0.4.2
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/bin/benchworks.mjs +36 -1
- package/package.json +1 -1
package/bin/benchworks.mjs
CHANGED
|
@@ -20,7 +20,7 @@ import { join } from "node:path";
|
|
|
20
20
|
import { fileURLToPath } from "node:url";
|
|
21
21
|
import { promisify } from "node:util";
|
|
22
22
|
|
|
23
|
-
const VERSION = "0.4.
|
|
23
|
+
const VERSION = "0.4.2";
|
|
24
24
|
const API = (process.env.BENCHWORKS_URL ?? "https://benchworks.dev").replace(/\/+$/, "");
|
|
25
25
|
const HOME = homedir();
|
|
26
26
|
// the runner's own folder: its key and the folder conversations start in (BENCHWORKS_HOME moves it, for a second pairing on one Mac)
|
|
@@ -244,6 +244,8 @@ async function connect(code) {
|
|
|
244
244
|
} else {
|
|
245
245
|
if (away) say("Back in touch with Benchworks.");
|
|
246
246
|
away = false;
|
|
247
|
+
// a newer runner is out: once no conversation is running here, it takes over in this window
|
|
248
|
+
if (newer(answer.body.latest, VERSION) && ![...sessions.values()].some((s) => s.busy)) return update(answer.body.latest);
|
|
247
249
|
if (answer.body.ask === "folder") {
|
|
248
250
|
say("Benchworks asked for a folder. The picker is open.");
|
|
249
251
|
const path = await pickFolder();
|
|
@@ -582,6 +584,8 @@ async function jobs() {
|
|
|
582
584
|
continue;
|
|
583
585
|
}
|
|
584
586
|
if (r.status === 401) return;
|
|
587
|
+
// the runner that took over asks for jobs now; one handed out here unsaid comes to it again
|
|
588
|
+
if (updating) return;
|
|
585
589
|
for (const job of r.body.jobs ?? []) {
|
|
586
590
|
acks.push(job.id);
|
|
587
591
|
if (seen.has(job.id)) continue;
|
|
@@ -597,6 +601,37 @@ setInterval(() => {
|
|
|
597
601
|
for (const s of sessions.values()) if (!s.busy && Date.now() - s.lastAt > IDLE_MS) end(s, "idle");
|
|
598
602
|
}, 60_000).unref();
|
|
599
603
|
|
|
604
|
+
/** Whether version a (x.y.z) is newer than b. */
|
|
605
|
+
function newer(a, b) {
|
|
606
|
+
if (typeof a !== "string" || !/^\d+\.\d+\.\d+$/.test(a)) return false;
|
|
607
|
+
const x = a.split(".").map(Number);
|
|
608
|
+
const y = b.split(".").map(Number);
|
|
609
|
+
for (let i = 0; i < 3; i++) if (x[i] !== y[i]) return x[i] > y[i];
|
|
610
|
+
return false;
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
let updating = false;
|
|
614
|
+
|
|
615
|
+
/**
|
|
616
|
+
* Moves to a newer runner in this same window: the conversations' Claude Code processes end (the next message resumes
|
|
617
|
+
* each), the new version runs as this one's child with the same key and folder, and this one waits for it and leaves with
|
|
618
|
+
* it. Ctrl-C reaches both, and the child is the one that answers it.
|
|
619
|
+
*/
|
|
620
|
+
function update(version) {
|
|
621
|
+
if (updating) return;
|
|
622
|
+
updating = true;
|
|
623
|
+
say(`Benchworks runner ${version} is out. Updating; your conversations carry on with your next message.`);
|
|
624
|
+
for (const s of sessions.values()) end(s, "idle");
|
|
625
|
+
process.removeAllListeners("SIGINT");
|
|
626
|
+
process.on("SIGINT", () => {});
|
|
627
|
+
const child = spawn("npx", ["-y", `benchworks@${version}`, "connect"], { stdio: "inherit", env: { ...process.env, BENCHWORKS_HOME: OWN } });
|
|
628
|
+
child.on("exit", (code) => process.exit(code ?? 0));
|
|
629
|
+
child.on("error", (e) => {
|
|
630
|
+
say(warn(`Could not start ${version} (${e.message}). Run ${again} to update.`));
|
|
631
|
+
process.exit(1);
|
|
632
|
+
});
|
|
633
|
+
}
|
|
634
|
+
|
|
600
635
|
function quit(code = 0) {
|
|
601
636
|
for (const s of sessions.values()) s.proc.kill();
|
|
602
637
|
process.exit(code);
|
package/package.json
CHANGED