Claude
72189d2b7b
fix(chat): use native async LLM call to prevent session reset on message submit
...
The previous implementation used asyncio.to_thread(llm.complete) to avoid
blocking the event loop, but Chainlit's contextvars context is not reliably
propagated across thread boundaries, causing the session to reset and clear
the message history on each user submission.
Changes:
- Add llm.acomplete() using litellm.acompletion() (native coroutine)
- Replace asyncio.to_thread() in on_message with await llm.acomplete()
- Store the welcome message in state.messages so it is replayed on reconnect
- Persist state to cl.user_session immediately after appending the user's
message (before the LLM call) so reconnect detection has the latest history
- Add pytest-asyncio dev dependency and asyncio_mode = "auto" config
- Add 6 async tests for acomplete() in tests/test_llm.py
https://claude.ai/code/session_01SUWzMzFvSfWiHXA2p6rPg9
2026-02-22 12:38:20 +00:00
Claude
9fdbe341be
feat(chat): implement web chat interface with accessibility
...
Core implementation:
- chat_app.py: Chainlit entry point with @cl.on_chat_start,
@cl.on_message (streaming via llm.stream_complete), @cl.on_chat_end
Reuses Config, KnowledgeBase, ConversationStore, AdminNotifier from src/
Handles registration completion, post-completion updates, new-child flow
- src/llm.py: add stream_complete() generator (litellm stream=True)
alongside existing complete(); tests added in tests/test_llm.py
- src/agent/response_parser.py: extract parse_llm_response(),
apply_updates(), fallback_message() from EmailAgent into shared module
EmailAgent now delegates to these functions (no logic change)
Chainlit configuration:
- chainlit.toml: telemetry off, German default, custom CSS + JS paths
- chainlit.md: German welcome page with playgroup info
Accessibility (WCAG 2.1 AA):
- public/custom.css: contrast overrides (≥4.5:1), prefers-reduced-motion
(static "…" replaces animated dots), skip link styles, 100dvh fix
- public/accessibility.js: MutationObserver injects aria-live="polite"
on message list, focus management after agent replies, skip link element
Other:
- .gitignore: add .chainlit/ (Chainlit runtime, auto-generated)
- openspec/config.yaml: populate context field with tech stack
- openspec/changes/implement-web-chat/tasks.md: mark completed tasks
95 tests pass.
https://claude.ai/code/session_01SUWzMzFvSfWiHXA2p6rPg9
2026-02-22 07:42:29 +00:00
Claude
7f55cdd204
Add pytest test suite (92 tests, all passing)
...
Covers every module in src/ with unit tests:
- tests/conftest.py shared fixtures (complete_registration, fresh_state, …)
- tests/test_models.py RegistrationData.is_complete(), to_dict/from_dict round-trips
- tests/test_storage.py normalize_email, _diff_registrations, ConversationStore CRUD,
registration versioning
- tests/test_llm.py litellm wrapper — message construction, model passthrough,
error propagation
- tests/test_agent.py EmailAgent — new/existing conversations, registration
completion, admin notification, fallback on LLM error,
JSON parsing, _apply_updates
- tests/test_notifier.py AdminNotifier routing, fee calculation, SMTP dispatch
- tests/test_knowledge_base.py KnowledgeBase loading and reload
All external I/O (litellm, SMTP, filesystem) is mocked. Tests run fast (~6s)
with no network access required.
https://claude.ai/code/session_01HaUFs7SaLD5SoiuGCY27Tw
2026-02-21 08:07:31 +00:00