feat(seo): wire autofill into publish path behind SEO_AUTOFILL (default off, dry-run support)
Build & Deploy ResearchOwl / build-and-push (push) Successful in 7s

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
ChemaVX
2026-06-25 14:14:39 +00:00
co-authored by Claude Opus 4.8
parent 89aa8d6030
commit 7a995da88f
4 changed files with 870 additions and 52 deletions
+18
View File
@@ -48,6 +48,15 @@ class Settings(BaseSettings):
ghost_url_en: str = Field("", env="GHOST_URL_EN")
ghost_api_key_en: str = Field("", env="GHOST_API_KEY_EN")
# SEO autofill — "off" | "on" | "dryrun" (default off).
# off = today's exact behavior (bare draft, no second LLM call).
# on = adds best-effort meta/OG/Twitter/tags/internal-links to the DRAFT
# (status stays "draft" — NEVER auto-publishes; see src/seo/autofill.py).
# dryrun = runs the full pipeline + reports the proposed SEO to Telegram, but
# writes a BARE draft (no seo fields), for inspection before trusting
# the write path. A `/generate blog en dry` arg forces dryrun per-call.
seo_autofill: str = Field("off", env="SEO_AUTOFILL")
# Alerts
cost_alert_threshold: float = Field(0.15, env="COST_ALERT_THRESHOLD")
@@ -61,6 +70,15 @@ class Settings(BaseSettings):
return []
return [int(uid.strip()) for uid in self.telegram_allowed_users.split(",") if uid.strip()]
@property
def seo_autofill_enabled(self) -> bool:
"""True when autofill should run (either live 'on' or 'dryrun')."""
return (self.seo_autofill or "").strip().lower() in ("on", "true", "1", "yes", "dryrun")
@property
def seo_autofill_dryrun(self) -> bool:
return (self.seo_autofill or "").strip().lower() == "dryrun"
class Config:
env_file = ".env"