@tiens.nguyen/gonext-local-worker 1.0.317 → 1.0.318
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 +56 -20
- package/package.json +1 -1
package/gonext_agent_chat.py
CHANGED
|
@@ -3177,15 +3177,32 @@ def run_agent_chat(cfg):
|
|
|
3177
3177
|
# Multi-step ReAct loop (thinking agent): the agent may take several
|
|
3178
3178
|
# Thought → tool → Observation steps and then call final_answer() itself. This
|
|
3179
3179
|
# replaced the old strict single-shot (max_steps=1) once a stronger coding model
|
|
3180
|
-
# (Qwen3-14B class) made real multi-step reasoning reliable.
|
|
3181
|
-
#
|
|
3182
|
-
#
|
|
3180
|
+
# (Qwen3-14B class) made real multi-step reasoning reliable. The default budget is
|
|
3181
|
+
# BACKEND-AWARE (a cloud OpenAI-compatible coder is stronger and cheaper-per-step than
|
|
3182
|
+
# a small local model, so it gets more room; a local Ollama coder gets a middle budget;
|
|
3183
|
+
# local MLX keeps the original tight default). Overridable via cfg.maxSteps.
|
|
3184
|
+
# The provide_final_answer override below is only the exhaustion fallback.
|
|
3185
|
+
#
|
|
3186
|
+
# Resolve the effective backend the SAME way as the model setup further down
|
|
3187
|
+
# (explicit kind wins; Auto sniffs the URL) so the budgets match the coder that runs.
|
|
3188
|
+
if coding_kind == "openai":
|
|
3189
|
+
_budget_is_ollama = False
|
|
3190
|
+
elif coding_kind == "ollama":
|
|
3191
|
+
_budget_is_ollama = True
|
|
3192
|
+
else:
|
|
3193
|
+
_budget_is_ollama = _is_ollama_server(coding_base_url)
|
|
3194
|
+
if coding_kind == "openai":
|
|
3195
|
+
_default_budget, _ws_budget = 20, 40 # OpenAI-compatible coder
|
|
3196
|
+
elif _budget_is_ollama:
|
|
3197
|
+
_default_budget, _ws_budget = 10, 20 # Ollama coder
|
|
3198
|
+
else:
|
|
3199
|
+
_default_budget, _ws_budget = 5, 12 # local MLX / Auto — original defaults
|
|
3183
3200
|
try:
|
|
3184
|
-
max_steps = int(cfg.get("maxSteps") or
|
|
3201
|
+
max_steps = int(cfg.get("maxSteps") or _default_budget)
|
|
3185
3202
|
except (TypeError, ValueError):
|
|
3186
|
-
max_steps =
|
|
3203
|
+
max_steps = _default_budget
|
|
3187
3204
|
if max_steps < 1:
|
|
3188
|
-
max_steps =
|
|
3205
|
+
max_steps = _default_budget
|
|
3189
3206
|
|
|
3190
3207
|
# Max web_search + fetch_url calls per task (user-configurable in web Settings →
|
|
3191
3208
|
# Agent). Default 10; past it the retrieval tools refuse and steer to finish.
|
|
@@ -3392,11 +3409,12 @@ def run_agent_chat(cfg):
|
|
|
3392
3409
|
_log(f"active workspace ignored (error resolving '{_aw_raw}'): {_e}")
|
|
3393
3410
|
if _WS_AVAILABLE:
|
|
3394
3411
|
_log(f"workspaces: {[(w['name'], w['path'], w['allowRun']) for w in _WS_ROOTS]}")
|
|
3395
|
-
# Coding tasks are edit→test→fix loops —
|
|
3396
|
-
# budget
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3412
|
+
# Coding tasks are edit→test→fix loops — the normal budget is too tight. Bump to
|
|
3413
|
+
# the backend-aware workspace budget (openai 40 / ollama 20 / MLX 12) when
|
|
3414
|
+
# workspaces are registered, unless the payload set one explicitly.
|
|
3415
|
+
if not cfg.get("maxSteps") and max_steps < _ws_budget:
|
|
3416
|
+
max_steps = _ws_budget
|
|
3417
|
+
_log(f"workspace registered → step budget raised to {_ws_budget} (no explicit maxSteps)")
|
|
3400
3418
|
# Auto-test adds a verify → fix → re-test cycle on top of the work itself, so give
|
|
3401
3419
|
# it more room (unless the user pinned a budget). Kept modest so a stuck test loop
|
|
3402
3420
|
# still terminates rather than burning a huge budget.
|
|
@@ -5163,14 +5181,27 @@ def run_agent_chat(cfg):
|
|
|
5163
5181
|
# Ollama honors it). Harmless if the server ignores it — usage stays 0.
|
|
5164
5182
|
completion_kwargs["stream_options"] = {"include_usage": True}
|
|
5165
5183
|
content, role, in_tok, out_tok, reasoning_len = self._run_stream(completion_kwargs)
|
|
5166
|
-
# Empty-turn retry: reasoning models (gemma4 on Ollama) sometimes spend the
|
|
5167
|
-
# WHOLE turn in the reasoning channel and emit no content → smolagents parses an
|
|
5168
|
-
# empty tool call and WASTES the step (seen live: 2 of 5 steps burned this way).
|
|
5169
5184
|
# Retry ONCE with a hard "emit the code block now" directive appended to the
|
|
5170
5185
|
# already-prepared API messages (plain dicts — no smolagents format guessing).
|
|
5171
|
-
|
|
5172
|
-
|
|
5173
|
-
|
|
5186
|
+
# Two triggers:
|
|
5187
|
+
# (1) EMPTY content — reasoning models (gemma4 on Ollama) sometimes spend the
|
|
5188
|
+
# WHOLE turn in the reasoning channel and emit no message.
|
|
5189
|
+
# (2) BROKEN code attempt — content has a dangling <code>/</code> tag but NO
|
|
5190
|
+
# valid pair, and #111 recovery found nothing in reasoning either (seen
|
|
5191
|
+
# live with Kimi K3: content = "Thought: …</code>", reasoning is plain
|
|
5192
|
+
# planning prose with no code). Without this, smolagents shows the ugly
|
|
5193
|
+
# "regex pattern <code> was not found" error and burns the step before its
|
|
5194
|
+
# own retry recovers. A finished PROSE answer has NO code tags, so it never
|
|
5195
|
+
# trips this — it flows to the auto-wrap path in generate() untouched.
|
|
5196
|
+
_pair_re = r"<code[^>]*>[\s\S]*?</code>"
|
|
5197
|
+
_has_pair = re.search(_pair_re, content or "", re.I) is not None
|
|
5198
|
+
_broken_code = (not _has_pair) and (
|
|
5199
|
+
re.search(r"</?code[\s>/]", content or "", re.I) is not None
|
|
5200
|
+
)
|
|
5201
|
+
if not content.strip() or _broken_code:
|
|
5202
|
+
why = "empty-content" if not content.strip() else "dangling code tag, no valid block"
|
|
5203
|
+
_log(f"{why} turn (reasoning={reasoning_len} chars) → retrying once with a "
|
|
5204
|
+
"'code now' directive")
|
|
5174
5205
|
_emit({"type": "step",
|
|
5175
5206
|
"text": "Model produced only analysis — nudging it to write the action…"})
|
|
5176
5207
|
retry_kwargs = dict(completion_kwargs)
|
|
@@ -5178,10 +5209,15 @@ def run_agent_chat(cfg):
|
|
|
5178
5209
|
{"role": "user", "content": self._CODE_NOW_DIRECTIVE}
|
|
5179
5210
|
]
|
|
5180
5211
|
r_content, r_role, r_in, r_out, _ = self._run_stream(retry_kwargs)
|
|
5181
|
-
|
|
5212
|
+
r_has_pair = re.search(_pair_re, r_content or "", re.I) is not None
|
|
5213
|
+
# Use the retry when it yields a real code block, or (empty original) any
|
|
5214
|
+
# content. If the retry is still broken and we HAD a Thought, keep the
|
|
5215
|
+
# original and let smolagents' own retry take it from here — no regression.
|
|
5216
|
+
if r_has_pair or (not content.strip() and r_content.strip()):
|
|
5182
5217
|
content, role = r_content, r_role
|
|
5183
|
-
|
|
5184
|
-
|
|
5218
|
+
in_tok = r_in or in_tok
|
|
5219
|
+
# Count the retry call's output either way — it was generated/billed (#112).
|
|
5220
|
+
out_tok += r_out
|
|
5185
5221
|
if stop_sequences and not self.supports_stop_parameter:
|
|
5186
5222
|
from smolagents.models import remove_content_after_stop_sequences
|
|
5187
5223
|
content = remove_content_after_stop_sequences(content, stop_sequences)
|
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.318",
|
|
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",
|