第一轮 Mac 闭环开发计划
更新日期:2026-09-26。状态:五条技术路线已扩展 Agent 与 Whisper:DeepSeek、固定工具、审批、取消和持久会话已实现,并完成统一构建、打包与本地签名(build-all.sh 退出码 0)。 按用户指示不做测试验证和 computer-use,没有打开应用、使用 API key、实际识别语音或测量性能。
最新使用与边界见 AI 与语音基础 和 runtime README。下文里程碑是完整产品方向;“代码已实现”与“运行验收通过”分别记录。
本计划把详细调研转成可以立即开始的小步实现。用户已确认“自建模型与工具循环”和“先 Mac 本地,后远程设备”,并要求通过并行 MVP 实际接触 Swift、Rust、GPUI 与 React 的不同宿主。最终 UI 和运行时语言尚未确定;可以直接从 GPUI/Rust 开始学习,无需先完成 Swift 版本。SQLite 与独立 Runner 仍是架构建议。
相关文档:五路线 examples 入口 · 阅读入口 · 产品架构调研 · Harness 提案 · 渲染实验。
1. 这轮开发的结果
Section titled “1. 这轮开发的结果”第一轮完整闭环应能让用户选择一个本地工作目录,提交任务,看到模型与工具的结构化进度,按运行策略授权动作,取消执行,并在再次打开界面后查看可信的记录。
“完整”包含错误和中断路径:模型失败、工具超时、输出过大、取消竞态、Runner 中断后结果未知。各阶段逐步加入这些能力,不把模拟数据演示当作完整 Harness。
本轮的主要体验目标是:Agent 工作期间,用户仍能顺畅输入、滚动、切换会话和发出取消请求。
2. 已有环境与构建结果
Section titled “2. 已有环境与构建结果”下列记录来自 2026-09-26 的环境读取和实际构建,只代表这台开发机器,不代表目标设备的最低要求。更新本文时没有重新运行检查或测试。
| 检查 | 实际结果 | 对开发的影响 |
|---|---|---|
| 当前目录 | /Users/chp/explore/yuuki-box,现在包含 docs/ 和 examples/ | 已有可继续修改的路线样例 |
| 系统 | macOS 27.0,build 26A428 | 记录为开发环境,不能据此决定最低部署版本 |
| 架构 | arm64 | 当前在 Apple Silicon 环境下工作 |
| Swift | Apple Swift 6.4,target arm64-apple-macosx27.0.0 | 已用 swiftc 编译实际 App 和语音 helper |
| 活动开发目录 | /Library/Developer/CommandLineTools | 当前选中 Command Line Tools |
xcodebuild -version | 初次检查失败,提示当前目录是 command line tools instance | 不影响当前通过 CLT 编译、手工打包 .app 的路径 |
| GPUI 构建路径 | GPUI 0.2.2、Rust 1.93、runtime_shaders | 已构建 GPUI App;在运行时编译 shader,不需要构建时执行 xcrun metal |
初次 xcodebuild 结果只能证明当时没有选中完整 Xcode,不能证明机器任意位置都没有安装 Xcode。本轮没有切换开发目录或安装完整 Xcode。完整 Xcode 不是开始这些 Mac 示例的前提。 Swift 的系统 SDK 与 CLT 已足以构建原生窗口、WKWebView 宿主、React 原生桥宿主和 Apple Speech helper;GPUI 也已有绕开构建期 Metal 工具要求的实际路径。
五个已经生成的应用包
Section titled “五个已经生成的应用包”| 路线 | 已生成的本机包 | 学习重点 |
|---|---|---|
| SwiftUI + AppKit | examples/swift-native/build/YuukiSwiftNative.app | 系统 UI、可观察状态和原生 API |
| Rust + GPUI | examples/rust-gpui/build/Yuuki GPUI.app | Rust 状态、GPUI 元素树与 GPU 绘制框架的使用 |
| React → AppKit | examples/react-native-bridge/build/YuukiReactNative.app | React custom renderer、进程协议与原生控件映射 |
| React + WKWebView | examples/react-webview/build/YuukiReactWebView.app | Swift 宿主、系统 WebKit、ReactDOM 与能力桥接 |
| Electron + React | 实际路径记录在 examples/electron/build/latest-path.txt | Chromium/Node 宿主、ReactDOM 和 Electron 原生能力接入 |
五条路线都已完成本轮编译和应用打包;包采用本机架构与本地 ad-hoc 签名,不是已公证、可面向用户分发的正式版本。构建与打开方式见 examples 入口。GPUI 当前默认 dev/debug,Swift 使用优化编译;这些构建配置不能直接用于性能排名。
以后需要完整 Xcode 时
Section titled “以后需要完整 Xcode 时”Xcode 工程、Instruments 分析、iOS/iPadOS 目标或其他完整工具链能力,可在需要时配置。届时从 Apple Xcode 下载入口安装或找到已有 Xcode,完成首次启动设置,再选择对应开发目录。下面是以后可选的单次命令示例,未作为本轮新检查执行:
DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer xcodebuild -version不要把这项后续配置重新变成目前的开工门槛。开发目录选择与命令行工具说明见 Apple Technical Note TN2339。
3. 已开始的第一项任务:五路线 Mac 窗口实验
Section titled “3. 已开始的第一项任务:五路线 Mac 窗口实验”这项任务最初产出五个不依赖模型密钥的回放演示。最新扩展保留该实验页,并加入真实 DeepSeek 调用路径、工具循环、审批、持久会话和独立 runtime 子进程;只有使用 AI 功能时才需要用户配置密钥。Whisper CLI 和模型由用户稍后准备。
已实现的共同范围
Section titled “已实现的共同范围”- 每条路线都有独立的窗口实现与构建入口,可以直接选择最感兴趣的路线改动。
- 共同 fixture 包含
message/tool事件;循环扩展为 1,000 或 10,000 条独立 ID 的历史,支持全部/工具筛选。 - 固定回放每 50 ms 追加一条,每轮最多 200 条,总保留上限 10,200 条;提供开始与停止。
- 更新按钮读取共同清单,覆盖有更新、当前版本和无效清单;实现版本发现与状态展示,未实现安装、替换程序或重启。
- 语音按钮接入同一个真实 Apple Speech / AVFoundation helper,默认要求设备端识别;只有用户主动启动才申请权限和采集。语音模型不是五套独立实现。
这些实现提供可读的入口,编译成功不等于实际交互、识别、性能或升级安装通过。侧栏/任务选择展示尚不构成真正的独立会话选择,固定 tool 行也没有执行系统工具。具体限制见每条路线 README。
M0 尚未完成的内容与以后可选的观察
Section titled “M0 尚未完成的内容与以后可选的观察”用户已明确允许本轮跳过测试验证和 computer-use,因此以下是以后想深入体验时可选的工作,不是本轮已执行或必须补跑的检查:
- 输入内容不会因为事件追加或切换状态丢失。
- 切换会话后,不会把之前会话的输出追加到当前会话。
- 用户向上阅读时,新输出不会强制把滚动位置拉回底部;提供明确的返回最新位置入口。
- 当进一步引入异步 Runner 后,点击停止先显示“正在停止”,最终状态只结束一次;当前固定回放主要演示定时追加与取消。
- 已完成的历史内容不会随着每次文本增量全部重新解析。
- 若开展性能比较,记录环境、负载和一致的优化构建配置;目前没有基线数据,不把初始目标填写成实测结果。
详细采样方法、变量控制与测量表见渲染性能学习与实验。
4. 从原型到完整闭环
Section titled “4. 从原型到完整闭环”下面以成果作为阶段边界,不承诺固定日历工期。可以在任意一条路线推进,也可以并行学习 Rust/GPUI 和其他宿主;不要求先完成 Swift UI。学习速度、具体能力和模型接口接入会影响实际耗时。
| 阶段 | 交付物 | 验收重点 | 当前状态 |
|---|---|---|---|
| M0:环境与回放 | 五路线窗口、固定模拟事件流;后续可选采样 | 输入、真实会话切换、停止和长历史 | 已有源码与构建;新增会话 UI,交互与性能未验收 |
| M1:真实模型循环 | 一个模型提供方、结构化响应与用量 | 流式完成、错误、取消、结束原因 | DeepSeek SSE、用量和结束状态已实现;未付费调用 |
| M2:最少工具闭环 | 文件读取、搜索、修改与命令执行 | 参数校验、策略、工具结果回传、超时和输出上限 | 部分实现:列目录、读文件、审批后新建笔记;无 shell、覆盖或删除 |
| M3:可信记录与恢复 | 状态/事件持久化、产物与中断恢复 | 结果未知、重复提交、崩溃窗口与凭据处理 | 部分实现:原子 JSON、Keychain、导出与中断标记;无 SQLite/故障注入 |
| M4:独立 Runner 与性能收敛 | 独立生命周期、重连与代表性负载记录 | 退出语义、进程树、缓冲上限、空闲开销 | 已有随 App 退出的子进程;无后台常驻、重连或性能实测 |
持久化和独立 Runner 的设计边界从前面阶段保留,实现顺序不意味着可以在 M1/M2 声称“关闭应用后仍运行”或“崩溃后自动恢复”。先完整跑通一个循环,再验证这些性质。
M1:一个模型提供方
Section titled “M1:一个模型提供方”先实现实际需要的一家提供方,不为尚未接入的模型建立一套庞大抽象。保留消息、工具 schema、流式事件、结束原因、用量和提供方原生附加数据的明确位置。
本阶段必须能区分:请求失败、流中断、模型正常结束、输出达到上限、用户取消。供应商错误不得被改写成成功答案。为真正允许重试的失败设定次数和时间上限。
提供方、模型与认证方式在接入时核实官方最新文档。本文不指定模型名、价格、上下文大小或 API 参数,因此不能直接作为某家 API 的实现参考。
验收用例:普通回答、工具调用请求的结构解析、流中断、超时、取消,以及缺失或延迟用量信息的记录方式。
M2:工具形成闭环
Section titled “M2:工具形成闭环”建议首批工具围绕真实本地任务组织:读取文件、搜索文本、应用受控修改、执行命令。每个工具必须有输入、输出和错误结构,UI 不需要从终端文本猜测它的状态。
先顺序执行调用;确实存在互不依赖的读取负载时再加入受限并发。并发修改同一工作区、子 Agent 和任务依赖调度放在有明确需求之后。
工具运行前校验参数并执行策略。命令工作目录、环境变量、输出限制、超时与子进程结束方式都是工具契约的一部分。工作目录限制不等于系统沙箱;如果首版没有操作系统级隔离,应把真实能力范围写清楚。
验收用例:工具成功、输入无效、权限拒绝、等待授权期间取消、命令失败、命令超时、连续大量输出,以及模型收到结构化错误后继续处理。
M3:让记录可信
Section titled “M3:让记录可信”在开始可能产生副作用的工具操作前,持久化调用标识和执行意图。结果返回后,把对应状态和事件一起提交。大输出保存为受限文件或产物,UI 和模型上下文只取需要的部分。
恢复时检查每个未完成调用:确知未执行、确知已完成、或结果未知。结果未知时根据工具能力进行检查或要求人工判断,不能一律重跑。
凭据放在系统凭据存储中;数据库记录引用和非敏感配置,不记录完整密钥。保留供应商原生响应所需的元数据,但不采集无法实际获得的模型内部推理。
验收用例:工具执行前崩溃、执行过程中崩溃、执行完成但结果落盘前崩溃、重复提交同一开始请求、重启后恢复显示,以及大型日志的保留与清理。
M4:把生命周期与响应落实
Section titled “M4:把生命周期与响应落实”先确定关闭窗口、退出 App、停止 Runner、系统重启各自意味着什么。子进程能运行,并不证明它具有独立于 App 的可靠生命周期。
如果要求退出 UI 后继续工作,实现并验证由系统管理的用户级 helper。若当前阶段选择退出 UI 即停止,也必须明确提示并妥善结束子进程,不能暗示后台仍在运行。
在真实模型与工具负载下重跑 M0 的输入、切换、滚动和取消场景,并加入工具输出突发、慢 UI 消费和长期空闲。对每个进程分别记录 CPU、内存与生命周期,避免把子进程成本遗漏。
5. 后续可选验证矩阵
Section titled “5. 后续可选验证矩阵”下表保留未来实现真实 Harness 时值得观察的行为和可用方法,目前全部未验证。它不是本轮的执行要求,也不是已运行测试的清单;用户本轮明确允许跳过测试验证和 computer-use。以后按当前阶段选择需要的验证,不必为学习样例先搭建完整测试体系。
| 情况 | 预期行为 | 合适的验证方式 |
|---|---|---|
| 模型返回工具调用 | 调用校验后执行,结果关联原调用并回传 | 假模型/假工具的集成测试 |
| 模型输出达到限制 | 保留部分结果,显示真实结束原因,不伪装正常完成 | 提供方响应夹具 |
| 授权请求过期或重复回复 | 已解决请求不会再次执行 | 状态机测试 |
| 用户取消与工具完成同时到达 | 最终状态一致,保留实际副作用记录 | 控制时序的竞态测试 |
| 工具输出远超界面速度 | 缓冲有界,显示和存储策略明确 | 输出压力回放 |
| 输出被截断 | 明确说明截断,保留产物或已采用的限制信息 | 工具输出边界测试 |
| Runner 崩溃 | 下次连接看到中断或未知状态,不盲目重跑 | 故障注入 |
| UI 断开再连接 | 按游标补齐已持久化事件,不重复显示 | 本地连接集成测试 |
| 用户切换会话 | 新事件按会话身份落位,当前输入不丢失 | UI 回放与人工检查 |
| 工具派生子进程 | 取消/超时按约定结束执行范围并回收资源 | 受控子进程测试 |
| 模型用量尚未知 | 显示未知或暂估状态,不记录为确定零成本 | 记录层测试 |
| 应用闲置 | 没有无意义的持续轮询或高频重绘 | Instruments 与进程观察 |
6. 什么现在决定,什么等到需要时再决定
Section titled “6. 什么现在决定,什么等到需要时再决定”| 时点 | 要明确的事项 | 暂缓依据 |
|---|---|---|
| M0 继续推进时 | 先打开和修改哪条路线、需要补哪项真实交互 | 五路线已构建,不要求先选定最终技术栈 |
| M1 开始前 | 一家模型提供方、认证方式、流式与错误契约 | 具体接口需以当时官方文档为准 |
| M2 开始前 | 首个真实任务、可操作目录、工具策略与隔离范围 | 决定真正需要哪些工具及权限 |
| M3 开始前 | 保存位置、保留策略、恢复语义、凭据引用 | 保证关键状态和副作用有证据 |
| M4 开始前 | 退出 UI 后是否继续、后台 helper 的注册与关闭方式 | 决定实际生命周期实现 |
| 分发前 | 最低 macOS、签名、更新、分发方式 | 本机开发版本不等于产品部署策略 |
| 远程阶段前 | 主机身份、认证、撤销配对、传输和断线补发 | 本地界面与运行时边界先验证 |
7. 当前学习范围与暂缓能力
Section titled “7. 当前学习范围与暂缓能力”使用 GPUI 与自研 GPU UI 引擎是不同的工作。 本轮已使用 GPUI 创建 Rust 应用;布局、图元绘制、窗口与 Metal 接入使用现成框架。研究其源码和修改应用可以现在开始,自行从零编写完整绘制框架才是下面暂缓的项目。
Rust 也不要求等出现性能瓶颈才学习。可以直接沿 GPUI 示例学习所有权、状态更新、事件和子进程,或在下一阶段用 Rust 实现 Harness;是否把整个产品统一成 Rust,等实际接入和维护体验足够具体时再决定。
| 暂缓项 | 重新评估的具体触发条件 |
|---|---|
| 从零自研 GPU UI 框架 | 学习目标进一步转向渲染引擎,或现成框架有明确无法满足的需求;不限制现在使用 GPUI |
| 最终整套产品统一语言 | 通过几条实际调用路径了解语言和桥接成本后决定;Rust Harness 可以先独立尝试 |
| CRDT | 多设备确实需要离线同时编辑同一文本并合并 |
| Wasm 插件平台 | 有实际第三方、不可信代码需要能力受控的执行环境 |
| 通用插件市场 | 工具契约已稳定且存在外部开发者需求 |
| 完整终端模拟器/IDE | 用户任务需要持续交互终端或深度代码编辑,现有视图不足 |
| 多 Agent 编排 | 单 Agent 的实际任务存在可测量、可分解的收益 |
| MCP 与 ACP | 分别出现具体工具服务器或外部 Agent/客户端兼容需求 |
| 多设备任务迁移 | 重连同一执行主机无法满足实际需求,且可定义副作用与文件迁移语义 |
“面向未来”在首版体现为清楚的边界、真实的状态和可验证的行为。每次增加机制,都应对应一个已经出现的问题。
8. 停止继续调研的条件
Section titled “8. 停止继续调研的条件”现在已有五条可以修改的路线,M0 已开始,无需继续等待所有长期选型定稿。继续工作的最小依据是:
- 首个窗口显示什么,用户怎样输入和停止。
- 模拟事件怎样产生,怎样与真实运行时替换。
- 如果之后想做性能实验,使用什么固定数据,怎样记录环境和结果;本轮不要求测量。
- 当前有哪些事实、建议和未知项,它们分别在哪里记录。
后续调研只围绕实现遇到的具体问题展开。例如“为什么每个增量触发整条历史重新布局”“取消后还有哪个子进程存活”“模型流中断后工具是否已经执行”。
9. 完成记录模板
Section titled “9. 完成记录模板”当前实施记录是:五条 UI 路线与共同语音 helper 已生成本机应用包;M0 部分完成,M1–M4 未开始。没有 GUI、性能、实际语音或完整更新安装的验证结果。helper 在用户调整要求之前做过的无权限检查见 examples 入口,不外推成整套 App 验收结论。
下列模板用于后续每个里程碑的工作记录;未执行的项目可以直接写“本轮未执行”:
阶段与日期:代码/构建版本:实际完成的用户行为:运行环境与固定负载:执行过的验证:观察到的结果与原始记录:仍未覆盖的情况:本轮接受/调整的设计决定:下一项最小工作:下一项最小工作是在感兴趣的路线里配置 DeepSeek 和练习目录,读懂“任务 → 模型工具循环 → 审批 → 结果”路径;Whisper 文件准备好后再填入设置。五条路线现在接入共同运行时,想学习 Rust/GPUI可以直接从它开始。后续基于亲手使用的结果选择优化目标,不提前给未经实测的路线排名。