让 Session UI 从「一次性页面」变成可持续同步的运行视图
这个 PR 把 agent session 的事件链路补完整:后端开始发出用户消息和结构化事件,前端新增 session UI 组件,并把规约后的运行态提升到连接级 store。结果是切走再回来时,session 不再停留在旧快照,而是继续从 timeline cache 读取当前状态。
一句话总结
PR #88 将 Eyrie 的 agent session 从后端事件生产到桌面端渲染接成一条可持续同步的链路,并用连接级 runtime store 取代视图内 reducer hook,解决 session 视图卸载后 timeline 停住和重开状态落后的问题。
git diff origin/main...HEAD --stat。读代码的主线
任务进入 session
任务详情和保存态面板接入 session 创建/打开入口;前端 task draft 模型补齐 repo working directory 相关状态,daemon 侧也修正默认 working directory 选择。
apps/desktop/src/renderer/features/tasks/components/SavedTaskPanel.tsx、apps/daemon/src/use-cases/tasks.ts
后端发出可规约事件
daemon 的 agent service 和 event codec 开始处理用户消息事件,把 message.user 和多 part 用户输入纳入 timeline;API contract 与 client session 类型随之暴露这些字段。
apps/daemon/src/agent/event-codec.ts、packages/api/src/trpc.ts、packages/client/src/session.ts
桌面端用 reducer 折叠 timeline
session model 负责把 run、message、tool、approval、ask-user 等事件规约成可渲染的 SessionState。后续 store 只订阅 React Query timeline cache 的追加变化,并增量 reduce。
apps/desktop/src/renderer/features/session/models/session-store.ts
运行态离开 React 视图树
新增 createSessionStore / useSessionStore,按 connection + session 复用 Zustand store。视图卸载不会销毁规约结果,重开 session 直接读当前状态。
apps/desktop/src/renderer/features/session/api/session-runtime-store.ts、apps/desktop/src/renderer/features/session/api/use-session-store.ts
SessionThread 负责可恢复渲染
UI 组件覆盖用户消息、assistant markdown、reasoning、bash/edit/tool group、approval 和 ask-user。局部 error boundary 避免单个 part 渲染失败拖垮整条 thread。
apps/desktop/src/renderer/features/session/components/SessionThread.tsx、apps/desktop/src/renderer/features/session/components/ToolGroup.tsx
关键变更分组
后端事件与契约
- 新增/扩展 agent event codec 测试,覆盖用户消息事件。
- API DTO、service contract 和 tRPC router 暴露 session/timeline 所需字段。
- daemon service 方法测试补齐用户消息与事件传播路径。
桌面 Session UI
- 新增完整 session 组件目录:composer、thread、tool rows、approval、ask-user、markdown、reasoning。
- board route 和 task 面板接入 session pane。
- 新增自动滚动和 resize scroll hooks。
运行态持久化
- 新增连接级 Zustand store,并增量规约 React Query timeline cache。
- 删除视图本地
useSessionRuntimehook 和 replay/catchup/live phase machine。 - 用
isHydrating抑制首轮 replay 动画。
验证与约束
- 新增
session-runtime-store单元测试。 - 修复 Biome import sort 失败。
- 根级 Vitest timeout 对齐 app 级 10s,避免根命令仍使用默认 5s。
行为变化
之前
session view 自己管理 replay/catchup/live 阶段,卸载后状态与订阅容易断开,重开时依赖重新回放。
现在
dispatcher 的 active session 选择在 view unmount 后保持 sticky,timeline 继续进入 cache,store 在组件树外继续保留规约结果。
结果
用户从 board 或其他 route 回到 session 时,看到的是当前已规约状态,而不是离开瞬间的旧快照。
测试与 CI
- GitHub CI 通过:
verify、Title & description、Commit messages。 - 本地通过:
bun run verify。 - 新增测试:
apps/desktop/src/renderer/features/session/api/session-runtime-store.test.ts覆盖 cache fold、append reduce、resync rebuild、hydration settling 和 store reuse。 - 注意:PR 当前包含 18 个 commits,因为 GitHub base 是
origin/main;不只是后续 phase1/phase2 的 6 个 commits。
Reviewer 快速入口
想看数据如何流动
从 apps/daemon/src/agent/event-codec.ts 开始,接着看 packages/api/src/trpc.ts 和 packages/client/src/session.ts。
想看 UI 如何恢复
从 apps/desktop/src/renderer/features/session/api/session-runtime-store.ts 开始,再看 SessionPane.tsx 和 SessionThread.tsx。
想看交互表面
看 FloatingComposer.tsx、ApprovalTool.tsx、AskUserTool.tsx、ToolGroup.tsx。
想看风险兜底
看 session-runtime-store.test.ts、agent-event-codec.test.ts 和 agent-service-methods.test.ts。
原始材料
- PR 链接:https://github.com/figuretu/eyrie/pull/88
- Diff 统计:
git diff origin/main...HEAD --stat - 提交列表:
git log --oneline origin/main..HEAD - 本地验证:
bun run verify