Hindsight Obsidian 集成演进全览:从插件首发到无头 CLI 同步引擎
【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight
Hindsight 的 Obsidian 插件(npm 包@vectorize-io/hindsight-obsidian)为笔记库接入 AI Agent 记忆:将 Obsidian vault 单向同步进 Hindsight memory bank,并提供基于笔记给出引用答案的聊天面板。本文以官方 changelog(skills/hindsight-docs/references/changelog/integrations/obsidian.md)为骨架,结合仓库源码与 README,逐版本梳理从 0.1.0 到 0.2.1 的功能演进与关键修复,并深入讲解同步引擎、隐式 scoping、CLI 工具与同步索引绑定等底层原理,读完后你将掌握该插件的完整能力边界、配置方式与实现机制。
版本演进总览
Obsidian 集成从 0.1.0 首发至今共经历 5 个版本,核心脉络清晰:先解决"插件能用"(0.1.0),再打磨"聊天体验"(0.1.1/0.1.2),随后补上"无头场景"(0.2.0),最后加固"多目标安全"(0.2.1)。
| 版本 | 类型 | 核心变化 |
|---|---|---|
| 0.1.0 | 首发 | 引入插件本体:编辑器内 Hindsight 聊天 + 笔记/记忆同步 |
| 0.1.1 | 功能 | 聊天笔记查看改进:grounded-note 引用、默认折叠、布局持久化、内联深度控制 |
| 0.1.2 | 修复 | 修复聊天视图问题,满足 Obsidian 社区商店(community store)审核要求 |
| 0.2.0 | 功能 | 新增无头 CLI 工具hindsight-obsidian-sync,无需运行 Obsidian 应用即可摄入/同步 vault |
| 0.2.1 | 修复 | 修复同步索引作用域,使 Obsidian 同步/对账按 memory bank 与 API 目标隔离,防止跨目标索引冲突 |
v0.1.0:插件首发,双向能力落地
0.1.0 是 Obsidian 集成的起点,带来两大核心能力:在编辑器内进行 Hindsight 聊天,以及将 Obsidian 笔记/记忆同步到 Hindsight。这两个能力对应仓库中两个独立前端:
- 插件本体(hindsight-integrations/obsidian/src/main.ts 等):聊天面板(
chat-view.ts)与同步逻辑(sync.ts); - 共享 HTTP 客户端(hindsight-integrations/obsidian/src/client.ts):封装了
retain(写入记忆)、deleteDocument(删除文档)、reflect(带引用问答)三个核心 API 调用。
插件的硬性设计原则:Obsidian 永远是唯一事实源
从 README 与sync.ts的注释可以看出,该插件有一条不可违背的规则:Hindsight 永远不是第二事实源。
- 同步是单向的:Obsidian → Hindsight,vault 是权威来源;
- 每条聊天回答都会引用来源笔记,方便你回到源头修改;
- 聊天记录默认不存储(可在设置中开启);
- 编辑一条笔记后,下次同步时 Hindsight 会重新收敛。
增量同步引擎(SyncEngine)
同步的核心实现在 hindsight-integrations/obsidian/src/sync.ts,SyncEngine针对最小化的SyncVault/SyncFile接口编写,因此可以脱离 Obsidian 运行时进行单元测试。
同步模型对应如下操作映射:
note created / edited ──▶ retain(documentId = note path) (upsert; replaces prior version) note renamed ──▶ deleteDocument(old) + retain(new) note deleted ──▶ deleteDocument(path) "Sync vault now" ──▶ reconcile: ingest drifted notes, prune orphans chat turn ──▶ reflect(question) over the whole bank └─ answer + citations (→ source notes) + reasoning本地索引(SyncIndex,记录 note path → 内容哈希 + mtime)保证只有变更的笔记才会被重新摄入:
- mtime 预过滤:上次同步后 mtime 未变 → 直接跳过,连文件都不读(
ingestFile中的 cheap pre-filter); - 内容哈希:mtime 变了但内容一致(如仅 touch)→ 只刷新索引中的 mtime,不触发重新摄入(SHA-256 前缀
sha256:); - 内容为空跳过:正文为空(frontmatter 剥离后无 body)的笔记直接
skipped,"nothing to ground on"; - upsert 语义:对同一
documentId重复retain即替换旧版本(updateMode: "replace"); - 对账(reconcile):全量遍历 vault 中应包含的笔记,摄入漂移项后,再按本地索引(而非服务端文档列表)清理孤儿文档——这样不会误删其他工具写入同 bank 的文档(如
conversation/…聊天记忆)。
隐式 scoping:用户只在召回时思考范围
这是 0.1.0 就确立的核心设计(源码注释引用 DESIGN.md §4.6)。每条笔记在摄入时被自动打上三类标签:
| 维度 | 标签 | 召回过滤示例 |
|---|---|---|
| Vault | vault:<name> | 只看 Work vault |
| 文件夹(含祖先) | folder:Work、folder:Work/Clients | Work/下全部内容 |
| 日期 | created:2026-03、updated:2026-06 | 本月更新的笔记 |
具体实现(sync.ts的folderTags与dateTags):
- 文件夹标签:对
Work/Clients/acme.md生成["folder:Work", "folder:Work/Clients"],因此folder:Work能匹配Work/下所有内容; - 日期标签:按"年 + 年月"两级桶生成(
["created:2026", "created:2026-03"]),因为 recall 没有硬性的日期范围过滤器,日期范围被表达为桶的 OR 组合; - metadata 附注:
path字段让 API 消费者(自动化)能把一次召回命中映射回具体笔记;vault字段用于多 vault 共库区分。
你自己在 frontmatter 里写的tags/aliases也会被透传保留。frontmatter 解析逻辑见 hindsight-integrations/obsidian/src/frontmatter.ts——它刻意保持轻量、无依赖,只识别 Obsidian 实际写入的简单键值/列表形式(tags、aliases、created/date),不做完整 YAML 解析。
多 vault 可以共享同一个 bank,靠vault:标签保持隔离;且UI 与 API 看到的是同一份数据——Obsidian 聊天面板和外部自动化(n8n、Hermes 等)命中同一个 bank、同一批标签,看到完全相同的 scoped 视图。
配置项
打开设置 → Hindsight即可配置:
| 设置项 | 默认值 | 说明 |
|---|---|---|
| API URL | https://api.hindsight.vectorize.io | Hindsight 服务地址(自托管用http://localhost:8888) |
| API key | — | Hindsight Cloud API key |
| Bank name | obsidian | 所有 vault 共享的 bank(用vault:标签隔离) |
| Include / exclude folders | — | 限制哪些笔记参与同步 |
| Sync on edit | 开启 | 编辑时自动重新摄入笔记 |
| Default chat depth | low | 聊天回答的 reflect 预算 |
| Remember conversations | 关闭 | 开启后聊天轮次会存进 Hindsight(在 vault 之外产生记忆) |
| Prefix document IDs | 开启 | 文档 ID 加 vault 前缀,防止共享 bank 下多 vault 冲突;单 vault 场景可关闭 |
插件还提供三个命令:Sync vault now(全量对账:摄入变更、清理删除)、Ingest current note(强制同步当前笔记)、Open chat(打开带引用的聊天面板)。
v0.1.1:聊天笔记查看体验升级
0.1.1 聚焦聊天面板的查看体验,带来四项改进:
- grounded-note 引用(grounded-note citations):答案明确列出命中的笔记,可点击打开;
- 默认折叠(collapsed-by-default):引用与推理披露默认收起,界面更清爽;
- 持久化布局(persisted layout):面板布局状态在会话间保留;
- 内联深度控制(inline depth controls):无需进入设置即可直接调整 reflect 预算。
这些能力与 README 中描述的 grounded chat 特性一致:侧边栏面板通过 Hindsight 的reflect在笔记上回答问题,每条答案列出检索到的笔记(点击打开)与推理披露(显示每一步查询了什么)。用提问栏上方的vault / folder下拉框限定问题范围,用New chat开启新线程,打开Debug logging还能在控制台看到完整的reflect请求与检索结果。
v0.1.2:为社区商店审核而做的修复
0.1.2 是一个合规性修复版本:修复 Obsidian 聊天视图中的问题,以满足Obsidian 社区商店(community store)评审要求。这一版本的意义在于流程层面——Hindsight Obsidian 插件此后具备了进入社区商店分发渠道的资质,用户可以通过 BRAT 等途径安装体验。
v0.2.0:无头 CLI 工具 —— 同一引擎的第二个前端
0.2.0 引入了hindsight-obsidian-sync无头 CLI 工具:不运行 Obsidian 应用,直接摄入/同步 vault 到 Hindsight。适合将 vault 放在常驻无头服务器上(由 Obsidian Sync 保持磁盘内容最新)的场景。
从源码结构看(hindsight-integrations/obsidian/src/node/),CLI 是建立在与插件完全相同的SyncEngine之上的薄封装,因此产生的文档 ID、scope 标签与 prune 归属与插件完全一致——一个 vault 可以在服务器上同步,之后在别处交互式打开 Obsidian 使用,两套前端不会互相打架或产生重复文档。两者的差异仅在三点(见cli.ts顶部注释):
- vault 来源:文件系统(
FsVault) vs Obsidian API; - 传输层:
fetch(fetch-transport.ts) vs Obsidian 的requestUrl(obsidian-transport.ts); - 同步索引位置:JSON 文件(
json-index.ts) vs 插件的data.json。
安装与基本用法
npm install -g @vectorize-io/hindsight-obsidian # one-shot reconcile(适合 cron) hindsight-obsidian-sync reconcile \ --vault ~/Vaults/Brain --bank my-vault \ --api-url https://api.hindsight.vectorize.io --api-token hsk_... # 或常驻运行,实时同步变更 hindsight-obsidian-sync reconcile --vault ~/Vaults/Brain --bank my-vault --watch--api-url/--api-token会回退到环境变量HINDSIGHT_API_URL/HINDSIGHT_API_TOKEN。完整参数(与cli.ts中USAGE一致):
| 参数 | 说明 |
|---|---|
--vault <path> | vault 根目录(必填) |
--bank <id> | 目标 Hindsight bank id(必填) |
--api-url <url> | API 基础 URL(或HINDSIGHT_API_URL) |
--api-token <token> | API token(或HINDSIGHT_API_TOKEN) |
--include <folder> | 仅同步该文件夹(可重复;默认整个 vault) |
--exclude <folder> | 跳过该文件夹(可重复) |
--vault-name <name> | 用于标签/ID 的 vault 名(默认取 vault 目录名) |
--prefix-doc-id | 文档 ID 加 vault 名前缀(多 vault 共享 bank 用) |
--index <file> | 同步索引 JSON 路径(默认在~/.hindsight/obsidian/下按目标生成) |
--watch | 常驻运行,实时同步变更 |
--help | 显示帮助 |
CLI 只接受reconcile一个子命令(也是默认命令),用法错误输出到 stderr 并返回退出码 2,--help输出到 stdout 返回 0(parseCliArgs与runCli的实现)。
watch 模式:基于 chokidar 的实时同步
--watch模式下(cli.ts的watchVault),CLI 先用一次初始reconcile建立基线,再用 chokidar 监听 vault 目录:
- 忽略点目录(
.obsidian、.trash、.git等); awaitWriteFinish: { stabilityThreshold: 300, pollInterval: 100 }合并部分保存;add/change事件 → 强制摄入对应笔记;unlink事件 → 删除对应文档;- 文件重命名在 chokidar 中体现为
unlink(old) + add(new),引擎天然按"删除旧路径 + 创建新路径"处理,与插件专用重命名路径结果一致。
v0.2.1:同步索引作用域修复 —— 跨目标隔离与 fail-closed
0.2.1 是本次 changelog 中最值得关注的安全修复:将同步索引作用域按 memory bank 与 API 目标隔离,防止跨目标索引冲突。修复的核心机制在 hindsight-integrations/obsidian/src/node/json-index.ts。
默认索引路径:刻意放在 vault 之外
CLI 的同步索引(相当于插件data.json)默认是一个按目标隔离的文件:
~/.hindsight/obsidian/<vault>-<bank>-<fingerprint>.json它刻意放在 vault 之外,这样 Obsidian Sync 永远不会把它传播到其他设备。文件名中的 fingerprint 是目标身份(IndexIdentity)的 12 位 SHA-256 摘要:
// IndexIdentity: apiOrigin + bankId + vaultPath + vaultName + prefixDocId任意绑定字段不同 → fingerprint 不同 → 即使两个 vault 同名也绝不共用索引文件。
索引与目标的绑定:fail-closed
索引绑定了其建立时所针对的目标(API origin、bank、vault 路径、文档 ID 命名空间)。loadIndex在校验时发现持久化的目标身份与当前不一致,就会抛出IndexIdentityErrorfail-closed——给出可操作的错误消息,而不是静默跳过文件,或把删除误归因到它从未写入过的 bank:
- 索引文件缺少 identity 元数据(旧版遗留)→ 拒绝复用,提示删除后从零重同步或换新路径;
- 目标身份字段不一致 → 逐字段列出差异,提示使用独立
--index路径或删除后重同步; - 索引损坏/不可读 → 仅警告后从空索引开始(内容哈希会跳过未变更的笔记),并说明孤儿清理需等索引重建。
刻意不绑定的是 include/exclude 作用域:同一目标下收窄范围本就应当修剪新排除的笔记(因为该摄入器在目标上拥有这些文档);而所有跨目标危害都源于目标变更,这正是绑定所拒绝的。
索引写入的原子性
makePersist采用"写临时文件 + 原子 rename"策略,保证永远不会留下半写状态的索引文件;持久化时还会盖上version信封版本号与identity,供下次加载校验。
CLI 与插件混用的注意事项
如果 CLI 和插件同时针对同一 bank + vault:请保持两者的 scope 配置一致(
--include/--exclude、--vault-name、--prefix-doc-id与插件设置匹配)。它们各自维护自己的索引,一次对账只会修剪自己索引跟踪的文档——两套前端 scope 不一致时,一方可能修剪掉另一方拥有的文档。
本地开发与手动安装
插件的开发工作流(hindsight-integrations/obsidian/package.json):
npm install npm run lint # tsc --noEmit npm test # vitest npm run build # esbuild → main.js想在真实 vault 中试用,把构建产物main.js、manifest.json、styles.css复制到<vault>/.obsidian/plugins/hindsight/并启用插件即可。插件为桌面端专用(manifest.json中isDesktopOnly: true),要求 Obsidian ≥ 1.7.2,Node ≥ 20.15。
测试方面,仓库在 hindsight-integrations/obsidian/tests/ 提供了完整覆盖:sync.spec.ts(同步引擎)、cli.spec.ts(CLI 参数解析)、reconcile-integration.spec.ts(对账集成)、watch.spec.ts(watch 模式)、json-index.spec.ts(索引绑定)等;sync.ts刻意面向最小接口SyncVault/SyncFile设计,正是为了能在无 Obsidian 运行时下单元测试。
自托管快速上手
不想依赖 Hindsight Cloud 时,可以本地起一个服务端:
pip install hindsight-all export HINDSIGHT_API_LLM_API_KEY=your-openai-key hindsight-api随后在插件设置中把 API URL 指向http://localhost:8888,并在 CLI 中使用--api-url http://localhost:8888即可。
总结
Obsidian 集成的版本演进勾勒出一条清晰的产品化路径:0.1.0 确立"单向同步 + 隐式 scoping + grounded chat"的核心架构与"vault 是唯一事实源"的设计原则;0.1.1/0.1.2 打磨聊天查看体验并打通社区商店渠道;0.2.0 通过共享同一SyncEngine的无头 CLI 把同一套同步语义扩展到服务器场景;0.2.1 则以目标绑定的同步索引收紧了多 bank/多 API 场景下的数据安全边界。对于想要深度使用 Hindsight 记忆能力的 Obsidian 用户,hindsight-integrations/obsidian/README.md 是配置入口,hindsight-integrations/obsidian/src/sync.ts 与 hindsight-integrations/obsidian/src/node/json-index.ts 则是理解其底层机制的最佳起点。
【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考