@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.
@@ -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. Install it with:\n"
365
- " python3 -m pip install xhtml2pdf markdown\n"
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 pure-Python xhtml2pdf (no system deps).
380
+ """Render Markdown text to PDF bytes using WeasyPrint (renders color emoji/flags).
372
381
 
373
- Raises RuntimeError with an install hint if the engine isn't available, or on a
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 xhtml2pdf import pisa as _pisa
379
- except Exception: # noqa: BLE001 β€” missing optional dependency
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: Helvetica, Arial, sans-serif; font-size: 11pt; line-height: 1.5; color: #18181b; }"
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
- from io import BytesIO as _BytesIO
403
- out = _BytesIO()
404
- result = _pisa.CreatePDF(src=html, dest=out, encoding="utf-8")
405
- if getattr(result, "err", 1):
406
- raise RuntimeError("PDF rendering failed (xhtml2pdf reported an error).")
407
- return out.getvalue()
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.95",
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",