我做了一个 Obsidian AI 插件,然后决定免费开源

结论先放前面:这个插件叫 AI Chat Assistant,从 2.0.0 起完全免费、源码公开(MIT)。授权系统已经整个删掉,所有旧激活码作废——也不再需要。

下面写三件事:这东西怎么长出来的、里面几个设计取舍为什么这么做、以及哪些地方我做砸了。


一、始末

起点只是一句”想推荐相关笔记”

2025 年 11 月,我想要的东西特别简单:打开一篇笔记,能不能自动列出其它可能相关的笔记?

那时候我连插件项目怎么建都不知道,靠 AI 一步步教:npx degit 拉模板、改 manifest.json、写 main.ts。第一版做出来是能做向量检索的,然后马上被现实教育:

  • 目录一多,建索引到一半 Obsidian 直接闪退,重进一看索引全没了;
  • 索引文件涨到 35 MB 的时候,插件一启动就崩。

回头看,这两次崩掉换来的认知比功能本身值钱:索引必须增量做、向量必须落到 IndexedDB 而不是一个越来越大的 JSON、UI 线程不能被向量计算堵死(后来才上 Web Worker)。

从”推荐”长成”聊天 + 知识库”

有了向量库,“推荐相关笔记”和”让 AI 读我的笔记回答”其实是同一件事的两面,于是接模型、做 RAG、支持流式输出、支持多家里程碑式地滚起来了。这一段最大的收获是检索质量不是模型问题:单纯向量搜索经常答非所问,得叠关键词、叠时间衰减、叠结果重排。最后用的是混合检索 + RRF 融合。

再长成”能动手”的智能体

只会聊天的 AI 助手遍地都是,真正有用的分水岭是:它能不能替我在库里动手? 于是加了工具调用——读文件、搜全文、精确替换、新建笔记。

然后就是这项目最痛的一课:AI 会骗人。它会输出”✅ 已替换成功”,而实际上根本没调用工具。为此加了一套执行可靠性机制(详见下面”设计思路”第二节),也是这个项目里我认为最有价值的部分。

角色扮演与长期记忆是意外收获

本来只是想给聊天加个”人格”,结果一路做到了兼容 SillyTavern 角色卡(PNG 里嵌的 chara 数据、V1/V2 JSON)、世界书、开场白与备选开场。

角色扮演立刻暴露了记忆系统的极限:长对话里角色会失忆、会说错自己该不该知道的事。于是有了”动静分离”的记忆改造——即时状态用状态机高优注入,事件用向量做情景记忆,人物/物品/势力关系抽成三元组做 Graph RAG 游走。

商业化尝试 → 放弃

2026 年我试着卖过:闲鱼挂单、做了个 PHP 卡密站(传上去一键部署就能无限发码)、装了台服务器做激活校验,代码里埋了三处功能门禁(智能体、知识库、高级模式)。

结果不意外:没做成。 买的人没几个,而”要给用户发激活码”这件事本身就消耗我仅有的耐心。

到 2026 年 9 月,两个判断让我彻底停了:

  1. 这类功能正在被各种 agent 吃掉——包括我自己现在都在用 agent 干活;
  2. 我自己早就不用这个插件了。

于是把授权代码整个删掉:LicenseManager.tsActivationModal.ts、三处 isLicenseValid() 门禁、设置页那个「激活状态」面板,全部移除。版本号直接跳到 2.0.0,源码公开。


二、设计思路(为什么这么做)

1. 不做”又一个聊天框”

一个只会在侧边栏里聊天的 AI,价值约等于一个网页标签页。这个插件真正想解决的是:让 AI 成为你笔记库的一个操作者,而不是一个旁观者。

所以工具集的第一性原则是”笔记库的原生动作”:读结构、搜全文、精确替换、新建、建文件夹、看元数据。宁可工具少而稳,也不要堆一堆花哨但难控的能力。

2. 先取证,再动手;动手之后必须验证

核心闭环:

SearchPlanner 预判 → ToolRouter 收缩工具面 → ExecutionSession 控制阶段 → 执行 / 验证 / 修复

四个阶段:

阶段干什么为什么需要
inspect读、搜、看结构修改类任务先看现场,别上来就写
act真正执行写入只有这里发生高风险动作
repair定位 + 最小修复 + 再验证写失败要能自愈,不能装死
answer停止调工具,直接回话收口,避免无限自我拉扯

