@tiens.nguyen/gonext-local-worker 1.0.4 → 1.0.6
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/README.md +5 -5
- package/gonext-local-worker.mjs +6 -24
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ Runs on **your Mac** next to **Ollama** or any **OpenAI-compatible** local serve
|
|
|
6
6
|
2. Runs the job against **`payload.baseURL`** (your LAN `http://127.0.0.1:11434/v1` etc.).
|
|
7
7
|
3. **`PATCH`**es **`running`** → **`completed`** / **`failed`** so DynamoDB and the web app update.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Set your Firebase **worker user id** in the worker env so it claims your own queued jobs.
|
|
10
10
|
|
|
11
11
|
## Install
|
|
12
12
|
|
|
@@ -32,7 +32,7 @@ Create `~/.gonext/worker.env` (optional):
|
|
|
32
32
|
mkdir -p ~/.gonext
|
|
33
33
|
cat > ~/.gonext/worker.env << 'EOF'
|
|
34
34
|
GONEXT_API_BASE=https://YOUR_API.execute-api.ap-southeast-1.amazonaws.com
|
|
35
|
-
|
|
35
|
+
GONEXT_WORKER_USER_ID=paste-your-firebase-user-id
|
|
36
36
|
GONEXT_POLL_MS=1500
|
|
37
37
|
EOF
|
|
38
38
|
chmod 600 ~/.gonext/worker.env
|
|
@@ -42,7 +42,7 @@ Or export in the shell:
|
|
|
42
42
|
|
|
43
43
|
```bash
|
|
44
44
|
export GONEXT_API_BASE=https://....execute-api....amazonaws.com
|
|
45
|
-
export
|
|
45
|
+
export GONEXT_WORKER_USER_ID=...
|
|
46
46
|
```
|
|
47
47
|
|
|
48
48
|
## Run
|
|
@@ -97,7 +97,7 @@ Local worker API endpoints on port 5001:
|
|
|
97
97
|
- `POST /api/chat` -> proxies to `http://localhost:11434/api/chat`
|
|
98
98
|
- `POST /api/generate` -> proxies to `http://localhost:11434/api/generate`
|
|
99
99
|
- `GET /api/tags` -> proxies to `http://localhost:11434/api/tags`
|
|
100
|
-
- `POST /api/dispatch-job` -> cloud dispatch entrypoint
|
|
100
|
+
- `POST /api/dispatch-job` -> cloud dispatch entrypoint
|
|
101
101
|
- `GET /api/health`
|
|
102
102
|
|
|
103
103
|
Legacy non-prefixed routes (`/chat`, `/generate`, `/tags`, `/dispatch-job`, `/health`) are also available for compatibility.
|
|
@@ -116,5 +116,5 @@ launchctl unload ~/Library/LaunchAgents/com.gonext.worker.plist
|
|
|
116
116
|
|
|
117
117
|
## Troubleshooting
|
|
118
118
|
|
|
119
|
-
- **`
|
|
119
|
+
- **`400` / missing workerUserId** — Set `GONEXT_WORKER_USER_ID` correctly.
|
|
120
120
|
- **Job never claimed** — Ensure DynamoDB + worker routes work; Settings must include **Ollama base URL** so the queued payload points at a reachable host from this Mac (`127.0.0.1` is fine).
|
package/gonext-local-worker.mjs
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Env:
|
|
7
7
|
* GONEXT_API_BASE HTTPS origin only (no trailing slash), e.g. https://xxx.execute-api....amazonaws.com
|
|
8
|
-
*
|
|
8
|
+
* GONEXT_WORKER_USER_ID Firebase user id (owner of queued jobs)
|
|
9
9
|
* GONEXT_POLL_MS Poll interval when idle (default 1500)
|
|
10
10
|
*
|
|
11
11
|
* Optional env files (loaded in order; shell exports win if set before launch):
|
|
@@ -14,7 +14,6 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import { homedir } from "node:os";
|
|
16
16
|
import os from "node:os";
|
|
17
|
-
import { createHash } from "node:crypto";
|
|
18
17
|
import { join } from "node:path";
|
|
19
18
|
import dotenv from "dotenv";
|
|
20
19
|
import express from "express";
|
|
@@ -50,7 +49,7 @@ gonext-local-worker — bridge cloud GoNext jobs ↔ local LLM (Ollama / OpenAI-
|
|
|
50
49
|
|
|
51
50
|
Usage:
|
|
52
51
|
export GONEXT_API_BASE=https://....amazonaws.com
|
|
53
|
-
export
|
|
52
|
+
export GONEXT_WORKER_USER_ID=your-firebase-user-id
|
|
54
53
|
gonext-local-worker
|
|
55
54
|
|
|
56
55
|
Options:
|
|
@@ -81,7 +80,7 @@ const apiBase = (
|
|
|
81
80
|
process.env.GONEXT_API_BASE ??
|
|
82
81
|
""
|
|
83
82
|
).replace(/\/+$/, "");
|
|
84
|
-
const
|
|
83
|
+
const workerUserId = (process.env.GONEXT_WORKER_USER_ID ?? "").trim();
|
|
85
84
|
const pollMs =
|
|
86
85
|
(Number.isFinite(args.pollMs) && args.pollMs > 0
|
|
87
86
|
? args.pollMs
|
|
@@ -98,19 +97,15 @@ const ollamaBase = (
|
|
|
98
97
|
process.env.GONEXT_LOCAL_OLLAMA_BASE ?? "http://127.0.0.1:11434"
|
|
99
98
|
).replace(/\/+$/, "");
|
|
100
99
|
|
|
101
|
-
if (!apiBase || !
|
|
100
|
+
if (!apiBase || !workerUserId) {
|
|
102
101
|
console.error(
|
|
103
|
-
"Missing GONEXT_API_BASE or
|
|
102
|
+
"Missing GONEXT_API_BASE or GONEXT_WORKER_USER_ID.\nSet them or put them in ~/.gonext/worker.env — run with --help."
|
|
104
103
|
);
|
|
105
104
|
process.exit(1);
|
|
106
105
|
}
|
|
107
106
|
|
|
108
107
|
const WORKER_VERSION = "1.0.0";
|
|
109
108
|
const WORKER_HOST = os.hostname();
|
|
110
|
-
const DISPATCH_TOKEN = createHash("sha256")
|
|
111
|
-
.update(workerKey, "utf8")
|
|
112
|
-
.digest("hex");
|
|
113
|
-
|
|
114
109
|
function ts() {
|
|
115
110
|
return new Date().toISOString();
|
|
116
111
|
}
|
|
@@ -137,7 +132,7 @@ async function workerFetch(path, init = {}) {
|
|
|
137
132
|
const url = `${apiBase}${path.startsWith("/") ? path : `/${path}`}`;
|
|
138
133
|
const headers = {
|
|
139
134
|
"Content-Type": "application/json",
|
|
140
|
-
"X-Worker-
|
|
135
|
+
"X-Worker-User-Id": workerUserId,
|
|
141
136
|
...(init.headers ?? {}),
|
|
142
137
|
};
|
|
143
138
|
return fetch(url, { ...init, headers });
|
|
@@ -255,15 +250,6 @@ function sleep(ms) {
|
|
|
255
250
|
return new Promise((r) => setTimeout(r, ms));
|
|
256
251
|
}
|
|
257
252
|
|
|
258
|
-
function requireDispatchToken(req, res) {
|
|
259
|
-
const token = req.header("x-gonext-dispatch-token") ?? "";
|
|
260
|
-
if (token !== DISPATCH_TOKEN) {
|
|
261
|
-
res.status(403).json({ error: "Invalid dispatch token." });
|
|
262
|
-
return false;
|
|
263
|
-
}
|
|
264
|
-
return true;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
253
|
function toOllamaChatMessages(messages) {
|
|
268
254
|
return (messages ?? []).map((m) => ({
|
|
269
255
|
role: m.role,
|
|
@@ -386,7 +372,6 @@ function startWebhookServer() {
|
|
|
386
372
|
app.get("/api/tags", tagsHandler);
|
|
387
373
|
|
|
388
374
|
const dispatchJobHandler = async (req, res) => {
|
|
389
|
-
if (!requireDispatchToken(req, res)) return;
|
|
390
375
|
const body = req.body ?? {};
|
|
391
376
|
if (!body?.jobId || !body?.payload) {
|
|
392
377
|
res.status(400).json({ error: "Expected { jobId, payload }." });
|
|
@@ -418,7 +403,6 @@ function startWebhookServer() {
|
|
|
418
403
|
try {
|
|
419
404
|
const body = req.body ?? {};
|
|
420
405
|
const jobId = typeof body.jobId === "string" ? body.jobId : "";
|
|
421
|
-
if (jobId && !requireDispatchToken(req, res)) return;
|
|
422
406
|
const requestBody =
|
|
423
407
|
body.request && typeof body.request === "object" ? body.request : body;
|
|
424
408
|
const parsed = await runOllamaAndMaybeUpdateJob({
|
|
@@ -439,7 +423,6 @@ function startWebhookServer() {
|
|
|
439
423
|
try {
|
|
440
424
|
const body = req.body ?? {};
|
|
441
425
|
const jobId = typeof body.jobId === "string" ? body.jobId : "";
|
|
442
|
-
if (jobId && !requireDispatchToken(req, res)) return;
|
|
443
426
|
const requestBody =
|
|
444
427
|
body.request && typeof body.request === "object" ? body.request : body;
|
|
445
428
|
const parsed = await runOllamaAndMaybeUpdateJob({
|
|
@@ -460,7 +443,6 @@ function startWebhookServer() {
|
|
|
460
443
|
console.log(
|
|
461
444
|
`[${ts()}] local worker API on http://127.0.0.1:${webhookPort} (/chat, /generate, /tags, /dispatch-job, /health)`
|
|
462
445
|
);
|
|
463
|
-
console.log(`[${ts()}] dispatch token is SHA256(worker key)`);
|
|
464
446
|
});
|
|
465
447
|
}
|
|
466
448
|
|
package/package.json
CHANGED