fix(api): best-effort call logging + non-JSON 200 → ModelError (final-review)
- call_log._default_write: swallow any exception from the default file/ stdout sink and report to stderr, so a log-write failure (disk full, bad permissions, misconfigured CALL_LOG_PATH) never turns a successful narration into a 500 (charter §13). Injected write= sinks (used by tests) are left to surface their own errors. - ollama_client.chat: catch ValueError alongside httpx.HTTPError in the retry loop so a 200 response with a non-JSON body (JSONDecodeError is a ValueError subclass) counts as a failed attempt and falls through to ModelError after the one retry, instead of escaping chat() uncaught (charter §12 — one retry, then ModelError, nothing else escapes). - main.py: update stale docstrings — /dm/narrate is now fully wired (routing + model call + logging); the other four roles remain stubs. Regression tests added for both fixes (TDD: watched RED, then GREEN). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3,7 +3,9 @@
|
||||
Skeleton: a health check plus the five role endpoints. Each role endpoint now
|
||||
validates the posted canon log against the contract (charter §11) before doing
|
||||
anything else — an invalid log is rejected with 422 and never reaches a prompt.
|
||||
Prompt routing, model selection, and logging land later.
|
||||
`/dm/narrate` is fully wired: prompt routing, the Ollama model call, and
|
||||
call-log logging. The other four roles remain stubs until they get the same
|
||||
treatment.
|
||||
"""
|
||||
|
||||
from fastapi import Depends, FastAPI, HTTPException
|
||||
@@ -48,8 +50,9 @@ def health() -> dict:
|
||||
|
||||
# ── Role endpoints (charter §4) ──────────────────────────────────────────────
|
||||
# The client knows these paths and nothing about which model or prompt serves
|
||||
# them. Bodies are validated against the canon log contract; the AI half is a
|
||||
# stub until prompt routing lands.
|
||||
# them. Bodies are validated against the canon log contract. /dm/narrate is
|
||||
# fully wired (routing + model call + logging); the other four roles remain
|
||||
# stubs until prompt routing, model selection, and logging land for them too.
|
||||
|
||||
|
||||
@app.post("/dm/narrate")
|
||||
|
||||
Reference in New Issue
Block a user