@tiens.nguyen/gonext-local-worker 1.0.74 → 1.0.76
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_agent_chat.py +53 -7
- package/package.json +1 -1
package/gonext_agent_chat.py
CHANGED
|
@@ -117,9 +117,31 @@ def _summarise_step(step_log):
|
|
|
117
117
|
return label + (" | ".join(parts) if parts else "thinking…")
|
|
118
118
|
|
|
119
119
|
|
|
120
|
+
# Keywords that strongly indicate the user wants to make an HTTP/network request,
|
|
121
|
+
# regardless of what the final output is (time, text, data, etc.).
|
|
122
|
+
_AGENT_KEYWORDS = re.compile(
|
|
123
|
+
r"\b("
|
|
124
|
+
r"request|fetch|call|hit|ping|curl|wget|GET|POST|PUT|DELETE|PATCH"
|
|
125
|
+
r"|api|endpoint|url|http|https"
|
|
126
|
+
r"|external\s+source|external\s+api|external\s+service"
|
|
127
|
+
r"|web\s+service|rest\s+api|rest\s+call"
|
|
128
|
+
r"|download|scrape|crawl"
|
|
129
|
+
r")\b",
|
|
130
|
+
re.IGNORECASE,
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
|
|
120
134
|
def _route(task_text: str, base_url: str, api_key: str, model_id: str) -> bool:
|
|
121
|
-
"""
|
|
122
|
-
|
|
135
|
+
"""Decide if the task needs the HTTP agent (True) or a plain chat reply (False).
|
|
136
|
+
|
|
137
|
+
Fast-path: if the user explicitly mentions network/request keywords → agent.
|
|
138
|
+
Otherwise: ask the model to classify.
|
|
139
|
+
"""
|
|
140
|
+
# Fast-path: explicit HTTP/network intent overrides the model classifier.
|
|
141
|
+
if _AGENT_KEYWORDS.search(task_text):
|
|
142
|
+
_log(f"router → YES (keyword match)")
|
|
143
|
+
return True
|
|
144
|
+
|
|
123
145
|
try:
|
|
124
146
|
from openai import OpenAI
|
|
125
147
|
client = OpenAI(base_url=base_url, api_key=api_key or "local",
|
|
@@ -128,10 +150,13 @@ def _route(task_text: str, base_url: str, api_key: str, model_id: str) -> bool:
|
|
|
128
150
|
model=model_id,
|
|
129
151
|
messages=[
|
|
130
152
|
{"role": "system", "content": (
|
|
131
|
-
"You are a task classifier. Reply
|
|
153
|
+
"You are a task classifier. Reply YES or NO only, no punctuation.\n"
|
|
154
|
+
"Answer YES if the task requires fetching data from an external network source "
|
|
155
|
+
"(URL, API, website, web service, or any remote server).\n"
|
|
156
|
+
"Answer NO if it can be solved entirely with Python stdlib, math, or is just conversation."
|
|
132
157
|
)},
|
|
133
158
|
{"role": "user", "content": (
|
|
134
|
-
f"Does this task require
|
|
159
|
+
f"Does this task require fetching data from an external network source?\n\n"
|
|
135
160
|
f"Task: {task_text}\n\nYES or NO:"
|
|
136
161
|
)},
|
|
137
162
|
],
|
|
@@ -139,7 +164,7 @@ def _route(task_text: str, base_url: str, api_key: str, model_id: str) -> bool:
|
|
|
139
164
|
temperature=0,
|
|
140
165
|
)
|
|
141
166
|
answer = (resp.choices[0].message.content or "").strip().upper()
|
|
142
|
-
_log(f"router → {answer!r}")
|
|
167
|
+
_log(f"router → {answer!r} (model)")
|
|
143
168
|
return answer.startswith("Y")
|
|
144
169
|
except Exception as e: # noqa: BLE001
|
|
145
170
|
_log(f"router error: {e} — defaulting to agent")
|
|
@@ -246,10 +271,17 @@ def run_agent_chat(cfg):
|
|
|
246
271
|
"You have ONE built-in function: `http_request(method, url, headers='', body='')`. "
|
|
247
272
|
"It returns a STRING with the HTTP status and body. "
|
|
248
273
|
"Call it, then immediately call `final_answer(response)` inside the same code block.\n"
|
|
249
|
-
"
|
|
274
|
+
"IMPORTANT RULES:\n"
|
|
275
|
+
"- Python's `datetime` module is available — use it for date/time tasks, no HTTP needed.\n"
|
|
276
|
+
"- If http_request returns an error starting with 'Error:', the URL failed. "
|
|
277
|
+
"Do NOT retry the same URL. Try a DIFFERENT URL or API, or use Python stdlib.\n"
|
|
278
|
+
"- Do NOT put final_answer outside the code block.\n\n"
|
|
250
279
|
)
|
|
251
280
|
task_with_hint = tool_hint + "Task: " + task_text
|
|
252
281
|
|
|
282
|
+
# Track URLs that have already failed so we don't retry dead endpoints across steps.
|
|
283
|
+
_failed_urls: set = set()
|
|
284
|
+
|
|
253
285
|
@tool
|
|
254
286
|
def http_request(method: str, url: str, headers: str = "", body: str = "") -> str:
|
|
255
287
|
"""Perform an HTTP request and return the status code and body preview.
|
|
@@ -266,11 +298,25 @@ def run_agent_chat(cfg):
|
|
|
266
298
|
parsed_headers = json.loads(headers)
|
|
267
299
|
except Exception: # noqa: BLE001
|
|
268
300
|
pass
|
|
269
|
-
|
|
301
|
+
url_key = f"{method.upper()}:{url}"
|
|
302
|
+
if url_key in _failed_urls:
|
|
303
|
+
msg = f"Error: {url} already failed — try a different URL or use Python stdlib."
|
|
304
|
+
_emit({"type": "step", "text": f"HTTP {method.upper()} {url} → (skipped, already failed)"})
|
|
305
|
+
_log(f"http_request skipped (already failed): {url_key}")
|
|
306
|
+
return msg
|
|
270
307
|
result = _http_request_impl(method, url, parsed_headers, body or None)
|
|
271
308
|
if result.startswith("Error:"):
|
|
309
|
+
# Retry once for flaky connections (e.g. gorok tunnels).
|
|
272
310
|
_log(f"http_request retry {method.upper()} {url}")
|
|
273
311
|
result = _http_request_impl(method, url, parsed_headers, body or None)
|
|
312
|
+
if result.startswith("Error:"):
|
|
313
|
+
# Both attempts failed — mark URL as dead so model tries something else.
|
|
314
|
+
_failed_urls.add(url_key)
|
|
315
|
+
result = (
|
|
316
|
+
f"{result}\n"
|
|
317
|
+
"Note: This URL failed twice. Do NOT retry it. "
|
|
318
|
+
"Try a DIFFERENT URL or use Python's datetime/math/etc. module instead."
|
|
319
|
+
)
|
|
274
320
|
status_line = result.split("\n")[0][:150] if result else "no response"
|
|
275
321
|
_emit({"type": "step", "text": f"HTTP {method.upper()} {url} → {status_line}"})
|
|
276
322
|
_log(f"http_request {method.upper()} {url} → {result[:80]}")
|
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.76",
|
|
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",
|