obsidian插件-yuhanbo-opencode:OpenCode 个人AI助手
OpenCode AI助手是一款将 OpenCode CLI 深度集成到 Obsidian 的插件,实现了 AI 辅助写作、知识库问答、全文 BM25 搜索、定时任务自动化等功能。本文将深入剖析其代码架构、核心模块与实现原理,帮助开发者理解插件的设计思路和技术细节。
bili 视频:
相关的开源插件:obsidian插件-yuhanbo-iflow,将iFlow CLI集成到Obsidian | 余汉波 文档
插件主类 IFlowPlugin
IFlowPlugin 类是插件的核心入口,继承自 Obsidian 的 Plugin 基类。它负责:
- 设置管理:通过 PluginSettingTab 提供可视化配置界面
- 视图注册:注册 IFlowChatView 侧边栏视图,提供 AI 对话界面
- 命令注册:注册"打开 AI 面板"、"管理定时任务"、"搜索笔记"等命令
- 适配器管理:创建和管理 OpenCodeAdapter 实例,与 CLI 后端通信
设置系统
插件支持丰富的配置选项,通过 IFlowPluginSettings 接口定义:
设置通过 Obsidian 的 loadData() 和 saveData() API 持久化存储。
HTTP + SSE 双通道通信
OpenCodeAdapter 类实现了与 OpenCode CLI 后端的双通道通信:
连接流程:
- SSE 事件流:用于接收流式响应,实时更新对话内容
会话管理
每个对话窗口对应一个独立的 session。session 创建时指定工作目录(cwd),确保文件操作限定在当前 Obsidian 仓库内。
流式消息处理
SSE 连接接收的事件类型包括:
通过 pendingMessages 队列和 AsyncIterable 接口,实现非阻塞的消息流式推送。
为避免 Agent 工具调用间隙误触发 task_finish,插件实现了 idle 防抖:
只有在连续 500ms 无新事件时,才发送任务完成信号。
索引构建
WeightedSearchIndex 类实现了 BM25 算法的变种,支持中英文混合检索:
中文处理采用 n-gram 分词,避免词表依赖:
搜索算法
BM25 评分公式:
关键参数:
用户可通过 searchKeywordWeights 自定义关键词权重,提升重要词汇的检索优先级。
- b:文档长度归一化系数(默认 0.75)
search() 方法返回结构化结果:
每个结果包含:
- snippet:智能截取的上下文摘要
- score:BM25 评分
- matches:匹配词的统计信息
Skills 路径解析
路径规范化
skills-paths.js 提供路径规范化函数:
绝对路径识别
Windows 绝对路径判断:
Skills 目录同步
ensureProjectSkills() 自动将 Skills 目录链接/复制到项目工作目录:
定时任务系统
任务数据结构
interface IFlowScheduledTask {
id: string;
name: string;
sourcePath: string; // 提示词模板文件路径
targetPath: string; // 输出文件夹(save 模式)
writeMode: 'save' | 'insert' | 'replace';
scheduleType: 'once' | 'daily';
schedule: string; // cron 表达式
sendEmail: boolean;
}
三种写入模式
| 模式 | 行为 |
|---|---|
| save | AI 结果写入 targetPath 指定文件夹的新文件 |
| insert | 解析 sourcePath 中的 [[WikiLink]],结果追加到被引用文件末尾 |
| replace | 解析 WikiLink,结果覆盖被引用文件 |
WikiLink 解析示例:
插件读取 测试3.md 内容,嵌入提示词,发送给 AI,然后将翻译结果写入 测试3.md(insert 或 replace)。
SMTP 配置
interface EmailSettings {
emailEnabled: boolean;
emailHost: string; // 默认 smtp.qq.com
emailPort: number; // 默认 465(SSL)
emailSecure: boolean;
emailUser: string;
emailPass: string;
emailFrom: string;
emailTo: string;
}
发送流程
任务完成后,调用 Node.js 内置 tls 模块发送邮件:
流程图
flowchart TD
%% 主流程:启动与初始化
A[用户打开 AI 面板] --> B[IFlowPlugin.onload]
B --> C[OpenCodeAdapter.connect]
C --> D{端口是否被占用}
D -->|是| E[检查服务健康状态]
E -->|健康| J[复用现有 Session]
E -->|不健康| G[杀掉旧进程]
G --> H[startProcess 启动服务]
D -->|否| H
H --> I[等待端口就绪]
I --> J
J --> K[建立 SSE 长连接]
K --> L[等待用户输入]
%% 交互循环
L --> M[HTTP POST /message]
M --> N[SSE 接收流式响应]
N --> O{事件类型}
O -->|assistant| P[更新对话文本 UI]
O -->|tool_call| Q[解析工具参数]
%% 工具调用分发
Q --> Q1{调用何种工具?}
Q1 -->|本地搜索| U
Q1 -->|定时任务| AA
%% 搜索模块逻辑 (集成)
subgraph 搜索模块
U[提取搜索关键词] --> V[WeightedSearchIndex.build]
V --> W[分词与提取 Tokens]
W --> X[检索倒排索引]
X --> Y[BM25 评分重排]
Y --> Z[格式化搜索结果]
end
%% 定时任务逻辑 (集成)
subgraph 定时任务
AA[解析 Cron 与 Action] --> AB[注册到调度器]
AB --> AC{任务触发}
AC --> AD[执行写入模式]
AD --> AE[save/insert/replace]
end
%% 回传结果给 AI
Z --> R[显示工具执行结果]
AE --> R
R -->|将结果反馈给 AI| M
%% 结束与通知
O -->|task_finish| S[结束流响应]
S --> T[可选邮件通知/UI 状态归位]
T --> L
主要改进点说明:
这样修改后的流程图更符合一个基于 SSE 的 AI 插件/Agent 的真实运行机制。
- 服务自愈闭环:
- 当检查到“不健康”时,增加“杀掉进程”并指向“启动服务”的逻辑,确保流程能走通。
- 启动成功后统一进入 Session 创建阶段。
- 工具调用集成 (Tool Call Integration):
- 将原本孤立的“搜索模块”和“定时任务”通过 tool_call 事件连接。
- 核心逻辑改进:工具执行完(R 节点)后,流程指向了 M (HTTP POST /message)。这是符合 AI Agent 逻辑的:AI 调用工具 -> 得到结果 -> 带着结果再次请求 AI -> AI 总结回复。
- 增加等待状态:
- 增加了 L[等待用户输入],使得流程在任务完成后能回到待命状态,形成交互闭环。
- 搜索模块内部细节优化:
- 将搜索逻辑从“用户触发”改为“提取关键词”,因为在 AI 场景下,搜索通常是由 AI 根据用户意图发起的。
- 定时任务执行逻辑:
- 明确了从解析到注册再到触发的异步过程。