【免费下载链接】puppyone
Context drive for your AI agents
PuppyOne 是一款本地优先的 AI 编辑器(local-first editor),它用一个简单的规则解决所有编辑器的老毛病——每个文件在内存中只存在一份 Working Copy(工作副本)。无论你怎么分屏、切换标签,还是让 AI Agent 同时改文件,你的每一次修改都有唯一归属、有版本校验、有原子落盘,不会丢、不会互相覆盖。
为什么代码会丢?先看三个典型事故场景
- 场景一:你在同一个文件开了两个分屏,改了左边,右边却还显示旧内容,保存时互相覆盖;
- 场景二:你编辑到一半,AI Agent 在后台把同一个文件改了,一刷新你的修改被冲掉;
- 场景三:关窗口瞬间有未保存内容,程序没等你确认就直接退出,几行代码没了。
很多编辑器在这几类场景下会静默丢数据。PuppyOne 的做法是把"内容"和"界面"彻底分开管理,从机制上消灭这三类事故。
核心设计:一个文件,只有一份 Working Copy
PuppyOne 把编辑器工作台拆成三层互不代管的记录(见编辑器架构文档):
| 层 | 记录什么 |
|---|---|
| 打开项目录 | "打开了什么"(资源、标题、最近使用) |
| Pane 布局 | "显示在哪里"(位置、分屏、比例) |
| Working Copy | "内容是什么、是否需要保存" |
关键约束:每个"存储身份 + 规范资源路径"的组合只对应一份 Working Copy。当你再次打开同一文件时,框架不会新建副本,而是复用已有实例,逻辑位于 documentWorkingCopies.ts:
const existing = bindings.get(identity.resourcePath); if (existing) { existing.session.setSaveMode(options.saveMode); return existing; // 复用,绝不新建第二份副本 }文件身份由"稳定存储身份 + 规范路径"构成,实现见 documentIdentity.ts。这意味着:
- ✅ 不同工作区里的同名文件严格隔离,不会串档;
- ✅ 即使界面层(React)重建了组件对象,只要身份相同就复用同一份副本,未保存内容原样保留;
- ✅ 打开、关闭、分屏、移动 Pane 这些操作只改"元数据",永远不会触发文档写入。
一句话:你看到的每个编辑窗口都只是这份唯一 Working Copy 的"投影",改任何一处,全局只有一份真值。
保存冲突绝不静默:条件写 + 版本校验
有了唯一副本,第二步是"落盘时别把别人的修改盖掉"。PuppyOne 的写入链路是条件写(conditional write):
- 每次读取文件时,主进程用内容算出一个
sha256:版本指纹,作为写入基线; - 保存时先在临时文件写完整内容、同步落盘(fsync),rename 前最后一刻重新校验版本;
- 版本不一致就返回结构化冲突结果(
conflict),而不是硬写; - 校验通过后原子 rename 替换目标文件,再同步目录,保证崩溃恢复后文件要么完整是旧的、要么完整是新的,不会出现半截文件。
这套原子写实现在 versioned-atomic-write.mjs:
if (getWorkspaceFileVersion(currentBytes) !== expectedVersion) { throw conflict // 版本变了 → 交还给用户决策,绝不覆盖 } await fs.rename(temporaryPath, filePath) // 原子替换存储端只会返回四种结构化结果:success | conflict | not-found | permission-denied | io。只有success才能推进基线——也就是说,编辑器永远知道"这次保存到底成没成",你不需要猜。
Agent 改你的文件时,编辑区会怎么做?
这是 PuppyOne 作为 AI 编辑器的关键差异点。工作副本维护一张干净的状态机(clean → dirty → saving → saved / conflict),规则非常克制:
- 你没有本地修改时:Agent 写入、文件 watcher 通知、Viewer 重新挂载——界面自动显示 Agent 的最新内容,磁盘写入次数为零,零副作用;
- 你有未保存修改、同时外部又变了:进入显式
conflict状态,由你选择"加载外部"还是"保留本地",而不是静默选边。
完整链路(页面保持打开 → Agent 改文件 → watcher 通知 → Viewer 重挂载)被列为 P0 级不变量,并由 Registry 驱动的测试矩阵对每一个可编辑格式逐一验证,见 editorExternalConsistencyMatrix.integration.test.tsx。新增一种可编辑 Viewer 但没补测试夹具时,测试会直接失败——机制不允许"裸奔"上线。
关闭窗口前,未保存内容必须先落地
第三类事故(关窗口丢改动)由专门的关窗协调器拦截:
- 关闭文档/工作区/应用前,主进程会向渲染进程发起 flush 请求,等待所有 Working Copy 把待保存内容写完,超时 12 秒;
- 如果确实有改动保存失败(比如权限问题),窗口会保持打开,并弹出提示"Some document changes could not be saved",让你重试,而不是直接退出。逻辑在 document-session-close-coordinator.mjs;
- 自动保存策略只负责"合并同一时刻的多次编辑、尽快请求保存"(见 autoSavePolicy.ts),它无权绕过版本与冲突语义——保存的时机可以快,但保存的正确性永远由 Working Copy 说了算。
整个保存生命周期(edit → manual → document-close → workspace-switch → app-close 的优先级调度)集中在框架无关的 DocumentEditingSession.ts 中,格式编辑器只提供快照,存储差异藏在持久化端口后面,顺序和版本不变量由宿主统一持有。
想自己验证?这套不变量都可以跑
除了集成测试矩阵,架构级约束还有独立检查:editorInteractionSessionArchitecture.test.ts 会校验"Viewer 不直接读写文件""布局树不持有内容"等规则。如果你想看设计全貌,推荐从 document-editing-persistence.md 入手,里面有一张完整的工作副本状态机图。
小结:代码不丢,靠的不是"小心",而是"不可能"
| 事故场景 | PuppyOne 的对策 |
|---|---|
| 多视图互相覆盖 | 一个文件只有一份 Working Copy,界面只是投影 |
| 落盘盖掉他人修改 | 版本指纹 + 条件写 + 原子 rename,冲突显式上报 |
| Agent 与用户同时编辑 | 干净态自动采纳外部更新;脏态进入显式冲突,人来决策 |
| 关窗丢失未保存内容 | 关窗前强制 flush,失败则窗口保持打开并提示 |
对日常用户来说,这些机制的体感就是:随便分屏、随便让 Agent 动手、随便关窗口,你的修改总有一份、且总有人负责把它存好——这正是 PuppyOne 把"Context drive for your AI agents"落到编辑器底座的方式。
【免费下载链接】puppyone
Context drive for your AI agents
相关推荐
DDSP与Gin配置:如何实现无需代码的灵活音频模型配置
DDSP与Gin配置:如何实现无需代码的灵活音频模型配置 DDSP(Differentiable Digital Signal Processing)是一个强大
深度学习音视频人工智能如何一键备份微博内容?Speechless 让你的社交记忆永不丢失 📱💾
如何一键备份微博内容?Speechless 让你的社交记忆永不丢失 📱💾 在信息快速更迭的时代,我们在微博上记录的生活点滴、思想感悟和重要时刻,常常面临因平
前端网页爬虫Micro编辑器文件并发编辑保护机制解析
Micro编辑器文件并发编辑保护机制解析 Micro作为一款现代化的命令行文本编辑器,其设计理念中包含了完善的并发编辑保护机制。本文将深入分析Micro如何通过
开发工具CLI
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考