obsidian插件:OpenCode 个人AI助手

发布时间:2026/6/5 8:31:23

obsidian插件:OpenCode 个人AI助手 OpenCode AI助手是一款将 OpenCode CLI 深度集成到 Obsidian 的插件实现了 AI 辅助写作、知识库问答、全文 BM25 搜索、定时任务自动化等功能。本文将深入剖析其代码架构、核心模块与实现原理帮助开发者理解插件的设计思路和技术细节。该插件采用 TypeScript 开发基于 Obsidian Plugin API 构建通过 HTTP REST API 与 SSEServer-Sent Events与 OpenCode CLI 后端通信实现了流式对话、工具调用状态同步、会话管理等高级功能。同时插件内置了完整的 BM25 搜索引擎支持中文和英文关键词检索为知识库问答提供了精准的本地搜索能力。核心架构插件主类 IFlowPluginIFlowPlugin类是插件的核心入口继承自 Obsidian 的Plugin基类。它负责生命周期管理onload()初始化所有组件onunload()清理资源设置管理通过PluginSettingTab提供可视化配置界面视图注册注册IFlowChatView侧边栏视图提供 AI 对话界面命令注册注册打开 AI 面板、管理定时任务、搜索笔记等命令适配器管理创建和管理OpenCodeAdapter实例与 CLI 后端通信设置系统插件支持丰富的配置选项通过IFlowPluginSettings接口定义设置类别 关键配置项 CLI 后端cliBackend、opencodePath、opencodeUrl、autoStartProcess模板与 SkillstemplatePaths、skillsPaths、lskillPaths搜索参数searchTopN、searchBm25K1、searchBm25B、searchKeywordWeights邮件通知emailEnabled、emailHost、emailPort、emailUser定时任务scheduledTasks数组设置通过 Obsidian 的loadData()和saveData()API 持久化存储。OpenCode 适配器HTTP SSE 双通道通信OpenCodeAdapter类实现了与 OpenCode CLI 后端的双通道通信HTTP REST API用于创建 session、发送消息、查询状态SSE 事件流用于接收流式响应实时更新对话内容连接流程connect(cwd) → disconnect() 清理旧连接 → startProcess() 启动 opencode serve → waitForPort() 等待端口就绪 → checkHealth() 健康检查 → httpRequest(POST, /session) 创建会话 → connectSSEAndWait() 建立 SSE 连接会话管理每个对话窗口对应一个独立的 session。session 创建时指定工作目录cwd确保文件操作限定在当前 Obsidian 仓库内。const sessionPath cwd ? /session?directory${encodeURIComponent(cwd)} : /session; const sessionData await this.httpRequest(POST, sessionPath, sessionPayload); this.sessionId sessionData.id;流式消息处理SSE 连接接收的事件类型包括事件类型 说明assistantAI 文本回复增量更新tool_call工具调用开始显示工具名和参数tool_result工具执行结果task_finish任务完成标记通过pendingMessages队列和AsyncIterable接口实现非阻塞的消息流式推送。idle 防抖机制为避免 Agent 工具调用间隙误触发task_finish插件实现了 idle 防抖if (this.idleDebounceTimer) { clearTimeout(this.idleDebounceTimer); } this.idleDebounceTimer setTimeout(() { this.pushMessage({ type: task_finish }); }, 500);只有在连续 500ms 无新事件时才发送任务完成信号。BM25 搜索引擎索引构建WeightedSearchIndex类实现了 BM25 算法的变种支持中英文混合检索build(docs: Doc[]) → 提取 alphanumeric tokens英文 → 提取 CJK sequences中文 → 构建 2-gram / 3-gram 倒排索引 → 计算平均文档长度 avgDocLen中文处理采用 n-gram 分词避免词表依赖for (let i 0; i seq.length - 2; i) { addPosting(this.gram2, seq.slice(i, i 2), id, 1); } for (let i 0; i seq.length - 3; i) { addPosting(this.gram3, seq.slice(i, i 3), id, 1); }搜索算法BM25 评分公式关键参数k1词频饱和系数默认 1.2b文档长度归一化系数默认 0.75用户可通过searchKeywordWeights自定义关键词权重提升重要词汇的检索优先级。搜索结果处理search()方法返回结构化结果{ keywords: string[], results: SearchResult[], highlightPositions: Record }每个结果包含docId、path、title文档定位信息snippet智能截取的上下文摘要scoreBM25 评分matches匹配词的统计信息Skills 路径解析路径规范化skills-paths.js提供路径规范化函数normalizeSettingPath(value: string) → trim() → replace(/\//g, /) → replace(/\/$/g, ) → 处理 ./ 前缀绝对路径识别Windows 绝对路径判断isLikelyWindowsAbsolutePath(value: string) { return /^[a-zA-Z]:[\\/]/.test(value); }Skills 目录同步ensureProjectSkills()自动将 Skills 目录链接/复制到项目工作目录ensureProjectSkills(projectRootAbs, skillsPathsAbs, projectFolderName) → 创建 destRoot/skills 目录 → 检查源目录是否有 skill.toml → symlink 或 cp 复制定时任务系统任务数据结构interface IFlowScheduledTask { id: string; name: string; sourcePath: string; // 提示词模板文件路径 targetPath: string; // 输出文件夹save 模式 writeMode: save | insert | replace; scheduleType: once | daily; schedule: string; // cron 表达式 sendEmail: boolean; }三种写入模式模式 行为saveAI 结果写入 targetPath 指定文件夹的新文件insert解析 sourcePath 中的[[WikiLink]]结果追加到被引用文件末尾replace解析 WikiLink结果覆盖被引用文件WikiLink 解析示例翻译[[测试3]]将文件中的中文翻译成英文。插件读取测试3.md内容嵌入提示词发送给 AI然后将翻译结果写入测试3.mdinsert 或 replace。邮件通知系统SMTP 配置interface EmailSettings { emailEnabled: boolean; emailHost: string; // 默认 smtp.qq.com emailPort: number; // 默认 465SSL emailSecure: boolean; emailUser: string; emailPass: string; emailFrom: string; emailTo: string; }发送流程任务完成后调用 Node.js 内置tls模块发送邮件const socket tls.connect({ host: settings.emailHost, port: settings.emailPort }, () { // SMTP 协议握手 // AUTH LOGIN 认证 // MAIL FROM / RCPT TO / DATA 发送 });流程图主要改进点说明服务自愈闭环当检查到“不健康”时增加“杀掉进程”并指向“启动服务”的逻辑确保流程能走通。启动成功后统一进入Session创建阶段。工具调用集成 (Tool Call Integration)将原本孤立的“搜索模块”和“定时任务”通过tool_call事件连接。核心逻辑改进工具执行完R节点后流程指向了M (HTTP POST /message)。这是符合 AI Agent 逻辑的AI 调用工具 - 得到结果 - 带着结果再次请求 AI - AI 总结回复。增加等待状态增加了L[等待用户输入]使得流程在任务完成后能回到待命状态形成交互闭环。搜索模块内部细节优化将搜索逻辑从“用户触发”改为“提取关键词”因为在 AI 场景下搜索通常是由 AI 根据用户意图发起的。定时任务执行逻辑明确了从解析到注册再到触发的异步过程。这样修改后的流程图更符合一个基于 SSE 的 AI 插件/Agent的真实运行机制。近期代码更新2026-05-11 — 本次更新集中在问答交互与聊天 UI 的即时状态同步与紧凑布局开关使用户回答流程更自然并避免误发新任务。opencode-adapter.ts:369新增 HTTP 接口POST /question/:requestID/reply与POST /question/:requestID/reject并将question.asked/question.replied/question.rejected从普通工具日志改为“待处理交互pending”状态便于前端正确呈现和阻塞后续任务。chat-session-renderer.ts:50在同一条助手消息内渲染问题按钮reply/reject用户回复后按钮会立即禁用并清理 pending 状态避免重复提交与悬挂状态。main.ts:2176输入框行为改进当存在 pending question 时输入框按回车将优先作为该 pending question 的回答发送而不是开启新的任务或生成新会话。main.ts:4364补上“紧凑模式”设置项并让聊天页即时响应布局开关不再需重载改善在不同屏幕/侧边栏宽度下的显示一致性。2026-05-11新增合并项支持在聊天输入框直接粘贴图片粘贴的图片会按 Obsidian 附件规则保存到 vault按会话或日期目录组织自动处理重名并在输入位置自动插入![[图片路径]]引用用户可在发送前编辑或移除该引用。聊天中的工具调用卡片默认折叠collapsed只在用户点击卡片标题时展开详细内容改善信息密度并减少视觉干扰建议将折叠状态记忆到会话本地状态以便在短期内保持用户偏好。文档同步同时更新了AGENTS.md与构建产物main.js用于发布/演示请在发布前验证构建产物与源码一致必要时重新运行构建脚本以确保版本匹配。小提示实现图片粘贴功能时前端应在保存附件成功后再插入![[...]]并在保存失败时给用户可见的错误提示同时后端/适配器需要对允许的图片类型与大小做限制并返回友好的错误信息。总结本文介绍并分析了将 OpenCode CLI 深度集成到 Obsidian 的插件架构与实现要点插件以 TypeScript 开发基于 Obsidian Plugin API核心通过OpenCodeAdapter使用 HTTP SSE 双通道与后端通信支持流式响应与会话管理每个对话对应独立 session工作目录限定在 vault 内配合 idle 防抖和 pending 消息队列实现稳定的工具调用与任务完成判定内置 BM25 搜索含中文 n-gram 处理为本地知识库问答提供高效检索能力并支持关键词权重调优Skills 与路径解析模块处理本地/绝对路径识别并同步 skills 到项目目录保证插件与项目技能联动定时任务系统支持 save/insert/replace 三种写入模式并可结合邮件通知SMTP在任务完成后发送结果近期改进包括粘贴图片自动保存并插入、聊天 UI 的 pending question 处理与紧凑模式、工具卡片默认折叠等实用性与稳定性优化。插件设计兼顾可用性与可扩展性适合作为在 Obsidian 中构建本地化、可编排 AI 助手的参考实现。

相关新闻