@tiens.nguyen/gonext-local-worker 1.0.75 → 1.0.77

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.
@@ -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
- """Ask the local model if this task needs an HTTP request.
122
- Returns True → run full agent; False → plain chat reply."""
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,12 +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 YES or NO only, no punctuation. "
132
- "Answer NO if the task can be solved with Python stdlib (datetime, math, etc.) "
133
- "or is just conversation. Answer YES only if it requires calling an EXTERNAL URL or web API."
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."
134
157
  )},
135
158
  {"role": "user", "content": (
136
- f"Does this task specifically require making an HTTP request to an external URL or web API?\n\n"
159
+ f"Does this task require fetching data from an external network source?\n\n"
137
160
  f"Task: {task_text}\n\nYES or NO:"
138
161
  )},
139
162
  ],
@@ -141,7 +164,7 @@ def _route(task_text: str, base_url: str, api_key: str, model_id: str) -> bool:
141
164
  temperature=0,
142
165
  )
143
166
  answer = (resp.choices[0].message.content or "").strip().upper()
144
- _log(f"router → {answer!r}")
167
+ _log(f"router → {answer!r} (model)")
145
168
  return answer.startswith("Y")
146
169
  except Exception as e: # noqa: BLE001
147
170
  _log(f"router error: {e} — defaulting to agent")
@@ -249,9 +272,13 @@ def run_agent_chat(cfg):
249
272
  "It returns a STRING with the HTTP status and body. "
250
273
  "Call it, then immediately call `final_answer(response)` inside the same code block.\n"
251
274
  "IMPORTANT RULES:\n"
252
- "- Python's `datetime` module is available use it for date/time tasks, no HTTP needed.\n"
253
- "- If http_request returns an error starting with 'Error:', the URL failed. "
254
- "Do NOT retry the same URL. Try a DIFFERENT URL or API, or use Python stdlib.\n"
275
+ "- `headers` must be a JSON string, e.g. headers='{\"Content-Type\": \"application/json\"}'\n"
276
+ "- For Basic Auth: import base64; "
277
+ "creds = base64.b64encode(b'user:password').decode(); "
278
+ "headers = '{\"Authorization\": \"Basic ' + creds + '\"}'\n"
279
+ "- For Bearer token: headers='{\"Authorization\": \"Bearer YOUR_TOKEN\"}'\n"
280
+ "- Python's `datetime` and `base64` modules are available.\n"
281
+ "- If http_request returns an error starting with 'Error:', do NOT retry the same URL. Try a different one.\n"
255
282
  "- Do NOT put final_answer outside the code block.\n\n"
256
283
  )
257
284
  task_with_hint = tool_hint + "Task: " + task_text
@@ -340,7 +367,7 @@ def run_agent_chat(cfg):
340
367
  max_steps=max_steps,
341
368
  step_callbacks=[step_callback],
342
369
  executor_kwargs={"timeout_seconds": 60},
343
- additional_authorized_imports=["json", "urllib", "urllib.request", "urllib.error"],
370
+ additional_authorized_imports=["json", "base64", "urllib", "urllib.request", "urllib.error"],
344
371
  )
345
372
  with contextlib.redirect_stdout(sys.stderr):
346
373
  result = agent.run(task_with_hint)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tiens.nguyen/gonext-local-worker",
3
- "version": "1.0.75",
3
+ "version": "1.0.77",
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",