@tiens.nguyen/gonext-local-worker 1.0.142 → 1.0.143

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.
@@ -482,6 +482,12 @@ def _summarise_step(step_log):
482
482
  err = str(error)
483
483
  if "Import of" in err and "not allowed" in err:
484
484
  parts.append("→ (import blocked — using http_request tool instead)")
485
+ elif "reached max steps" in err.lower() or "max steps" in err.lower():
486
+ # NOT a user-facing failure: hitting the step budget triggers our
487
+ # provide_final_answer override, which ALWAYS delivers a synthesized answer
488
+ # (a rendered PDF, the last tool result, or a plain reply). Surfacing the raw
489
+ # "Error: Reached max steps." made a successful run look failed (task #10).
490
+ parts.append("→ Wrapping up (reached step budget)…")
485
491
  else:
486
492
  parts.append(f"→ Error: {err[:120]}")
487
493
 
@@ -634,14 +640,23 @@ def _strip_tool_tags(text: str) -> str:
634
640
 
635
641
  _THINK_BLOCK = re.compile(r"<think>.*?</think>", re.DOTALL | re.IGNORECASE)
636
642
 
637
- # Whitespace/attr variants of smolagents' code-block tags. Weak models routinely
638
- # emit "<code >" (trailing space), "< code >", "</ code>", or an uppercase form
639
- # none of which match smolagents' exact "<code>(.*?)</code>" parser, so EVERY step
640
- # fails with "regex pattern <code>(.*?)</code> was not found" and the run burns all
641
- # its steps. Normalizing the tags to the canonical form before the parser sees them
642
- # turns that spiral into a normal, parseable step.
643
- _CODE_OPEN_TAG = re.compile(r"<\s*code(?:\s[^>]*)?\s*>", re.IGNORECASE)
643
+ # Malformed variants of smolagents' code-block tags. Weak coding models routinely
644
+ # emit "<code >" (trailing space), "< code >", "</ code>", "<CODE>", OR worst
645
+ # "<code print(x) </code>" where the OPENING tag is missing its ">" entirely. None
646
+ # match smolagents' exact "<code>(.*?)</code>" parser, so EVERY step fails with
647
+ # "regex pattern <code>(.*?)</code> was not found" and the run burns all its steps.
648
+ # Normalizing the tags to canonical form before the parser sees them turns that
649
+ # spiral into a normal, parseable step.
644
650
  _CODE_CLOSE_TAG = re.compile(r"<\s*/\s*code\s*>", re.IGNORECASE)
651
+ # A well-formed-ISH open tag that DOES have a ">": "<code>", "<code >", "< code >",
652
+ # "<CODE>", "<code class=py>". Critically the attr span is [^<>] (NOT [^>]) so it can
653
+ # never swallow across the "<" of a following "</code>" — the bug that collapsed
654
+ # "<code print(x) </code>" to a bare "<code>" and destroyed the code.
655
+ _CODE_OPEN_TAG = re.compile(r"<\s*code\b[^<>]*>", re.IGNORECASE)
656
+ # An open tag MISSING its ">": "<code" not immediately followed by ">". \b keeps it
657
+ # from matching "<codeblock"/"<coder"; the lookahead skips the already-canonical
658
+ # "<code>" so this pass only rescues the no-">" case.
659
+ _CODE_OPEN_NO_GT = re.compile(r"<\s*code\b(?!>)", re.IGNORECASE)
645
660
  # Fallback: a markdown code fence (```py / ```python / ```) when the model ignored
646
661
  # the tag convention entirely. Captures the fenced body so we can re-wrap it.
647
662
  _MD_FENCE_BLOCK = re.compile(
@@ -652,18 +667,25 @@ _MD_FENCE_BLOCK = re.compile(
652
667
  def _normalize_code_tags(text: str) -> str:
653
668
  """Coerce a model reply's code-block delimiters to smolagents' exact <code>…</code>.
654
669
 
655
- Handles the two failure modes seen live with weak coding models:
656
- 1. tag whitespace/case: "<code >", "< code >", "</ code>", "<CODE>" "<code>".
657
- 2. markdown fences instead of tags: ```py … ``` → <code> </code> (only when
658
- no <code> tag is present after step 1, so we don't touch code that legitimately
659
- contains backticks inside a real <code> block).
660
- Returns text unchanged when it already parses cleanly."""
670
+ Handles the failure modes seen live with weak coding models:
671
+ 1. close-tag variants: "</ code>", "< / code >" "</code>" (done FIRST so the
672
+ open-tag pass has a canonical "<" boundary to stop at).
673
+ 2. open-tag-with-">": "<code >", "< code >", "<CODE>", "<code attr>" "<code>".
674
+ 3. open-tag-missing-">": "<code print(x) </code>" → "<code> print(x) </code>".
675
+ 4. markdown fences instead of tags: ```py … ``` → <code>…</code> (only when no
676
+ <code> tag is present, so we don't touch backticks inside a real <code> block).
677
+ 5. opened-but-never-closed (exactly one "<code>", no "</code>"): append "</code>"
678
+ so the parser can still extract the code instead of failing the whole step.
679
+ Idempotent — already-correct "<code>…</code>" is returned unchanged."""
661
680
  if not text:
662
681
  return text
663
- fixed = _CODE_OPEN_TAG.sub("<code>", text)
664
- fixed = _CODE_CLOSE_TAG.sub("</code>", fixed)
682
+ fixed = _CODE_CLOSE_TAG.sub("</code>", text)
683
+ fixed = _CODE_OPEN_TAG.sub("<code>", fixed)
684
+ fixed = _CODE_OPEN_NO_GT.sub("<code>", fixed)
665
685
  if "<code>" not in fixed:
666
686
  fixed = _MD_FENCE_BLOCK.sub(lambda m: f"<code>\n{m.group(1)}</code>", fixed, count=1)
687
+ if fixed.count("<code>") == 1 and "</code>" not in fixed:
688
+ fixed = fixed + "\n</code>"
667
689
  return fixed
668
690
 
669
691
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tiens.nguyen/gonext-local-worker",
3
- "version": "1.0.142",
3
+ "version": "1.0.143",
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",