@tiens.nguyen/gonext-local-worker 1.0.326 → 1.0.327

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-repl.mjs CHANGED
@@ -456,6 +456,20 @@ function slashCloseSeq(line, cursor, cols) {
456
456
  `\r\x1b[${Math.min(width, PROMPT_COLS + cursor + 1)}G`
457
457
  );
458
458
  }
459
+ // A window resize reflows every row, so the overlay's row arithmetic (and the width it
460
+ // clipped to) is stale the moment it happens: rows that fit before may now wrap, which is
461
+ // precisely what made the menu stack in the first place (#109 v3). Redraw at the new width
462
+ // — the render ends with ESC[J, so a block that used to be taller leaves no orphans behind.
463
+ if (process.stdout.isTTY) {
464
+ process.stdout.on("resize", () => {
465
+ if (!slashOverlayActive) return;
466
+ try {
467
+ renderSlashOverlay(slashSel);
468
+ } catch {
469
+ closeSlashOverlay(); // never let a resize wedge the prompt
470
+ }
471
+ });
472
+ }
459
473
  if (process.stdin.isTTY) {
460
474
  process.stdin.on("keypress", (_ch, key) => {
461
475
  // An arrow-key list picker (/server) is up → ↑/↓ move the highlight, Enter chooses.
@@ -1469,6 +1469,28 @@ def _plain_reply(messages: list, base_url: str, api_key: str, model_id: str,
1469
1469
  # • a genuine model/agent error — worth the plain-reply degrade.
1470
1470
  # `str(e)` for a proxy error is the raw nginx HTML ("<html>…502 Bad Gateway…"), so match
1471
1471
  # on the status text/codes and the common connection-failure phrases.
1472
+ def _http_status_of(err):
1473
+ """The HTTP status an exception carries, or None if it isn't an HTTP error.
1474
+
1475
+ openai-python's APIStatusError exposes `.status_code` (and `.response.status_code`).
1476
+ smolagents wraps model exceptions in AgentGenerationError, so the chain is walked —
1477
+ otherwise every error reaching the turn-level handler would look status-less and fall
1478
+ back to matching on message text."""
1479
+ cur, depth = err, 0
1480
+ while cur is not None and depth < 6:
1481
+ for attr in ("status_code", "http_status", "status"):
1482
+ code = getattr(cur, attr, None)
1483
+ if isinstance(code, int) and 100 <= code <= 599:
1484
+ return code
1485
+ resp = getattr(cur, "response", None)
1486
+ code = getattr(resp, "status_code", None)
1487
+ if isinstance(code, int) and 100 <= code <= 599:
1488
+ return code
1489
+ cur = (getattr(cur, "__cause__", None) or getattr(cur, "__context__", None))
1490
+ depth += 1
1491
+ return None
1492
+
1493
+
1472
1494
  def _is_backend_overloaded(err) -> bool:
1473
1495
  """True when the model server ACCEPTED the connection but REFUSED the work because it
1474
1496
  is saturated or we are over a quota — 429 / engine_overloaded / rate limit (task #114).
@@ -1481,7 +1503,15 @@ def _is_backend_overloaded(err) -> bool:
1481
1503
  Live trigger: Moonshot returned
1482
1504
  Error code: 429 - {'error': {'message': 'The engine is currently overloaded, please
1483
1505
  try again later', 'type': 'engine_overloaded_error'}}
1484
- A local Ollama/MLX box does not produce these, so nothing keyed off this fires there."""
1506
+ A local Ollama/MLX box does not produce these, so nothing keyed off this fires there.
1507
+
1508
+ A STRUCTURED status wins when the exception carries one: a real 429 is an overload
1509
+ whatever its body says, and a real 401/500/... is NOT one even if some tool output
1510
+ quoted the words "rate limit" into the message. Only when there is no status at all
1511
+ (a bare string, a wrapped error that lost its cause) do we fall back to matching text."""
1512
+ code = _http_status_of(err)
1513
+ if code is not None:
1514
+ return code == 429
1485
1515
  s = str(err or "").lower()
1486
1516
  if "429" in s or "too many requests" in s:
1487
1517
  return True
@@ -1555,6 +1585,12 @@ def _is_backend_unavailable(err) -> bool:
1555
1585
  # down". Checked FIRST because a 429 body can also contain the word "timeout".
1556
1586
  if _is_backend_overloaded(err):
1557
1587
  return False
1588
+ # A structured 5xx IS a gateway/backend outage regardless of wording: a provider that
1589
+ # returns `Error code: 502 - {"error": …}` carries no "bad gateway" text for the
1590
+ # phrase list below to match, and would otherwise be misfiled as a generic error.
1591
+ code = _http_status_of(err)
1592
+ if code is not None:
1593
+ return code in (502, 503, 504)
1558
1594
  return (
1559
1595
  "502 bad gateway" in s
1560
1596
  or "503 service" in s
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tiens.nguyen/gonext-local-worker",
3
- "version": "1.0.326",
3
+ "version": "1.0.327",
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",