- Select one storage backend per instance via AGENT_STORAGE, retaining
memory as the backward-compatible default. Manage the selected async
repository, official checkpointer and connection pools in lifespan;
fail startup on unavailable or uninitialized storage without fallback.
- Add SQLite and PostgreSQL adapters, schema initialization CLI, sample
PostgreSQL compose configuration and a Windows-compatible serve entry.
SQLite enforces single-instance file ownership; PostgreSQL uses a
dedicated pool for session advisory locks plus version/epoch fencing.
- Make repository IO and commit callbacks awaitable. Persist business
fields, a complete committed graph snapshot and turn result/version in
one business transaction before success. Rebuild execution checkpoints
from that snapshot, discarding uncommitted progress after interruption.
- Support optional Idempotency-Key on durable chat requests. Replay
committed results and return 409 on changed request content; delete
removes business/history data and replay records while retaining only
an epoch/version tombstone to reject stale commits.
- Document migration, database switching boundaries, backup/deployment
expectations and crash recovery. Ignore generated database files.
Validation: 315 tests passed with real SQLite and isolated PostgreSQL,
including abrupt child-process exits before/after business commit;
both backends passed CLI migration and actual HTTP server restart smoke.
Existing API tests were rechecked after isolating them from user storage.
An initial Windows CreateProcess permission failure did not recur in the
full diagnostic run; failure assertions were not skipped or relaxed.
- plan: assignment status table, five landed architecture decisions
(propose-validate, context_schema DI, verbatim alignment, no LangGraph
Server/SDK with rationale, 2004 semantics), real-model eval results
(collection 12/12; photo_skip 0/4 and no_false 2/8 share the '对'
routing pattern), three open questions with next actions, code map
- 2004 task rewritten as plate-confirm with both paths whitelisted
- graduation requirement reworded: illegal transitions never committed
- README: current status section pointing to plan appendix
- prompts/collection.md: versioned collection system prompt extracted
from workflow node yQaBxfrWjbRr with source/version/porting notes
- llm.py: LLMService protocol; FakeLLMService (scripted, records
calls); OpenAILLMService (async, wait_for timeout with cancellation,
retry only on timeout/429/connection, errors normalized)
- collect.py: run_collect reference impl - one LLM call produces
state prefix + body, controlled repair (max 1 retry) for missing
prefix or illegal stage proposal, whitelist guard, CollectReplyError
without raw model content; dialogue history + confirmed fields
injected into prompt so the model skips known info (作业4-5)
- fields.py / clock.py: three-state field candidates (unknown/
candidate/confirmed), per-type validation (count not inferred from
description, future time rejected), injectable Clock
- graph.py: welcome node - first message returns fixed 1001 greeting
without LLM (mirrors workflow is_first_message -> Assigned Reply#3),
route empty stage to welcome
- endpoints/delete_session: backend switch - langgraph clears graph
checkpoint, fastgpt path unchanged
- config: AGENT_LLM_PROVIDER fake|openai with validation
- untrack .env (secrets), move template to root .env.example
Verified:
- pytest 103 passed; smoke turns 1/2/1
- Real LLM e2e: POST /chat multi-turn context works
- Golden eval collection_skip_known_info: 12/12 cases pass
- Golden eval no_false: 8/10 cases pass; 4 confirm/photo cases fail
at final step - model routes on short reply '对' (prompt-adherence
gap, photo/confirm stages are assignment 5 scope); recorded in
evals/results/20261020-144856
Known limits: field extraction from model reply not wired (stub);
photo/confirm nodes still scaffold; clarify counting is approximate.