feat(chat): Phase 3 PR-B — chat HTTP + SSE + replay (text-only)#23
Merged
Leolebleis merged 12 commits intomainfrom May 2, 2026
Merged
feat(chat): Phase 3 PR-B — chat HTTP + SSE + replay (text-only)#23Leolebleis merged 12 commits intomainfrom
Leolebleis merged 12 commits intomainfrom
Conversation
- Replace `repo.get_message + raw _conn.execute(rowid)` with `repo.get_cursor`; kills the SLF001/ty-ignore reach-through and the production assert. - Replace 7-case match in `_event_to_sse` with `type(event).__name__` → snake_case + `asdict`; mirrors `events/router.py` and removes PLR0911. - Convert `chat_message_to_response` to `ChatMessageMapper.to_api_response` matching `JournalMapper`/`BagMapper` style. - Drop `_to_jsonable` wrapping; widen `ToolCallResult.result` to `Any` (preserve raw shape on the wire — dict/str/list/None). - Use `ModelMessagesTypeAdapter.dump_python(mode="json")` instead of `dump_json → decode → json.loads` round-trip in service + mapper. - Drop `if history else []` short-circuit — `validate_python([])` is fine. - Drop dead `and messages` from `next_before_id` guard. - Reuse `fellow_mock` fixture from `tests/e2e/conftest.py`. - Extract `parse_sse` / `parse_sse_async` to `tests/_sse.py`. - Simplify `make_fake_chat_agent` (drop dead mid-loop branch; rename to `raise_at_end`). - Use `NotFoundError.for_resource` consistently in tests. - Delete narrating WHAT-comments in service.py. All 410 tests green; coverage 95.53%.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Lands the user-facing chat backend on top of PR-A's foundation.
POST /chat/messages— text-only SSE stream. 7 typed wire events:text_delta,tool_call_start,tool_call_delta,tool_call_result,thinking_delta,done,error.GET /chat/messages— replay withlimit + before_idcursor pagination.ChatAgentProtocol seam inchat/client.py—ChatServiceandrouter.pystay pydantic-ai-free.>=1.89,<2; addedanthropic_cache_instructions='1h'tobuild_chat_agent.get_thread404-only-on-cursor-miss,before_idcursor pagination.Stack notes
agent.run_stream_events(prompt, message_history=...)(pydantic-ai 1.89 —AgentRunResultEventmoved to top-levelpydantic_ai, mapper adapted).CachePoint-driven hot-state injection.load_history. Token-aware truncation deferred.(created_at, rowid)row-value comparison, resolved throughrepo.get_cursor.Test plan
uv run pytest— 410 passing (376 baseline + 34 new chat/e2e tests)uv run ruff check --no-cache src/ tests/cleanuv run ty check src/cleanerroreventbefore_idOut of scope (PR-C)
BinaryContentuser inputCachePoint_mcp_server.read_resource()workaround for chat