@tiens.nguyen/gonext-local-worker 1.0.79 → 1.0.81
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 +2 -0
- package/gonext_agent_chat.py +46 -23
- package/package.json +1 -1
package/gonext-local-worker.mjs
CHANGED
|
@@ -1376,6 +1376,8 @@ async function runAgentChatJob(job) {
|
|
|
1376
1376
|
agentBaseURL: payload?.agentBaseURL ?? "",
|
|
1377
1377
|
agentApiKey: payload?.agentApiKey ?? "",
|
|
1378
1378
|
agentModelId: payload?.agentModelId ?? "",
|
|
1379
|
+
codingBaseURL: payload?.codingBaseURL ?? "",
|
|
1380
|
+
codingModelId: payload?.codingModelId ?? "",
|
|
1379
1381
|
tools: payload?.tools ?? ["http_request"],
|
|
1380
1382
|
maxSteps: payload?.maxSteps ?? 5,
|
|
1381
1383
|
});
|
package/gonext_agent_chat.py
CHANGED
|
@@ -8,6 +8,8 @@ Reads on stdin:
|
|
|
8
8
|
"agentBaseURL": str,
|
|
9
9
|
"agentApiKey": str,
|
|
10
10
|
"agentModelId": str,
|
|
11
|
+
"codingBaseURL": str, # optional: dedicated coding/reasoning model for the
|
|
12
|
+
"codingModelId": str, # CodeAgent's tool-use loop; empty = reuse agentModelId
|
|
11
13
|
"tools": ["http_request"], # v1: only http_request
|
|
12
14
|
"maxSteps": int # default 10
|
|
13
15
|
}
|
|
@@ -204,18 +206,27 @@ def _summarize_result(task_text: str, agent_output: str,
|
|
|
204
206
|
return agent_output
|
|
205
207
|
|
|
206
208
|
|
|
207
|
-
def _plain_reply(
|
|
208
|
-
"""Plain chat completion
|
|
209
|
+
def _plain_reply(messages: list, base_url: str, api_key: str, model_id: str) -> str:
|
|
210
|
+
"""Plain chat completion using the full conversation history."""
|
|
211
|
+
_THINK_RE_LOCAL = re.compile(r"<think>.*?</think>", re.DOTALL | re.IGNORECASE)
|
|
212
|
+
chat_messages = [{"role": "system", "content": "You are a helpful assistant."}]
|
|
213
|
+
for m in messages:
|
|
214
|
+
role = m.get("role", "")
|
|
215
|
+
content = m.get("content", "")
|
|
216
|
+
if role not in ("user", "assistant"):
|
|
217
|
+
continue
|
|
218
|
+
if role == "assistant":
|
|
219
|
+
content = _THINK_RE_LOCAL.sub("", content).strip()
|
|
220
|
+
if not content:
|
|
221
|
+
continue
|
|
222
|
+
chat_messages.append({"role": role, "content": content})
|
|
209
223
|
try:
|
|
210
224
|
from openai import OpenAI
|
|
211
225
|
client = OpenAI(base_url=base_url, api_key=api_key or "local",
|
|
212
226
|
max_retries=0, timeout=60)
|
|
213
227
|
resp = client.chat.completions.create(
|
|
214
228
|
model=model_id,
|
|
215
|
-
messages=
|
|
216
|
-
{"role": "system", "content": "You are a helpful assistant."},
|
|
217
|
-
{"role": "user", "content": task_text},
|
|
218
|
-
],
|
|
229
|
+
messages=chat_messages,
|
|
219
230
|
temperature=0.7,
|
|
220
231
|
max_tokens=512,
|
|
221
232
|
)
|
|
@@ -235,9 +246,17 @@ def run_agent_chat(cfg):
|
|
|
235
246
|
agent_base_url = cfg.get("agentBaseURL") or ""
|
|
236
247
|
agent_api_key = cfg.get("agentApiKey") or "local"
|
|
237
248
|
agent_model_id = cfg.get("agentModelId") or ""
|
|
249
|
+
# Optional dedicated coding/reasoning model for the CodeAgent's tool-use loop.
|
|
250
|
+
# Routing, plain replies and summarization stay on the chat model (better at
|
|
251
|
+
# natural language); the code model only drives http_request reasoning.
|
|
252
|
+
coding_base_url = (cfg.get("codingBaseURL") or "").strip() or agent_base_url
|
|
253
|
+
coding_model_id = (cfg.get("codingModelId") or "").strip() or agent_model_id
|
|
238
254
|
max_steps = int(cfg.get("maxSteps") or 5)
|
|
239
255
|
|
|
240
|
-
_log(
|
|
256
|
+
_log(
|
|
257
|
+
f"start model={agent_model_id!r} base={agent_base_url!r} "
|
|
258
|
+
f"codeModel={coding_model_id!r} codeBase={coding_base_url!r} maxSteps={max_steps}"
|
|
259
|
+
)
|
|
241
260
|
|
|
242
261
|
# Build task from the conversation history.
|
|
243
262
|
# Include prior USER messages as context so the agent has conversational memory,
|
|
@@ -268,7 +287,7 @@ def run_agent_chat(cfg):
|
|
|
268
287
|
|
|
269
288
|
if not needs_agent:
|
|
270
289
|
_log("router: plain chat (no HTTP needed)")
|
|
271
|
-
answer = _plain_reply(
|
|
290
|
+
answer = _plain_reply(messages, agent_base_url, agent_api_key, agent_model_id)
|
|
272
291
|
_log(f"plain reply: {len(answer)} chars")
|
|
273
292
|
_emit({"type": "final", "text": answer})
|
|
274
293
|
return
|
|
@@ -282,20 +301,24 @@ def run_agent_chat(cfg):
|
|
|
282
301
|
tool_hint = (
|
|
283
302
|
"You have ONE built-in function:\n"
|
|
284
303
|
" `http_request(method, url, headers='', body='', username='', password='')`\n"
|
|
285
|
-
"
|
|
286
|
-
"
|
|
287
|
-
"
|
|
288
|
-
"
|
|
289
|
-
" response = http_request('GET',
|
|
304
|
+
"\n"
|
|
305
|
+
"RETURN FORMAT: 'HTTP 200\\n{body}' — first line is 'HTTP <code>', body follows.\n"
|
|
306
|
+
"\n"
|
|
307
|
+
"BASIC AUTH — ALWAYS use username= and password=, NEVER construct headers manually:\n"
|
|
308
|
+
" response = http_request('GET', 'https://api.example.com/data',\n"
|
|
309
|
+
" username='alice@example.com', password='secret123')\n"
|
|
310
|
+
" final_answer(response)\n"
|
|
311
|
+
"The function handles base64 encoding automatically. NEVER write 'Basic ' + anything.\n"
|
|
312
|
+
"\n"
|
|
313
|
+
"BEARER TOKEN — use headers:\n"
|
|
314
|
+
" response = http_request('GET', url, headers='{\"Authorization\": \"Bearer TOKEN\"}')\n"
|
|
290
315
|
" final_answer(response)\n"
|
|
291
|
-
"
|
|
292
|
-
"
|
|
293
|
-
"-
|
|
294
|
-
"
|
|
295
|
-
"-
|
|
296
|
-
"-
|
|
297
|
-
"- If http_request returns an error (starts with 'Error:'), try a different URL.\n"
|
|
298
|
-
"- Python's `datetime` module is available for date/time tasks.\n"
|
|
316
|
+
"\n"
|
|
317
|
+
"RULES:\n"
|
|
318
|
+
"- Pass response DIRECTLY to final_answer — do NOT split, parse, or index the string.\n"
|
|
319
|
+
"- If the response starts with 'HTTP 2' it SUCCEEDED — call final_answer immediately.\n"
|
|
320
|
+
"- If http_request returns 'Error:' or HTTP 4xx/5xx, try a different approach.\n"
|
|
321
|
+
"- Python's datetime module is available for date/time tasks (no HTTP needed).\n"
|
|
299
322
|
"- Do NOT put final_answer outside the code block.\n\n"
|
|
300
323
|
)
|
|
301
324
|
task_with_hint = tool_hint + "Task: " + task_text
|
|
@@ -385,8 +408,8 @@ def run_agent_chat(cfg):
|
|
|
385
408
|
|
|
386
409
|
try:
|
|
387
410
|
model = OpenAIServerModel(
|
|
388
|
-
model_id=
|
|
389
|
-
api_base=
|
|
411
|
+
model_id=coding_model_id,
|
|
412
|
+
api_base=coding_base_url,
|
|
390
413
|
api_key=agent_api_key,
|
|
391
414
|
)
|
|
392
415
|
agent = CodeAgent(
|
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.81",
|
|
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",
|