@tiens.nguyen/gonext-local-worker 1.0.332 → 1.0.333
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 +4 -4
- package/gonext-repl.mjs +36 -11
- package/gonext_agent_chat.py +3 -5
- package/package.json +1 -1
package/gonext-local-worker.mjs
CHANGED
|
@@ -1832,8 +1832,7 @@ function _isLocalCodingUrl(baseURL) {
|
|
|
1832
1832
|
/** Resolve to "ollama" | "openai" | "local". `kind` is the user's Settings choice
|
|
1833
1833
|
* ("ollama" | "openai" | "" = Auto). Only Auto costs a probe. */
|
|
1834
1834
|
async function resolveCodingBackend(kind, baseURL) {
|
|
1835
|
-
if (kind === "ollama") return
|
|
1836
|
-
if (kind === "openai") return "openai";
|
|
1835
|
+
if (kind === "ollama" || kind === "openai" || kind === "local") return kind;
|
|
1837
1836
|
if (await _probeIsOllama(baseURL)) return "ollama";
|
|
1838
1837
|
return _isLocalCodingUrl(baseURL) ? "local" : "openai";
|
|
1839
1838
|
}
|
|
@@ -1872,8 +1871,9 @@ async function runAgentChatJob(job) {
|
|
|
1872
1871
|
const cancelAc = new AbortController();
|
|
1873
1872
|
let cancelled = false;
|
|
1874
1873
|
// Task #108: the user's Coding backend setting ("ollama" | "openai" | "" = Auto).
|
|
1875
|
-
const codingKind =
|
|
1876
|
-
|
|
1874
|
+
const codingKind = ["ollama", "openai", "local"].includes(payload?.codingKind)
|
|
1875
|
+
? payload.codingKind
|
|
1876
|
+
: "";
|
|
1877
1877
|
const runRes = await workerFetch(`/api/worker/jobs/${jobId}`, {
|
|
1878
1878
|
method: "PATCH",
|
|
1879
1879
|
body: JSON.stringify({ jobStatus: "running" }),
|
package/gonext-repl.mjs
CHANGED
|
@@ -876,32 +876,52 @@ async function chooseModel() {
|
|
|
876
876
|
}
|
|
877
877
|
const allowed = Array.isArray(probe?.codingAllowed) ? probe.codingAllowed : [];
|
|
878
878
|
const def = (probe?.codingDefault ?? "").trim();
|
|
879
|
-
|
|
879
|
+
// Task #123: a choice is a (backend, model) PAIR — several backends (Ollama, an
|
|
880
|
+
// OpenAI-compatible endpoint, local MLX) can be enabled at once, and picking one moves
|
|
881
|
+
// the URL, the kind and the API key with it. `codingChoices` carries the backend of each
|
|
882
|
+
// entry so the list can say which is which; `codingAllowed` is the same ids, and stays
|
|
883
|
+
// the fallback for an API that predates this.
|
|
884
|
+
const choices = Array.isArray(probe?.codingChoices) && probe.codingChoices.length
|
|
885
|
+
? probe.codingChoices
|
|
886
|
+
: allowed.map((id) => ({ id, model: id, kind: "" }));
|
|
887
|
+
if (choices.length === 0) {
|
|
880
888
|
console.log(dim(" No coding model configured. Set one in the web app → Settings → Agent.\n"));
|
|
881
889
|
return;
|
|
882
890
|
}
|
|
883
|
-
if (
|
|
891
|
+
if (choices.length === 1) {
|
|
884
892
|
console.log(
|
|
885
|
-
dim(` Only one coding model is available: ${
|
|
886
|
-
dim(" Add more in the web app → Settings → Agent →
|
|
893
|
+
dim(` Only one coding model is available: ${choices[0].model}.\n`) +
|
|
894
|
+
dim(" Add more in the web app → Settings → Agent → Coding backends.\n")
|
|
887
895
|
);
|
|
888
896
|
return;
|
|
889
897
|
}
|
|
890
898
|
const active = sessionCodingModel || def;
|
|
891
|
-
// Arrow-key picker (↑/↓ + Enter) — pre-highlight the active model, tag the default
|
|
892
|
-
|
|
893
|
-
const
|
|
899
|
+
// Arrow-key picker (↑/↓ + Enter) — pre-highlight the active model, tag the default, and
|
|
900
|
+
// name the backend when more than one is in play (the same model name can appear twice).
|
|
901
|
+
const KIND_LABEL = { ollama: "Ollama", openai: "OpenAI-compatible", local: "local MLX", "": "auto" };
|
|
902
|
+
const showKind = new Set(choices.map((c) => c.kind ?? "")).size > 1;
|
|
903
|
+
const labels = choices.map((c) => {
|
|
904
|
+
const kind = showKind ? ` ${dim(`· ${KIND_LABEL[c.kind ?? ""] ?? c.kind}`)}` : "";
|
|
905
|
+
return `${c.model}${kind}${c.id === def ? " (default)" : ""}`;
|
|
906
|
+
});
|
|
907
|
+
const activeIdx = choices.findIndex((c) => c.id === active);
|
|
894
908
|
console.log(dim(" Choose the coding model (↑/↓ then Enter):"));
|
|
895
909
|
const idx = await pickFromList(labels, activeIdx >= 0 ? activeIdx : 0);
|
|
896
910
|
if (idx < 0) {
|
|
897
911
|
console.log(dim(" (cancelled)\n"));
|
|
898
912
|
return;
|
|
899
913
|
}
|
|
900
|
-
const chosen =
|
|
914
|
+
const chosen = choices[idx];
|
|
901
915
|
// Empty override means "use the account default" — so don't send an override when the
|
|
902
916
|
// user picks the default (keeps the payload clean and lets a later default change win).
|
|
903
|
-
sessionCodingModel = chosen === def ? "" : chosen;
|
|
904
|
-
|
|
917
|
+
sessionCodingModel = chosen.id === def ? "" : chosen.id;
|
|
918
|
+
// Remember the friendly name for the token footer, which should never show a raw
|
|
919
|
+
// "<kind>::<model>" wire id.
|
|
920
|
+
sessionCodingLabel = chosen.id === def ? "" : chosen.model;
|
|
921
|
+
const where = showKind ? ` (${KIND_LABEL[chosen.kind ?? ""] ?? chosen.kind})` : "";
|
|
922
|
+
console.log(
|
|
923
|
+
green(` ✓ coding model → ${chosen.model}${where}${chosen.id === def ? " (default)" : ""}\n`)
|
|
924
|
+
);
|
|
905
925
|
}
|
|
906
926
|
|
|
907
927
|
// Probe whether SSH KEY auth already works for a server (so we can tell the user to run
|
|
@@ -1252,7 +1272,12 @@ let jobIdForApprovalRace = "";
|
|
|
1252
1272
|
|
|
1253
1273
|
// Per-session coding-model override chosen via /model (empty = use the account default).
|
|
1254
1274
|
// Sent to /agent-ask as codingModelOverride; the API validates it against the whitelist.
|
|
1275
|
+
// Task #123: with several backends configured this is a QUALIFIED id ("<kind>::<model>"),
|
|
1276
|
+
// which resolves to a whole backend — URL, kind and API key — not just a model name.
|
|
1255
1277
|
let sessionCodingModel = "";
|
|
1278
|
+
// The friendly model name behind sessionCodingModel, for display only: the token footer
|
|
1279
|
+
// must never show a raw "<kind>::<model>" wire id. Empty = running the account default.
|
|
1280
|
+
let sessionCodingLabel = "";
|
|
1256
1281
|
// The default coding model id (from the startup agent-payload probe) — shown in the
|
|
1257
1282
|
// per-turn token footer next to the GLOBAL output total so it's clear which model that
|
|
1258
1283
|
// lifetime count belongs to. The /model override (sessionCodingModel) wins when set.
|
|
@@ -2383,7 +2408,7 @@ async function main() {
|
|
|
2383
2408
|
// name so it's clear which coder that running total belongs to. Guard on THIS turn's
|
|
2384
2409
|
// activity so a plain-reply greeting that did no code-model work shows nothing (#112).
|
|
2385
2410
|
if ((inputTokens ?? 0) > 0 || (turnOutputTokens ?? 0) > 0) {
|
|
2386
|
-
const coder =
|
|
2411
|
+
const coder = sessionCodingLabel || defaultCodingModel;
|
|
2387
2412
|
console.log(
|
|
2388
2413
|
dim("tokens · ↑ in ") +
|
|
2389
2414
|
fmtTokens(inputTokens ?? 0) +
|
package/gonext_agent_chat.py
CHANGED
|
@@ -949,10 +949,8 @@ def _resolve_coding_backend(kind, base_url, probe=None):
|
|
|
949
949
|
`probe` is injectable so the resolution table can be replayed offline without network.
|
|
950
950
|
"""
|
|
951
951
|
k = (kind or "").strip().lower()
|
|
952
|
-
if k
|
|
953
|
-
return
|
|
954
|
-
if k == "openai":
|
|
955
|
-
return "openai", "explicit setting"
|
|
952
|
+
if k in ("ollama", "openai", "local"):
|
|
953
|
+
return k, "explicit setting"
|
|
956
954
|
if (probe or _is_ollama_server)(base_url):
|
|
957
955
|
return "ollama", "auto: server answers as Ollama"
|
|
958
956
|
if not _is_local_url(base_url):
|
|
@@ -3620,7 +3618,7 @@ def run_agent_chat(cfg):
|
|
|
3620
3618
|
# coding_api_key: the Bearer key for an OpenAI-compatible coder (empty otherwise). Used
|
|
3621
3619
|
# for the code-model calls (and coding-model auto-detect), NOT the chat agent_api_key.
|
|
3622
3620
|
coding_kind = (cfg.get("codingKind") or "").strip().lower()
|
|
3623
|
-
if coding_kind not in ("ollama", "openai"):
|
|
3621
|
+
if coding_kind not in ("ollama", "openai", "local"):
|
|
3624
3622
|
coding_kind = ""
|
|
3625
3623
|
coding_api_key = (cfg.get("codingApiKey") or "").strip()
|
|
3626
3624
|
# Task #107: when on, emit each code-model response so the worker persists it to Mongo.
|
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.333",
|
|
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",
|