@tiens.nguyen/gonext-local-worker 1.0.35 → 1.0.37

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,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
3
  * GoNext local worker:
4
- * - `gonext-local-worker set <workerKey> [--api-base URL] [--poll-ms 1500]`
4
+ * - `gonext-local-worker set <workerKey> [--api-base URL]`
5
5
  * writes ~/.gonext/worker.env
6
6
  * - `gonext-local-worker ws-ping-test` — POST worker ws-ping (needs GONEXT_* env)
7
7
  * - `gonext-local-worker simulate-chat [text]` — claim next chat job, push fake reply like the real worker (needs GONEXT_* env)
@@ -30,7 +30,7 @@ gonext-local-worker
30
30
 
31
31
  Usage:
32
32
  gonext-local-worker
33
- gonext-local-worker set <workerKey> [--api-base <url>] [--poll-ms <ms>]
33
+ gonext-local-worker set <workerKey> [--api-base <url>]
34
34
  gonext-local-worker ws-ping-test # POST /api/worker/ws-ping-test (needs GONEXT_* env)
35
35
  gonext-local-worker simulate-chat [text...] # claim next chat job, fake reply (stop normal worker first)
36
36
 
@@ -63,7 +63,6 @@ async function setConfig() {
63
63
  const currentRaw = await readFile(ENV_FILE, "utf8").catch(() => "");
64
64
  const current = dotenv.parse(currentRaw);
65
65
  const apiBaseFromFlag = parseFlag("--api-base");
66
- const pollMsFromFlag = parseFlag("--poll-ms");
67
66
  const next = {
68
67
  GONEXT_API_BASE: (
69
68
  apiBaseFromFlag ??
@@ -72,8 +71,7 @@ async function setConfig() {
72
71
  ""
73
72
  ).replace(/\/+$/, ""),
74
73
  GONEXT_WORKER_KEY: workerKey,
75
- GONEXT_POLL_MS:
76
- pollMsFromFlag ?? current.GONEXT_POLL_MS ?? process.env.GONEXT_POLL_MS ?? "1500",
74
+ GONEXT_POLL_MS: "500",
77
75
  };
78
76
  await mkdir(join(homedir(), ".gonext"), { recursive: true });
79
77
  await writeFile(
@@ -99,7 +97,8 @@ if (args[0] === "set") {
99
97
 
100
98
  const apiBase = (process.env.GONEXT_API_BASE ?? "").replace(/\/+$/, "");
101
99
  const workerKey = process.env.GONEXT_WORKER_KEY ?? "";
102
- const pollMs = Number(process.env.GONEXT_POLL_MS ?? "1500") || 1500;
100
+ const pollMs = 500;
101
+ const localHealthConcurrency = 4;
103
102
 
104
103
  const CHUNK_PATH = "/api/worker/job-chunk";
105
104
 
@@ -717,15 +716,29 @@ async function runLocalHealthJob(job) {
717
716
  }
718
717
  }
719
718
 
719
+ const localHealthInFlight = new Set();
720
+
721
+ function trackLocalHealthTask(task) {
722
+ localHealthInFlight.add(task);
723
+ task.finally(() => {
724
+ localHealthInFlight.delete(task);
725
+ });
726
+ }
727
+
720
728
  async function pollOnce() {
721
- const res = await workerFetch("/api/worker/jobs/next", { method: "POST" });
722
- if (res.status === 204) return;
723
- if (!res.ok) {
724
- const t = await res.text().catch(() => "");
725
- throw new Error(`next failed ${res.status}: ${t}`);
726
- }
727
- const job = await res.json();
728
- if (job?.jobId) {
729
+ while (localHealthInFlight.size < localHealthConcurrency) {
730
+ const res = await workerFetch("/api/worker/jobs/next", { method: "POST" });
731
+ if (res.status === 204) {
732
+ return;
733
+ }
734
+ if (!res.ok) {
735
+ const t = await res.text().catch(() => "");
736
+ throw new Error(`next failed ${res.status}: ${t}`);
737
+ }
738
+ const job = await res.json();
739
+ if (!job?.jobId) {
740
+ return;
741
+ }
729
742
  console.log(
730
743
  `[gonext-worker] claimed ${job.jobId} type=${job.jobType ?? "unknown"} modelKey=${job.modelKey ?? "unknown"}`
731
744
  );
@@ -734,15 +747,24 @@ async function pollOnce() {
734
747
  const isLocalHealthByPayload =
735
748
  Array.isArray(job.payload?.ollamaBaseUrls) || !!job.payload?.mlxOpenAiBaseUrl;
736
749
  if (isLocalHealthByType || isLocalHealthByModelKey || isLocalHealthByPayload) {
737
- await runLocalHealthJob(job);
738
- return;
750
+ const task = runLocalHealthJob(job).catch((e) => {
751
+ console.error("[gonext-worker] local_health task error:", e);
752
+ });
753
+ trackLocalHealthTask(task);
754
+ console.log(
755
+ `[gonext-worker] local_health in-flight ${localHealthInFlight.size}/${localHealthConcurrency}`
756
+ );
757
+ continue;
739
758
  }
740
759
  await runChatJob(job);
760
+ return;
741
761
  }
742
762
  }
743
763
 
744
764
  async function main() {
745
- console.log(`[gonext-worker] polling ${apiBase} every ${pollMs}ms`);
765
+ console.log(
766
+ `[gonext-worker] polling ${apiBase} every ${pollMs}ms (local_health concurrency=${localHealthConcurrency})`
767
+ );
746
768
  for (;;) {
747
769
  try {
748
770
  await pollOnce();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tiens.nguyen/gonext-local-worker",
3
- "version": "1.0.35",
3
+ "version": "1.0.37",
4
4
  "description": "Polls GoNext cloud API for async local LLM jobs and runs them against Ollama/OpenAI-compatible servers on this Mac",
5
5
  "type": "module",
6
6
  "license": "MIT",