v4.0 — 让 Agent 住进来的编辑器
SoloMD 一直是同一份产品的两半:把纯 .md
写到磁盘上的编辑器,加上指向同一个 vault 的 MCP server。
v4.0 加了第三半 —— 编辑器内一等公民的 Agent
面板,有完整的安全护栏 (AutoGit 分支沙箱、
单次 write-cap、accept/reject UI),让自动写入是
"可审" 而不是 "可怕"。
品牌也跟着进化:从 "编辑器 + MCP 端点" 变成 "让 Agent 住进来的编辑器"。
这一版为什么憋了 12 周
v3.6 已经功能稳定了。下面 5 个支柱本来可以分成 5 个
minor 版本在春天里陆续发出去。我们故意没这么干 ——
在 main 上进入静默期 (3.6.2 之后只接补丁),
把 v4.0 当作下一次架构跃迁来对待。代价:12 周没有零碎的
marketing 节点。收益:每一个支柱都跑同一份安全契约 ——
同一个 run handle、同一个 trace 格式、同一个 write-cap
registry。Agent 面板、Recipe、REST API、MCP Federation
—— 入口不同,信任模型只有一份。
这 12 周里大约 6 周写代码,2 周做菜谱、向导、ja/ko 本地化骨架,最后 4 周是 dogfood —— 在真实 vault 上跑 v4-beta build,找集成测试漏掉的 bug。v4.0 大约三分之一的 commit 落在了最后这个窗口里。
五大支柱
1. 内置 Agent 面板
右侧一等公民面板,跟大纲 / 反向链接 / 标签 / 历史平级。
通过进程内 MCP 接口和已有 14 家 AI provider
组成 streamed chat-with-vault。[[wikilink]]
引用解析为真正的笔记跳转,点开就跳。每次 agent 调工具的
卡片在对话流里展开,看得到读取了什么、写入了什么、
参数和结果都看得见。回复太长?插入
把整段塞进当前编辑器的光标处 (有选区就替换);
复制 直接进剪贴板。运行历史以纯 markdown
形式存在 .solomd/agent-runs/ 下 —— 可 grep、
可被 git 追踪、几个月后还能审。
2. Agent Recipe / 定时运行
声明式 agent 任务,YAML 文件放在
<workspace>/.solomd/agents/*.yml。触发器:
schedule (cron)、on-save、
on-commit、on-tag-add、手动。
安全护栏不可妥协:
-
每次运行都开自己的 AutoGit 分支
agent/<recipe>/<run-id>。Recipe runner 在工作区脏的时候直接拒绝启动 —— 你的 WIP 永远不会被扫进 agent 的 commit。 -
所有写入只落在分支上。accept/reject UI 把 diff
摆出来再决定要不要合入
main。 -
单次
write-cap(默认 5,硬上限 50) 防止失控循环。模型在 cap 是 5 的情况下要写 50 个文件, 从第 6 次工具调用就被拒,不会出现"半成品"状态。 - 被 Reject 的运行分支被 hard-delete —— git 历史里 完全看不到这次运行。
自带 11 个 Recipe 模板:周报、日报、 TODO 抽取、翻译过一遍、引用清理、CJK 校对 agent、 链接腐烂检测、front-matter 规范化、大纲转博客、 重构过一遍、周度 tag 整理。设置 → Recipes → 浏览菜谱 里挑一个,改 prompt,运行。
3. Agent Trace View
每次运行 (无论是 Panel 对话还是 Recipe) 都按步生成
trace.jsonl:
prompt / model_call /
tool_call / tool_result /
git_commit / done。步骤卡片
可展开看 args、结果、token 数、成本估算、AutoGit
分支引用。从第 N 步重放 把运行回退到
第 N 步,改输入后从那里重新跑 —— 这是 self-correcting
recipe 的入口。新增 MCP 工具
read_agent_trace(run_id),把 trace
暴露给其他 agent 读取,所以 recipe 可以读自己之前的
失败、改个思路再来一遍。
4. 多 Vault MCP Federation
solomd-mcp --workspace path1 --workspace path2 --workspace path3
—— 一个 MCP 会话,多个 vault。工具签名加了可选
workspace 参数,默认 = 第一个传入的
(单 vault 客户端继续工作不受影响)。AutoGit 分支按
workspace 隔离。设置 → 集成 里有
MCP profile UI:把多个 vault 命名打包,一键复制 Claude
Desktop 的配置片段。从此不用开 3 个 Claude Code
会话来桥接两个 vault —— 一个会话,同时看两个。
5. Ollama 一等公民
我们 不 自己捆绑本地 LLM 运行时 —— Ollama 已经做得很好,重新发明轮子违反"少写需要 永久维护的代码"原则。v4.0 只是把集成磨得更顺:
- 自动检测
localhost:11434(设置 → AI 里有绿色状态灯)。 - 未安装时一键引导安装 (跳到 ollama.com —— 我们不代理下载)。
- 三个模型预设:
rewrite→ qwen2.5:7b ·quick→ qwen2.5:1.5b ·cjk→ qwen2.5:14b。 - 空模型列表 → 内联"推荐 pull (Qwen2.5 1.5B,~1 GB)"按钮。
- Recipe 可以
provider: local(ollama 别名),用零云成本跑自动化循环。
你的笔记永不离开机器 —— 通过 BYOK Ollama 从 v2.2 起这一直是真的;v4.0 只是把这条路在第一天 就让你看得到。
质量条 —— 看不见但用得到的部分
- 首次启动向导。新装用户 60 秒内见到 Agent 面板。引导你填 BYOK key 或装 Ollama。后续可从 帮助 重新打开。
- 本地 REST API(只监听 localhost, token 鉴权)。和 MCP 同一套接口,给那些还没接 MCP 的客户端用 —— Alfred / Raycast / n8n / 你自己的脚本。
- BYOK 成本计。按 provider 累计已花 token 数,opt-in。设置 → 集成。
- 本地化。ja / ko 翻译骨架在 README + iPad 商店元信息里。en/zh 仍是 UI 全覆盖语言。
- MCP server 加了
--workspace参数(可重复)。原来单 workspace 的 MCP 客户端 继续工作不受影响;federation 行为是可选加入的。
Dogfood 抓出来的(所以你不用再踩)
Dogfood 阶段 —— 在真机上、真 vault 里、用真 BYOK key 把 build 跑起来 —— 暴露出了 262 个单测 + 集成测 没抓到的 bug:
- macOS 启动 UX。启动激活时机错位
—— 在
setup里调set_focus()时 NSApp 的 run loop 还没跑完启动流程,激活请求被吞了,SoloMD 启动后藏在 前一个 frontmost app 后面。改成在RunEvent::Ready+ 等 window-state plugin 的第一次 restore 信号才激活,问题解决。 - 侧栏 resize handle hover 灌满整片。
5px 宽的拖动条
position: absolute; top: 0; bottom: 0,被一个全局:deep(*)规则把width: 5px覆盖成100%。 再叠上 hover 时半透明 accent 背景 +z-index: 10,整片侧栏被刷成橙色, 所有点击都被这片 div 接走了。看起来像卡住的浮层, 其实是被拉伸的 div。 - "生成中..." 卡死无错误。Ollama
模型名打错时 OpenAI-compat 层会返回 HTTP 404,
Rust 端正确发了
solomd://ai-error, 但 JS 监听器靠currentRunId匹配, 这个值是在await invoke()resolve 之后 才赋的 —— 而 404 太快,错误事件 先到、currentRunId还是 null 就被丢掉了。 修法:在前端 mint request id,通过 invoke payload 传给后端,这样监听器在任何后端事件可能发出之前已经 武装好了。 - 7 个输入面板的 IME 守卫。拼音用户、
日文 kana、韩文谚文 —— 按回车确认候选词触发了
发送 / 重命名 / 打开,而不是让 IME 处理。给
AgentPanel、FileTree 重命名、命令面板、快速切换、
全文搜索、RAG 搜索、预览搜索都加了
e.isComposing守卫。 - agent_tools 路径穿越。父目录不存在时
resolve_in_workspacefallback 到原始 candidate,..段绕过starts_with(workspace)检查,在文件系统 层面真的逃出了 workspace。已确认 exploit:{"path": "../../tmp/pwn/x.md"}真的能 写到 workspace 外。重写以对齐mcp-server::safety::resolve_in—— 前置拒绝..段和绝对路径,canonicalize 到最深的存在祖先。 - AutoGit recipe 沙箱吃掉用户 WIP。
checkout 把未提交的修改迁到 agent 分支,
add_all(["*"])把 WIP 一起扫进 agent 的 commit,force-restore 还可能销毁 in-flight 修改。 Recipe runner 现在工作区脏时直接拒绝启动,restore_head优先用 safe checkout。
最后这一类是这次发布最在意的事。Agent 往你的笔记里写东西是个 赌数据 的功能。如果某次 recipe 安静地改坏了一段、你下周才发现,整个产品就废了。 所以 AutoGit 分支沙箱、write-cap、accept/reject UI、 路径穿越加固、脏检查 —— 五重不变量守同一条防线。
v4.0 明确不做的
说"不"也是产品的一部分。下面这些被认真考虑过、明确不做:
- 自带本地 LLM 运行时。Ollama 已经做得很好。 重新发明轮子违反"少写需要永久维护的代码"原则。 BYOK provider 仍是路径。
- 线上 Recipe 市场。服务器运维 + 内容审核 = 偏离主线。 菜谱直接打进发行版。
- 多人 / 团队 agent。违反"一个窗口,一个写者"。 这个产品给单作者用;协作属于另一个产品。
- Copilot 风格的鬼字补全。不同的品牌定位。 鬼字补全会稀释作者自己的声音;我们的 agent 工作单位是 vault, 写入是批量 + 可审 + 走分支的。
升级须知
没有文件格式变更。已有的 .md、AutoGit
历史、同步配置、BYOK key 全部原样保留。Agent 面板首次
启动自动开 (一次性迁移 —— v3.6.x 用户因为 v4-beta
期间脚手架的默认值,会有一个隐藏的
showAgentPanel: false)。不想要可以
⌘⇧P → View: Toggle Agent Panel 关掉,
以后会一直关着。
接下来
v4.x 及之后 的开放方向都在 roadmap 上:沙盒化的脚本 API (capability-scoped,Trilium 那种 "我想写脚本定制工作流")、CLI v2 (终端里 rewrite / commit / 语义搜索 / 触发 recipe)、以及一直拖着的 "SoloMD 要不要做成商业产品?" 问题 —— v3.0 时代的老问题,还没答,这块的工程不会动。
现在:下载 v4.0, 指向一个 vault,周日试试 cookbook 里的"周报"recipe。 如果它碰了不该碰的,accept/reject UI 会拦下来。如果它 做对了,你刚刚用 30 秒装好了一个每周自动跑、不用你管的东西。
感谢所有在静默期内跑 v4-beta build 的人。上面这些 bug 能进 release notes 是因为 dogfood 把它们抓出来了; 没进 release notes 的那些 bug,才是这一切能跑起来的 真正原因。Issue 反馈:GitHub。