refactor(agent): inject deps via context_schema, LLM-driven photo/confirm nodes

- graph.py: LangGraph-native DI - StateGraph(context_schema=GraphDeps),
  nodes take (state, runtime: Runtime[GraphDeps]); build_graph() decoupled
  from LLM; deleted scaffold _event_reply/_fake_llm_propose/stub nodes
- photo.py: model proposes stage+body via per-mode prompts (direct/addon);
  validator enforces clientMode exits; deterministic event forcing removed
- confirm.py: single runtime for single/dual confirm, extraction call
  isolated per person_index
- llm.py: workflow_fake_llm() (offline workflow-faithful responder,
  history-aware) for smoke/tests
- backend: LangGraphBackend(graph, llm) passes context per call
- tests: invoke helpers inject GraphDeps; illegal-proposal test asserts
  error + state untouched via second well-behaved fake

Verified: 143 passed; smoke turns 1/2/1 with original welcome text
This commit is contained in:
Eric Wang
2026-10-21 15:11:16 +08:00
parent a5407e03b2
commit 6d0a2169c8
12 changed files with 794 additions and 187 deletions
+2 -2
View File
@@ -26,8 +26,8 @@ async def lifespan(app: FastAPI):
from ..agent.llm import build_llm_service
global _langgraph_graph
_langgraph_graph = build_graph(llm=build_llm_service())
_chat_backend = LangGraphBackend(_langgraph_graph)
_langgraph_graph = build_graph()
_chat_backend = LangGraphBackend(_langgraph_graph, llm=build_llm_service())
else:
_fastgpt_client = AsyncChatClient(
api_key=Config.FASTGPT_API_KEY,