Files
jsahnandClaude Fable 5 f5fa7ec70f Add a Monday-morning weekly recap briefing
No US session closes into Monday KST, so Mondays (default 07:00, cron
in the daemon with restart catch-up) now publish a weekly review built
entirely from stored data: the quotes table collapsed into week-over-
week changes and the week's daily briefing headlines as the narrative.
The recap is a BriefingResult kind="weekly" reusing MarketPayload, so
the store, verification pass, all delivery channels (Blogger title
"미국 주간 리뷰 <monday>") and the dashboard (주간 리뷰 badge) work
unchanged. Manual runs via `run-once --weekly [--date <monday>]`.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-12 23:52:31 +09:00

40 lines
1.3 KiB
Python

"""LLM provider interface. Implementations must be side-effect free apart from the HTTP call."""
from __future__ import annotations
from typing import Protocol
from us2kr.models import MarketPayload, Report, Verification, VerificationIssue
class LLMError(RuntimeError):
"""Raised when every configured model failed to produce a valid Report."""
class LLMProvider(Protocol):
def summarize(self, payload: MarketPayload) -> tuple[Report, str]:
"""Return (validated Report, model id that produced it). Raise LLMError on total failure."""
...
def summarize_weekly(self, payload: MarketPayload, week_sessions: list) -> tuple[Report, str]:
"""Weekly recap over a payload whose quotes carry week-over-week changes."""
...
def verify(
self, payload: MarketPayload, report: Report, data_message: str | None = None
) -> tuple[Verification, str]:
"""Fact-check `report` against the payload (or `data_message`). Raise LLMError on total failure."""
...
def revise(
self,
payload: MarketPayload,
report: Report,
issues: list[VerificationIssue],
*,
system_prompt: str | None = None,
data_message: str | None = None,
) -> tuple[Report, str]:
"""Return a corrected Report addressing `issues`. Raise LLMError on total failure."""
...