# 纵向功能 状态:开发中 需求版本:0.3.0(已确认、已冻结) 实施方案版本:0.4.0(已确认) 项目骨架:已确认(2026-08-12) 允许的状态:“待开始”“进行中”“待用户查看”“已完成”“已阻塞”。用户已于 2026-08-14 授权 F-004 及后续切片由 Agent 验证通过后直接标记“已完成”并提交,最后统一人工审核。“已完成”仍不等于最终功能验收已经通过。 ## 当前版本功能切片 ### F-001——应用外壳、首次状态与普通会话 - 状态:已完成(用户于 2026-08-12 审核通过) - 用户可见结果:首次进入看到“最近”和“项目”空状态及右侧对话引导;点击“新任务”不会创建空会话,发送首条有效消息后普通会话出现,选择历史会话可还原消息并继续输入。 - 页面与交互:Claude Desktop 风格三栏外壳、空状态、对话引导、新任务草稿、普通历史会话、输入校验、加载与保存失败状态。 - 服务或接口:普通会话列表、会话详情、首条消息原子创建会话、已有会话追加用户消息。 - 数据持久化:Conversation 和 Message 实体 JSON、普通会话可重建索引、首条消息失败不暴露空会话。 - 权限与校验:应用内无身份层;普通会话强制 `projectId = null`;空文本拒绝;客户端不能指定工作区。 - 异常状态:列表加载失败、会话不存在、输入无效、持久化失败、重复提交期间禁用。 - 自动化测试:Core 首条消息和空消息用例、本地文件 Repository、Web DTO/路由及骨架回归共 10 个测试、24 个断言,全部通过。 - 验证命令与结果:`bun run format:check`、`bun run lint`、`bun run typecheck`、`bun run check:file-size`、`bun run check:architecture`、`bun test`、`bun run build` 全部通过。 - 人工验证步骤:在空数据目录启动生产服务;确认首次引导与空最近列表;点击“新任务”确认列表不新增;发送“这是第一条本地消息”确认会话和消息出现;刷新确认不自动选择;点击历史会话确认消息恢复。 - 人工操作结果:2026-08-12 使用本机浏览器完成上述步骤,首次与点击新任务后的会话数均为 0,发送后为 1,刷新后仍显示引导,选择历史后消息恢复。 - 视觉参考:已只读采集本机 Claude Desktop 新任务页并保存为 `docs/visual-reference/claude-new-task.png`;F-001 实现截图保存为 `docs/visual-reference/f001-conversation.png`。历史任务采集超时,留待 F-009 补齐。 - 查看阶段修改:根据用户反馈将集中式 `global.css` 拆为全局令牌/reset、应用外壳样式和 conversations 组件共置样式;后续组件继续遵循相同约定。 - 已知限制:本切片不调用模型;用户消息可持久化,但助手回复从 F-002 开始。 ### F-002——Agent Core 与 DeepSeek 流式回复 - 状态:已完成(用户于 2026-08-13 审核通过) - 用户可见结果:普通会话可启动 Agent Run,DeepSeek 回复增量显示,完成后的助手消息写入本地会话并可继续聊天;未配置模型密钥时保留用户消息并显示明确错误。 - Agent Core:新增独立于 HTTP 的 `AgentRunService`、Run/RunEvent 领域对象、`ModelPort` 与 `RunRepository`;模型增量、完成和失败均转为稳定的领域事件。 - DeepSeek 接入:`model-deepseek` 在适配器内部映射 OpenAI 兼容协议,Core 只依赖自身 Message/ModelEvent 类型;首个模型固定为 DeepSeek。 - 服务与流式协议:新增 `POST /api/runs` 和 `GET /api/runs/:runId/events`;事件按序包含 Run 开始、消息开始/增量/完成及 Run 完成/失败。前端使用基于 `fetch` 的 SSE 读取,兼容不提供原生 `EventSource` 的 WebView。 - 数据持久化:每次运行保存 `run.json` 和有序 `events.ndjson`;成功后助手消息写入真实本地 Conversation 文件,失败后保存稳定失败终态和错误代码。 - 轮次关联:每条用户和助手消息都必须保存 `runId`;Run 使用 `triggerMessageId` 指向触发本轮运行的用户消息,并复用流式 `message.started` 给出的助手 `messageId`,因此运行、触发消息、流式事件和最终消息可以稳定互查。会话写接口只提供查询,新增消息必须通过 Run 用例,避免产生没有 Run 的孤立消息。“第几回合”由用户消息顺序计算,不持久化易失序号;重试链 `retryOfRunId` 仍在 F-005 实现。 - 页面与交互:发送消息后进入运行状态、实时拼接助手草稿、完成后读取持久化消息;模型配置缺失时显示“尚未配置 DeepSeek API 密钥”,输入恢复可用且不丢失已提交的用户消息。 - 异常状态:模型密钥缺失保留具体可行动提示;其他模型异常对外收敛为“模型服务暂时不可用”,不泄露供应商原始错误或密钥。 - 自动化测试:Agent Core 成功/失败和轮次关联、文件 Run Repository、HTTP 与 SSE 消息标识一致性、禁止绕过 Run 直接写消息及原有回归共 13 个测试、43 个断言,全部通过。 - 验证命令与结果:`bun run format:check`、`bun run lint`、`bun run typecheck`、`bun run check:file-size`、`bun run check:architecture`、`bun test`、`bun run build` 全部通过。 - 人工验证步骤:以空临时数据目录和未配置 DeepSeek 密钥启动生产构建;发送“最终失败链路验收”;检查用户消息、错误提示、输入恢复以及 Run 事件文件和失败摘要。 - 人工操作结果:2026-08-12 使用本机应用内浏览器完成;页面准确显示模型密钥缺失提示,输入恢复,用户消息保留;`events.ndjson` 依次写入 `run.started`、`message.started`、`run.failed`,`run.json` 状态为 `failed`。 - 查看阶段修改:根据用户反馈将应用外壳锁定为浏览器可视区高度;页面根节点不再滚动,侧栏仅“最近”区域内部滚动,ConversationPane 仅消息内容区内部滚动,顶部操作、侧栏底部信息和输入组件保持固定。2026-08-13 在 1280×720 视口验证根页面高度与视口一致且无页面滚动,两个内容区均为独立 `overflow-y: auto` 容器。 - 开发环境修正:`bun run dev` 的后端固定以仓库根目录运行并读取根 `.env`;前端由 Vite 提供 HMR,开发时统一访问 `127.0.0.1:5173`,`/api` 按同一份 `HOST/PORT` 配置代理到 Bun watch 后端。生产 `start` 仍由 Bun/Hono 提供构建后的 `web/dist`。 - 视觉参考:失败状态验收截图保存为 `docs/visual-reference/f002-model-config-error.jpg`。 - 已知限制:真实 DeepSeek 成功调用需要用户在运行环境提供自己的密钥;自动化和本次人工验收未使用或读取真实密钥。停止与重试留在 F-005,服务重启后的事件重放加固留在 F-010。 - 主要验收:AC-004、AC-010、AC-014、AC-016。 ### F-003——项目管理与项目聊天 - 状态:已完成(用户于 2026-08-14 审核通过) - 用户可见结果:创建、选择、重命名和删除项目,在项目中维护多个独立会话。 - 主要验收:AC-026 至 AC-033。 - 自动化验证结果:2026-08-13 通过全仓类型检查、16 项测试、生产构建、代码检查、格式检查、文件规模检查与架构依赖检查。 - 人工操作结果:2026-08-13 使用本机应用内浏览器完成;验证了真实目录创建项目、首条消息才创建项目会话、项目历史恢复并继续聊天、重命名、删除确认信息,以及删除后本地工作目录仍然存在。 ### F-004——用户交互卡片 - 状态:已完成(Agent 于 2026-08-14 验证通过,等待最终统一人工审核) - 用户可见结果:Agent 请求单选、多选、确认或意见输入,回答后继续同一 Run。 - 主要验收:AC-034 至 AC-038。 - 实现结果:DeepSeek 工具调用被转换为独立 `interaction.*` 领域事件;交互请求按 Run 持久化,回答后使用原 `runId` 和 `toolCallId` 继续模型请求,不创建新 Run 或用户消息。支持单选、多选、确认和自由文本,包含选项数量、选择上下限、未知选项、重复回答及 8 KiB 文本校验。 - 页面结果:消息时间线按交互类型显示四类 VanJS 卡片;等待回答时禁用普通输入;回答后保留只读问题和答案;等待中的任务可从卡片停止并显示取消状态。 - 自动化验证结果:2026-08-14 通过全仓类型检查、21 项测试和 75 个断言、生产构建、代码检查、格式检查、文件规模检查与架构依赖检查;Fake Model 验证暂停和恢复前后 Run 标识不变、事件序列连续。 - 人工操作结果:2026-08-14 使用隔离数据目录和本机应用内浏览器验证四类卡片、提交条件、只读答案、取消状态及刷新恢复;页面控制台无错误。 ### F-005——停止、失败与重试 - 状态:已完成(Agent 于 2026-08-14 验证通过,等待最终统一人工审核) - 用户可见结果:停止当前生成并从失败状态重试。 - 主要验收:AC-005、AC-010、AC-011。 - 实现结果:Agent Core 持有每个活动 Run 的取消控制器,停止操作真正中断 ModelPort;停止前已生成内容持久化,Run 和事件日志进入 `cancelled` 终态。失败或取消后创建带 `retryOfRunId` 的新 Run,复用原触发消息且不重复写入用户消息。Repository 与串行启动锁共同执行全局单活动 Run 检查,第二个任务返回 `RUN_ALREADY_ACTIVE`。 - 失败处理:DeepSeek 请求增加与环境配置一致的模型超时并映射 `MODEL_TIMEOUT`;Bun 服务空闲超时与模型超时对齐;流式连接提前中断时前端结束加载并主动取消仍在运行的后台任务。 - 页面结果:生成时发送按钮切换为“停止生成”;失败和取消显示明确状态及“重试”按钮;API 启动失败时保留输入草稿。 - 自动化验证结果:2026-08-14 通过全仓类型检查、24 项测试和 84 个断言、生产构建、代码检查、格式检查、文件规模检查与架构依赖检查。 - 人工操作结果:2026-08-14 使用隔离慢速 Fake Model 验证停止按钮、部分回复保留、取消终态和重试成功;并通过两个连续 HTTP 请求确认活动任务期间第二个请求稳定返回 `409 RUN_ALREADY_ACTIVE`;页面控制台无错误。 ### F-006——附件、文件列表、读取与搜索 - 状态:已完成(Agent 于 2026-08-14 验证通过,等待最终统一人工审核) - 用户可见结果:附加工作区文件并让 Agent 安全读取和搜索。 - 主要验收:AC-007 至 AC-009、AC-021、AC-022、AC-028、AC-030。 - 实现结果:消息新增必填附件元数据,支持一次选择最多 10 个工作区文件和仅附件消息;普通草稿、项目草稿与已有会话均由服务端解析可信工作区,浏览器和模型不能传入根目录。文件层支持目录浏览、文件名与 UTF-8 内容搜索、2 MiB 内文本读取、二进制识别,并拒绝绝对路径、`..`、空字节和符号链接逃逸。 - Agent 工具:新增 `list_directory`、`search_files` 和 `read_text_file`;普通文件工具使用独立 `tool.started`、`tool.completed`、`tool.failed` 事件,结果交回同一次模型请求链继续生成,与用户交互事件保持区分。 - 页面结果:VanJS 输入区提供工作区文件选择器、目录导航、搜索、最多 10 项选择、待发送附件和历史附件状态;只有附件时发送按钮可用。附件在发送后消失或不可访问时,历史会话仍可打开并明确显示“不可用”;项目目录离线时附件入口禁用且不会回退到默认工作区。 - 自动化验证结果:2026-08-14 通过全仓类型检查、29 项测试和 99 个断言、生产构建、代码检查、格式检查、文件规模检查与架构依赖检查;覆盖读取/搜索、二进制拒绝、绝对路径、父目录跳转、符号链接逃逸、仅附件消息和文件工具续跑。 - 人工操作结果:2026-08-14 使用隔离工作区、隔离数据目录和未配置模型密钥的本机应用内浏览器完成;验证选择 `README.md`、仅附件发送、会话标题与附件历史恢复;删除测试文件后刷新,历史附件显示“不可用”,隔离页面控制台无错误。 ### F-007——文件创建与安全修改 - 状态:已完成(Agent 于 2026-08-14 验证通过,等待最终统一人工审核) - 用户可见结果:Agent 在正确工作区内创建和安全修改文本文件。 - 主要验收:AC-008、AC-009、AC-023、AC-028。 - 实现结果:新增 `create_text_file` 和 `apply_text_patch` 两个模型工具。新建文件使用排他写入,目标已存在时不会覆盖;修改必须携带最近一次 `read_text_file` 返回的 SHA-256 内容哈希,并使用 1 至 50 项精确文本替换。待替换文本不存在、默认模式下出现多次、文件已被外部改动或修改没有产生变化时均明确失败。 - 写入安全:新文件先解析真实父目录并再次检查工作区边界,阻止通过目录符号链接写到外部;已有文件修改在同目录写临时文件、保留原权限并原子替换,替换前再次核对内容哈希。继续限制 UTF-8 文本和 2 MiB 上限,不增加删除、移动、批量覆盖或 Shell 能力。 - 页面结果:创建和修改与其他文件工具共用已有工具状态卡片,分别显示“创建文件”和“修改文件”;成功与失败仍使用 `tool.completed` 和 `tool.failed`,不会混入主要回复消息或用户交互卡片。 - 自动化验证结果:2026-08-14 通过全仓类型检查、31 项测试和 109 个断言、生产构建、代码检查、格式检查、文件规模检查与架构依赖检查;覆盖排他创建、哈希修改、过期哈希、缺失替换、歧义替换、路径穿越及目录符号链接逃逸。 ### F-008——会话管理与个人设置 - 状态:进行中 - 用户可见结果:重命名和删除会话,查看并修改非敏感设置。 - 主要验收:AC-003、AC-018。 ### F-009——Claude Desktop 视觉与交互收口 - 状态:待开始 - 用户可见结果:全部已支持状态在目标视口下贴近确认后的参考界面。 - 主要验收:AC-001、AC-002、AC-012、AC-013、AC-020、AC-024。 ### F-010——恢复、边界与发布前加固 - 状态:待开始 - 用户可见结果:刷新、重启、目录离线和数据损坏等边界均有明确恢复行为。 - 主要验收:AC-006、AC-017 至 AC-019、AC-023、AC-029、AC-030、AC-036、AC-037。 ## 后续版本想法 当前无。新增想法只记录在这里,不扩大 0.3.0 冻结范围。