@tiens.nguyen/gonext-local-worker 1.0.95 β 1.0.97
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 +41 -18
- package/package.json +1 -1
package/gonext_agent_chat.py
CHANGED
|
@@ -361,50 +361,72 @@ def _strip_tool_tags(text: str) -> str:
|
|
|
361
361
|
|
|
362
362
|
|
|
363
363
|
_PDF_INSTALL_HINT = (
|
|
364
|
-
"PDF engine not installed on the worker.
|
|
365
|
-
"
|
|
364
|
+
"PDF engine not installed on the worker. On macOS:\n"
|
|
365
|
+
" brew install pango libffi\n"
|
|
366
|
+
" python3 -m pip install weasyprint markdown\n"
|
|
367
|
+
"(optional, for color emoji/flags: brew install --cask font-noto-color-emoji)\n"
|
|
366
368
|
"then restart the worker. (See the Instructions page in the web app.)"
|
|
367
369
|
)
|
|
368
370
|
|
|
371
|
+
# Font stack with color-emoji fallbacks last, so WeasyPrint resolves emoji/flag
|
|
372
|
+
# codepoints (π πΏπ¦) to a color font per-glyph while text uses a clean sans-serif.
|
|
373
|
+
_PDF_FONT_STACK = (
|
|
374
|
+
"'Helvetica Neue', Helvetica, Arial, 'DejaVu Sans', "
|
|
375
|
+
"'Noto Color Emoji', 'Apple Color Emoji', sans-serif"
|
|
376
|
+
)
|
|
377
|
+
|
|
369
378
|
|
|
370
379
|
def _render_pdf_bytes(markdown_text: str, title: str = "") -> bytes:
|
|
371
|
-
"""Render Markdown text to PDF bytes using
|
|
380
|
+
"""Render Markdown text to PDF bytes using WeasyPrint (renders color emoji/flags).
|
|
372
381
|
|
|
373
|
-
|
|
382
|
+
Requires the WeasyPrint system libs (pango/cairo via Homebrew on macOS). Raises
|
|
383
|
+
RuntimeError with an install hint if the engine/libs aren't available, or on a
|
|
374
384
|
render failure. The model is expected to pass already-formatted Markdown.
|
|
375
385
|
"""
|
|
376
386
|
try:
|
|
377
387
|
import markdown as _md
|
|
378
|
-
from
|
|
379
|
-
except Exception: # noqa: BLE001 β missing
|
|
388
|
+
from weasyprint import HTML as _HTML # pulls pango/cairo via cffi at import
|
|
389
|
+
except Exception: # noqa: BLE001 β missing python pkg OR system libs (cffi OSError)
|
|
380
390
|
raise RuntimeError(_PDF_INSTALL_HINT)
|
|
381
391
|
|
|
382
392
|
body_html = _md.markdown(
|
|
383
393
|
markdown_text or "",
|
|
384
394
|
extensions=["extra", "sane_lists", "tables", "nl2br"],
|
|
385
395
|
)
|
|
386
|
-
safe_title = (title or "Document").strip()
|
|
387
396
|
html = (
|
|
388
397
|
"<html><head><meta charset='utf-8'><style>"
|
|
389
398
|
"@page { size: A4; margin: 2cm; }"
|
|
390
|
-
"body { font-family:
|
|
399
|
+
f"body {{ font-family: {_PDF_FONT_STACK}; font-size: 11pt; line-height: 1.5; color: #18181b; }}"
|
|
391
400
|
"h1 { font-size: 20pt; margin: 0 0 12pt; }"
|
|
392
401
|
"h2 { font-size: 15pt; margin: 16pt 0 8pt; }"
|
|
393
402
|
"h3 { font-size: 12pt; margin: 12pt 0 6pt; }"
|
|
394
|
-
"code, pre { font-family: Courier, monospace; background: #f4f4f5; }"
|
|
395
|
-
"pre { padding: 8pt; }"
|
|
403
|
+
"code, pre { font-family: 'DejaVu Sans Mono', Courier, monospace; background: #f4f4f5; }"
|
|
404
|
+
"pre { padding: 8pt; white-space: pre-wrap; }"
|
|
396
405
|
"table { border-collapse: collapse; width: 100%; }"
|
|
397
406
|
"th, td { border: 1px solid #d4d4d8; padding: 4pt 6pt; text-align: left; }"
|
|
398
407
|
"</style></head><body>"
|
|
399
408
|
f"{body_html}"
|
|
400
409
|
"</body></html>"
|
|
401
410
|
)
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
411
|
+
try:
|
|
412
|
+
return _HTML(string=html).write_pdf()
|
|
413
|
+
except Exception as e: # noqa: BLE001 β surface a clean render failure
|
|
414
|
+
raise RuntimeError(f"PDF rendering failed (WeasyPrint: {type(e).__name__}: {str(e)[:160]}).")
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
def _ssl_context():
|
|
418
|
+
"""SSL context backed by certifi's CA bundle.
|
|
419
|
+
|
|
420
|
+
macOS Python (python.org / Homebrew) doesn't use the system keychain, so urllib's
|
|
421
|
+
default verification fails with CERTIFICATE_VERIFY_FAILED. certifi ships with the
|
|
422
|
+
openai/httpx stack the worker already depends on.
|
|
423
|
+
"""
|
|
424
|
+
import ssl
|
|
425
|
+
try:
|
|
426
|
+
import certifi
|
|
427
|
+
return ssl.create_default_context(cafile=certifi.where())
|
|
428
|
+
except Exception: # noqa: BLE001 β fall back to system defaults
|
|
429
|
+
return ssl.create_default_context()
|
|
408
430
|
|
|
409
431
|
|
|
410
432
|
def _pdf_upload_via_api(api_base: str, worker_key: str, file_name: str,
|
|
@@ -416,6 +438,7 @@ def _pdf_upload_via_api(api_base: str, worker_key: str, file_name: str,
|
|
|
416
438
|
import urllib.request as _u
|
|
417
439
|
import urllib.error as _ue
|
|
418
440
|
|
|
441
|
+
ctx = _ssl_context()
|
|
419
442
|
base = (api_base or "").rstrip("/")
|
|
420
443
|
if not base or not worker_key:
|
|
421
444
|
raise RuntimeError("PDF upload is not available: worker API base/key missing.")
|
|
@@ -431,7 +454,7 @@ def _pdf_upload_via_api(api_base: str, worker_key: str, file_name: str,
|
|
|
431
454
|
method="POST",
|
|
432
455
|
)
|
|
433
456
|
try:
|
|
434
|
-
with _u.urlopen(req, timeout=30) as resp:
|
|
457
|
+
with _u.urlopen(req, timeout=30, context=ctx) as resp:
|
|
435
458
|
ref = json.loads(resp.read().decode("utf-8"))
|
|
436
459
|
except _ue.HTTPError as e: # noqa: PERF203
|
|
437
460
|
detail = e.read().decode("utf-8", "replace")[:300]
|
|
@@ -453,7 +476,7 @@ def _pdf_upload_via_api(api_base: str, worker_key: str, file_name: str,
|
|
|
453
476
|
method="PUT",
|
|
454
477
|
)
|
|
455
478
|
try:
|
|
456
|
-
with _u.urlopen(put_req, timeout=60) as up:
|
|
479
|
+
with _u.urlopen(put_req, timeout=60, context=ctx) as up:
|
|
457
480
|
if up.status not in (200, 201, 204):
|
|
458
481
|
raise RuntimeError(f"S3 upload failed (HTTP {up.status}).")
|
|
459
482
|
except _ue.HTTPError as e: # noqa: PERF203
|
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.97",
|
|
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",
|