关键在最后一条约束:没有真实的写工具成功结果,就不许输出完成态。 这条规则是拿真实事故换来的——早期版本的”假完成”让批量替换这种任务完全不可信。

3. 工具编排是运行时的硬约束,不是模型说了算

模型很擅长给自己找理由。所以:

  • 每个阶段能用的工具集合是收窄的(inspect 阶段没有写入工具);
  • 权限要审批(PermissionManager);
  • 执行有会话边界与轮次上限(避免”只读不写”卡死,也避免无限循环)。

这类约束用户看不见,但正是”体感稳不稳”的来源。

4. 参考过 claude-code,但收获是”别把主链做厚”

我认真读过 claude-code 的主干架构并写了对照分析,结论不是”它 planner 多”,恰恰相反:

它强的地方是默认主链又窄又硬又连续——一轮查询循环里完成”看上下文 → 调工具 → 继续 → 结束”。

对照自己的项目,我最大的架构问题就是链路偏重:阶段、路由、验证、会话层层叠上去,结果简单任务(比如”新建一篇笔记”)会因为误判要先 inspect 而在那儿反复读,用户看着就是”卡”。

这部分我认了:复杂度是要用体感换的,换不到就该砍。

5. 图谱感知检索:顺着双链取上下文

笔记库和普通文档库最大的差别是链接。你写下 [[某个概念]] 的时候,其实是在标注”这两篇有关系”。

所以做 RAG 时没有只做向量搜索,而是沿着双链把上下文一并取回来。命中一篇笔记时,把它的父级、子级、相关链接的摘要也带上——这比单纯提高 top-k 更贴近”我笔记之间的关系网”。

6. 本地优先(隐私不是口号)

  • 向量库用 IndexedDB,全部在本地;
  • 可以接 Ollama,模型也在本地;
  • 没有遥测、没有埋点,对话只发给你自己配的那个 API。

配齐本地模型后,这套东西能完全断网运行

7. 加工具”零接线”

新增一个工具只需要在 tools/ 目录放一个文件并导出,registerDefaultTools() 会自动遍历注册,不用去改设置、改路由表。

这是注册表模式的收益:扩展成本低。代价是运行时才暴露问题(漏了参数、名字冲突都得跑起来才知道),后期如果重做,我会在这里加一层静态校验。


三、我做砸的地方(诚实版)

这部分比上面更有用,因为它是真的:

  • 授权系统整个是白折腾。 三处门禁加起来没几行代码,卡密站一键部署就能无限发码——它从来没有真正”防住”过谁。更糟的是我曾把 50 个测试卡密明文写在公开仓库的 README 里,挂了大约 5 个月。这次 2.0.0 我直接用 force push 重写历史把它抹掉了。
  • 商业化没做成。 想卖的时候,最该问的问题是”这东西比免费替代品强在哪”,我没问,先做了支付链路。顺序反了。
  • main.ts 拆不完。 一度涨到 2500+ 行,view.ts 3200+ 行。拆分进行到一半就停了,现在是明确的负债。
  • DeepSeek 缓存的命中率没真正优化好。 prompt 前缀不稳定,缓存收益远低于预期——这件事我一直在”知道”但没动手。
  • Skills 和 MCP 徒有其表。 MCP 只实现了 HTTP/SSE,没有 stdio,也没在真实客户端上充分验证;Skills 是”能跑通”,不是”能靠”。
  • 没有自动化测试。 改代码靠人肉点,所以后期我越来越不敢动核心链路。
  • 内置 HTTP API server 没有鉴权。 虽然默认关闭、只监听本机,但这就是个隐患,应该在 1.x 就补掉。

四、现在它是什么,以后怎么办

现状
版本2.0.0(免费开源,MIT)
仓库https://github.com/zzzzzllllllaaaa/ai-chat-assistant
下载Releases 里的 main.js + manifest.json + styles.css
授权无,旧激活码全部作废;曾付费的用户可以开 issue 找退款
维护不追新功能,能跑就行;欢迎任何人接手

如果你正想找的东西是”能在 Obsidian 里读写笔记、能接本地模型的智能体”,它大概能用;如果你想要一个打磨精良、稳定可靠的生产力工具,老实说现在的它还差得远——上面那些坑就是差距清单。

写这个插件的两年里,我从”连插件工程都不会建”到能自己设计一套智能体执行链路。如果说有什么结论,大概是这句:

把东西做出来最快的方式是先用起来;而让它值得被使用的唯一方式,是承认哪里做得不好。