# Phase 7 剩余项与已知生产缺陷追踪 7.7 DSH 插件已完成(见 `docs/PLUGIN-GUIDE.md` 与 PLAN.md §7.7)。 ## 无法立即推进(缺基础设施) ### 7.8 跨主机 Agent 发现 - Gateway + Registry 拆分为独立服务 - etcd / Consul 服务注册与发现 - Agent 跨主机路由 ## 可以立即推进的生产缺陷 ### P0 — SSE Last-Event-ID 补投 **根因**:EventSource 断线重连时自带 Last-Event-ID 头,但服务端直接忽略了—— 所有断线期间的邮件通知都丢失。用户刷新页面也会错过已推的事件。 **影响**:重连后永远看不到断线期间收到的邮件(除非手动刷新)。 **修法**:服务端维护一个有界循环缓冲区(ring buffer),每次 Broadcast 同时写入, SSE 连接的 handler 在首次连接时从缓冲区头部开始(客户端传了 Last-Event-ID 就从那里), 没有则从头(只带最近 N 条)。缓冲区大小设 500,内存 < 2MB。 ### P0 — 连接状态指示器 **根因**:SSE 断线后前端无任何可见反馈——用户以为系统正常,实际通知已停。 **影响**:实时性是 Agent 协作的核心体验,断线无提示会让人以为「Agent 没在动」。 **修法**:header 旁加一个连接状态点(绿/黄/红),SSE 的 onopen/onerror 事件驱动。 ### P1 — 登录限速跨进程问题 ✅ **根因**:LoginLimiter 是进程内内存计数器,多实例部署时每个实例独立计数。 **修法**:改为 DB 事务(rate_limits 表 + IMMEDIATE 事务),多实例共享同一份计数。 ### P1 — 新建会话限速同理 ✅ **根因**:sessionRateLimiter 也是进程内计数器。 **修法**:同上,sessionrate.go 重写为调用 RateLimitCheckAndRecord。 ### P2 — 组件级测试 **现状**:前端无任何组件测试,前端回归只靠 lint 与构建。 **范围**:关键组件(AddressInput 补全、PermissionPanel 决策、WorkCard 预算渲染)。 ### P2 — 深色主题 **现状**:只有浅色主题,深夜使用刺眼。 **范围**:tailwind dark: 前缀覆盖主要组件。 ### P1 — 每平台可用模型范围(进行中) **需求**:配置页面为每个 Agent 平台划定「邮箱调用场景下可用的模型范围」, 端侧插件按范围**逐个降级尝试**,全部失败时把失败原因封装成邮件回复。 选择而非手打模型名 —— 平台上报目录,管理员勾选。 **已完成**: - `agent_model_catalog`(平台上报的目录)+ `agent_allowed_models`(管理员的选择) 两张表,两份 schema - `repo/models_scope.go`:`ReplaceModelCatalog` / `ListModelCatalog` / `ListAllowedModels` / `SetAllowedModels` **为什么分两张表**:模型会从平台目录里消失(换了 provider 配置、上游临时下线), 整行删掉会连带把管理员的选择也删了,模型回来还得重配一遍。分开存之后 「选了什么」是持久的,目录只决定「这一项现在是否可用」。 **待做**: - [ ] handler + 路由:注册时接收目录、管理员读写选择 - [ ] 插件在注册时上报目录(opencode 有 `/config/providers`,DSH 有 `llm.listModels`) - [ ] 插件按 rank 顺序尝试,记录每次失败的原因 - [ ] 全部失败 → 发一封说明失败原因的邮件(走免配额通道) - [ ] 前端配置页:复选框 + 拖拽排序(rank 即优先级)