模块以 service.py 中的 SessionService 为编排入口,对外暴露创建/发送消息/取消/查询等 API;内部依赖四个协作子层:
- 数据模型层 models.py:定义 Session、Message、Attempt、Principal、SessionStatus、AttemptStatus 等 dataclass,并通过 to_dict/from_dict 实现 JSON 序列化。
- 持久化层 store.py 的 SessionStore:基于文件系统,按 {session_id}/session.json、messages.jsonl(追加日志 + fsync)、attempts/{attempt_id}/attempt.json 结构落盘,提供 Session/Message/Attempt 的 CRUD。
- 事件层 events.py 的 EventBus:进程内线程安全 SSE 事件总线,维护 per-session 环形缓冲与异步队列订阅,支持 last_event_id 重放与心跳保活,通过 call_soon_threadsafe 解决后台线程向 asyncio.Queue 投递的竞态问题。
- 搜索层 search.py 的 SessionSearchIndex:SQLite FTS5 反向索引,独立于主存储提供跨会话全文检索,通过触发器自动同步消息,并提供 reindex_from_store 从磁盘重建索引;通过 get_shared_index() 单例共享连接。
- WebUI 辅助 webui_turns.py、goal_state.py:为 WebSocket 通道适配器提供轮次计时与目标状态归一化。
执行流:send_message 先通过 _reserve_session 加锁抢占会话并发槽(防止 409),写入 Message 并创建 Attempt,再以 asyncio.create_task 启动 _run_attempt;后者在固定大小的 ThreadPoolExecutor(max_workers=4) 中调用 build_registry 和 AgentLoop.run,将工具调用/结果事件经回调转发到 EventBus,最终根据 AttemptStatus 发出 attempt.completed/cancelled/failed 终端事件。依赖方向单向:service → store/events/search → models,service 通过延迟 import 避免循环引用至 src.agent.loop、src.tools、src.providers.chat。