@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.
- package/gonext-local-worker.mjs +39 -17
- package/package.json +1 -1
package/gonext-local-worker.mjs
CHANGED
|
@@ -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]
|
|
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>]
|
|
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 =
|
|
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
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
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
|
-
|
|
738
|
-
|
|
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(
|
|
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.
|
|
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",
|