diff --git a/core/orchestrator.py b/core/orchestrator.py index 5843782..9c93ab7 100644 --- a/core/orchestrator.py +++ b/core/orchestrator.py @@ -205,9 +205,14 @@ def llm_chat(prompt: str, model: str = "qwen3.5:4b-mlx", host: str = OLLAMA_MACB result = r.json() if "message" in result: content = result["message"].get("content", "") - # ornith puts output in 'thinking' when content is empty + # ornith puts output in 'thinking' when content is empty. + # WARNING: 'thinking' is chain-of-thought reasoning, NOT article text. + # Only fall back to it for JSON/short tasks, never long-form prose. if not content: content = result["message"].get("thinking", "") + if content: + log.warning(f"LLM {model} returned empty content — fell back to 'thinking' field ({len(content)} chars). " + f"Verify this is real output, not chain-of-thought.") if content: return content if "error" in result: diff --git a/sites/_engine/app.py b/sites/_engine/app.py index b3dce3b..1eec3ed 100644 --- a/sites/_engine/app.py +++ b/sites/_engine/app.py @@ -10,6 +10,24 @@ from pathlib import Path from datetime import datetime from flask import Flask, request, jsonify, render_template_string, g, abort, Response +try: + import markdown as _md +except ImportError: + _md = None + + +def md_to_html(text): + """Convert Markdown to HTML for article rendering.""" + if not text: + return "" + if _md is not None: + return _md.markdown(text, extensions=["extra", "sane_lists"]) + # Minimal fallback (markdown lib not installed) + import re as _re + out = _re.sub(r"^#{1,6}\s+(.+)$", r"

\1

", text, flags=_re.M) + out = _re.sub(r"^\*\*(.+?)\*\*$", r"\1", out, flags=_re.M) + return "

" + out.replace("\n\n", "

").replace("\n", "
") + "

" + # ─── Config ──────────────────────────────────────────────────────── VERTICAL = os.environ.get("PUBLISHER_VERTICAL", "guides") DOMAIN = f"{VERTICAL}.thetempleofdoom.com" @@ -520,8 +538,10 @@ def api_publish(): slug = data.get("slug", "") title = data.get("title", "") - content_html = data.get("content_html", data.get("content_md", "")) - content_md = data.get("content_md", "") + content_md = data.get("content_md") or data.get("content") or "" + content_html = data.get("content_html", "") + if not content_html and content_md: + content_html = md_to_html(content_md) excerpt = data.get("excerpt", data.get("seo_description", "")) seo_title = data.get("seo_title", title) seo_description = data.get("seo_description", "") @@ -1113,7 +1133,7 @@ ARTICLE_TEMPLATE = """
- {{ article.content_html|safe }} + {{ (article.content_md or article.content_html)|md|safe }}