Wechsels
dsh-zotero-wiki
DeepSeekHarness × Zotero 插件:自动同步文献库,MinerU 解析 PDF,DeepSeek 全文阅读生成结构化笔记,编译成可检索的 Obsidian LLM Wiki。
- Stars
- 2
- Language
- TypeScript
- Created
- Aug 14, 2026
- Updated
- Aug 15, 2026
Introduction
dsh-zotero-wiki
中文 | English
DeepSeekHarness(dsh)× Zotero 插件:自动同步 Zotero 文献库,用 MinerU 解析 PDF、用 DeepSeek 阅读全文,把文献编译成可检索的 Obsidian Wiki,并让 Agent 在回答时附带可追溯的文献引用。
项目定位(范围)
是什么:一个 Node/Cordis 风格的 dsh 插件 + 独立 CLI。它把你的 Zotero 文献库变成一座持续更新的 Obsidian 知识库,并暴露原生工具供 Agent 检索。
完整链路:
Zotero(本地库 / Web API)
└─ sync:增量同步元数据 → .zotero-sync/sync.db(SQLite 状态库)
└─ parse:MinerU 官方平台解析 PDF → raw/ 源文件 + DeepSeek 全文笔记 → wiki/ 单篇页
└─ compile:主题综述、索引、交叉链接、归档标记
└─ query:Agent 通过 query_zotero_wiki 检索,回答附 [Zotero key, §章节] 引用
明确不做(保持轻量):向量数据库、自动聚类、多用户服务端、定时后台服务、Web UI、Zotero 注释(高亮/批注)同步、引用页码提取。
特性
| 能力 | 说明 |
|---|---|
| 双源同步 | 本地 zotero.sqlite(临时副本只读打开,不干扰 Zotero 进程)或 Zotero Web API(version 游标增量) |
| 交互式范围 | 全部 / 指定 Collection(含子级)/ 标签过滤,选择结果持久化,启动时静默复用 |
| PDF 智能解析 | MinerU 官方开放平台(上传→轮询→Zip),解析产物落为 raw/ bundle(Markdown + images/),原始 PDF 不落盘 |
| DeepSeek 全文笔记 | deepseek-chat 全文直读(100K token 上限、尾部截断),产出中文结构化笔记(摘要/方法/结论/创新点/局限/关键引用) |
| 优雅降级 | 无 PDF 或解析失败 → 基于标题+摘要生成简版笔记;后续补 PDF 自动升级全文笔记 |
| 配额与并发 | 单轮解析上限 MAX_PARSE_PER_SYNC(默认 50),并发 3,失败记库、下轮可重跑 |
| Wiki 编译 | 主题综述(LLM 增量改写)、index/authors/years 索引、See Also 交叉链接、归档标记(不删页)、追加式 log |
| Agent 查询 | minisearch 内存全文检索 + 中文 bigram 分词,返回片段与 [key, §章节] 章节级引用;无命中明确告知,不编造 |
当前状态与路线图
| 里程碑 | 内容 | 状态 |
|---|---|---|
| M1 | Zotero 双源读取与增量同步 | ✅ 已落地并通过真实库验收 |
| M2 | MinerU 解析 + DeepSeek 笔记生成 | ✅ 已落地并通过真实环境验收(7 篇全文笔记 + 37 篇摘要降级,0 失败) |
| M3 | 主题归类与 Wiki 生成 | ✅ 已落地并通过真实环境验收(deepseek-v4-flash 综述生成 + 幂等二跑) |
| M4 | dsh 插件集成与查询工具 | ✅ 已落地并通过 dsh 真机联调 |
| M5 | 测试、打包、文档完善 | 进行中 |
路线图中(不阻塞使用):向量检索增强、Zotero 注释同步、引用页码提取、术语表、定时同步。问题与建议请提 Issues。
架构
┌────────────────────┐ ┌─────────────────────────────────────────┐
│ Zotero 桌面端 │ ───▶ │ dsh-zotero-wiki │
│ / Zotero Web API │ │ │
└────────────────────┘ │ sync 引擎 ──▶ SQLite 状态库 │
│ parse 管道 ─▶ MinerU + DeepSeek │
┌────────────────────┐ │ compile 器 ─▶ 综述/索引/链接/归档 │
│ MinerU 官方平台 │ ◀──▶ │ query 索引 ─▶ minisearch + bigram │
│ DeepSeek API │ │ │
└────────────────────┘ │ dsh 工具:query / sync / parse │
└────────────────┬────────────────────────┘
▼
┌─────────────────────────────────────────┐
│ Obsidian Vault │
│ raw/(解析源文件) wiki/(笔记与索引) │
│ references/(模板) .zotero-sync/(状态)│
└─────────────────────────────────────────┘
生成的 Vault 结构:
<Vault>/
├── raw/<topic>/YYYY-MM-DD-<slug>/ # MinerU 产物(Markdown + images/,只读)
├── references/ # 模板(首次 parse 自动写入)
├── wiki/
│ ├── index.md / authors.md / years.md / log.md
│ └── <topic>/
│ ├── _index.md # 主题综述(LLM 生成)
│ └── <article>.md # 单篇笔记(frontmatter + 章节化正文)
└── .zotero-sync/sync.db # 同步游标、条目、处理状态(不入 git)
安装
环境要求
- Node.js ≥ 22.19(使用内置
node:sqlite) - Zotero 本地库或 Web API Key
- (parse 阶段)MinerU Token(mineru.net API 管理页申请)与 DeepSeek API Key
从源码安装(MVP 阶段推荐)
git clone https://github.com/Wechsels/dsh-zotero-wiki.git && cd dsh-zotero-wiki
npm install
cp .env.example .env # 然后按需编辑,见下方配置
npm run build
注册为 dsh 插件(本地路径安装)
npx -y @deepseek-ai/dsh plugin --profile web add file:/path/to/dsh-zotero-wiki
插件加载后:dsh 启动时自动静默增量同步并重建查询索引;聊天中即可调用三个原生工具。
配置
所有配置在插件目录下的 .env(参见 .env.example):
| 键 | 必填 | 默认 | 说明 |
|---|---|---|---|
ZOTERO_MODE | 是 | local | local / web |
ZOTERO_DATA_DIR | local 可选 | 自动探测 | 含 zotero.sqlite 与 storage/ 的目录 |
ZOTERO_API_KEY / ZOTERO_USER_ID / ZOTERO_GROUP_ID | web 必填 | — | Web API 凭据(Group 优先于 User) |
OBSIDIAN_VAULT_PATH | 是 | — | Vault 根目录 |
SYNC_SCOPE_JSON | 否 | 交互选择 | 持久化同步范围,如 {"mode":"all","collectionKeys":[],"tags":[]} |
MINERU_TOKEN | parse 必填 | — | MinerU 官方平台 Token |
MINERU_MODEL_VERSION | 否 | pipeline | 可选 vlm(质量更高) |
MINERU_TIMEOUT_MS | 否 | 1200000 | 单文件解析超时 |
DEEPSEEK_API_KEY | parse/综述必填 | — | DeepSeek API Key |
DEEPSEEK_MODEL | 否 | deepseek-chat | 全文笔记生成模型 |
REVIEW_MODEL | 否 | deepseek-v4-flash | 主题综述生成模型(compile) |
NOTE_TOKEN_LIMIT | 否 | 100000 | 每篇全文截断上限(按字符保守估算) |
MAX_PARSE_PER_SYNC | 否 | 50 | 单轮最多上传解析篇数(保护 MinerU 免费额度) |
PARSE_CONCURRENCY | 否 | 3 | 解析并发上限 |
REVIEW_REGEN_THRESHOLD | 否 | 5 | 综述累计新增 N 篇后全量重生成 |
REVIEW_NOTE_CHARS | 否 | 2000 | 综述生成时每篇笔记送入 LLM 的字数上限 |
用法
CLI(完整能力,首次配置入口)
node dist/cli.js sync # 增量同步;首次弹交互选择范围并持久化
node dist/cli.js sync --interactive # 重新选择同步范围
node dist/cli.js parse --dry-run # 预览待解析候选与配额占用
node dist/cli.js parse # MinerU 解析 + DeepSeek 笔记生成
node dist/cli.js compile # 综述/索引/交叉链接/归档标记
node dist/cli.js compile --no-review # 跳过 LLM 综述(无需 DEEPSEEK_API_KEY)
dsh 原生工具(Agent 侧)
| 工具 | 说明 |
|---|---|
query_zotero_wiki(query, topic?, max_results?) | 检索 Wiki,返回片段、元数据与 [Zotero key, §章节] 引用;无命中返回"当前 Wiki 中没有找到相关文献" |
sync_zotero_wiki() | 手动增量同步并重建索引 |
parse_zotero_wiki() | 手动执行解析与笔记生成(受配额限制)并重建索引 |
典型对话:"帮我总结荧光材料方向这几年的进展" → Agent 调用 query_zotero_wiki → 基于命中片段与引用编制回答。
同步行为约定
- 启动自动同步按上次持久化的范围静默执行;交互选择只在首次或手动
--interactive时出现 - 已有页面更新/扩充,新文献新增,
log.md追加;永不物理删除页面——Zotero 中删除的条目在 Wiki 中标记status: archived,恢复后自动复原 - 未归入任何 Collection 的文献跳过,待用户在 Zotero 中分类后下轮处理
- 一篇文献属于多个 Collection:
raw/只存一份(首个 Collection),每个主题的wiki/各生成一份笔记页
开发
npm run typecheck # tsc --noEmit
npm test # vitest(18 个测试文件 / 82 个用例)
npm run build # vite → dist/cli.js + dist/plugin.js
npm run dev # 监听构建
src/
├── cli.ts # CLI(sync / parse / compile)
├── plugin.ts # dsh 集成层(工具注册 + 启动 sync,依赖注入可测)
├── config.ts # .env 加载与回写
├── sources/ # Zotero 双源(local sqlite / Web API)
├── sync/ # 同步引擎与 scope 过滤
├── parse/ # MinerU 客户端、Zip 解包、单篇 pipeline
├── llm/ # DeepSeek 客户端、prompts、截断
├── compile/ # 综述、索引、See Also、归档、日志
├── query/ # minisearch 索引、bigram 分词、检索
├── wiki/ # topic 映射、笔记写盘、frontmatter、模板
└── state/ # SQLite 状态库
dsh/index.js # 插件薄壳 → dist/plugin.js
设计文档:deepseek-zotero-plugin方案.md(总体方案)与 M1/M2/M3/M4-实现计划.md(各里程碑实现计划)。
常见问题
Q:启动时提示 "SYNC_SCOPE_JSON 未配置"?
在终端运行一次 node dist/cli.js sync 完成交互式范围选择;dsh 运行环境无交互终端,首次配置必须走 CLI。
Q:本地模式提示找不到 Zotero 数据目录?
在 .env 显式设置 ZOTERO_DATA_DIR 指向含 zotero.sqlite 的目录(如 D:\ZoteroLibrary)。
Q:parse 很慢 / 部分篇目一直是 pending?
MinerU 免费额度为每日 2000 页高优先级,超出后排队降速;调小 MAX_PARSE_PER_SYNC 分多轮执行即可。
Q:中文查询效果不理想?
当前为 bigram 分词的关键词检索(零原生依赖);可尝试更具体的关键词或加 topic 过滤。向量检索增强在路线图中。
Q:npx @deepseek-ai/dsh 报 'dsh' 不是内部或外部命令?
npx 在部分 Windows 环境下无法生成可执行 shim。改用本地 dsh 源码仓的 CLI 入口即可:node <dsh 仓库>/apps/cli/lib/bin.js plugin --profile web add file:/path/to/dsh-zotero-wiki。
Q:dsh 启动报 Cannot find module .../dist/plugin.js?
本地 file: 安装时 pnpm 打包会遵守 .gitignore;确保 package.json 的 files 字段显式包含 dist(本仓库已配置)。
Q:能在 Obsidian 里手动编辑笔记吗?
可以。只有 ## See Also 章节、索引页(index/authors/years)与归档提示块会被自动重写,其余内容不受影响。
许可证 / License
dsh-zotero-wiki
中文 | English
A DeepSeekHarness (dsh) plugin for Zotero: automatically syncs your Zotero library, parses PDFs with MinerU, reads full texts with DeepSeek, compiles everything into a searchable Obsidian wiki, and lets your agent answer questions with traceable literature citations.
Positioning & Scope
What it is: a Node/Cordis-style dsh plugin plus a standalone CLI that turns your Zotero library into a continuously updated Obsidian knowledge base, exposing native tools for agent retrieval.
Full pipeline:
Zotero (local DB / Web API)
└─ sync: incremental metadata sync → .zotero-sync/sync.db (SQLite state)
└─ parse: MinerU PDF parsing → raw/ bundles + DeepSeek full-text notes → wiki/ pages
└─ compile: topic reviews, indexes, cross-links, archive marks
└─ query: agents search via query_zotero_wiki, answers cite [Zotero key, §section]
Explicitly out of scope (kept lightweight): vector databases, automatic clustering, multi-user server, scheduled background services, Web UI, Zotero annotation/highlight sync, page-number citations.
Features
| Feature | Description |
|---|---|
| Dual-source sync | Local zotero.sqlite (read-only temp copy, never blocks Zotero) or Zotero Web API (version-cursor incremental) |
| Interactive scope | All / specific Collections (incl. children) / tag filter; the choice is persisted and silently reused at startup |
| PDF parsing | MinerU official open platform (upload → poll → zip); results stored as raw/ bundles (Markdown + images/); original PDFs are never persisted |
| DeepSeek notes | deepseek-chat full-text reading (100K-token cap, tail truncation) producing structured Chinese notes (abstract / method / conclusions / contributions / limitations / key quotes) |
| Graceful degradation | No PDF or parse failure → concise note from title + abstract; automatically upgraded to a full-text note once a PDF is added |
| Quota & concurrency | Per-run parse cap MAX_PARSE_PER_SYNC (default 50), concurrency 3, failures recorded and retryable next run |
| Wiki compile | LLM topic reviews (incremental rewrite), index/authors/years pages, See Also cross-links, archive marks (no page deletion), append-only log |
| Agent query | minisearch in-memory full-text search with Chinese bigram tokenization; returns snippets with [key, §section] citations; explicitly reports "not found", never fabricates |
Status & Roadmap
| Milestone | Scope | Status |
|---|---|---|
| M1 | Zotero dual-source reading & incremental sync | ✅ landed, verified against a real library |
| M2 | MinerU parsing + DeepSeek note generation | ✅ landed, verified in a real environment (7 full-text notes + 37 abstract fallbacks, 0 failures) |
| M3 | Topic compilation & wiki generation | ✅ landed, verified in a real environment (deepseek-v4-flash reviews + idempotent re-run) |
| M4 | dsh plugin integration & query tools | ✅ landed, verified with a real dsh installation |
| M5 | Testing, packaging, documentation | in progress |
On the roadmap (non-blocking): vector retrieval, Zotero annotation sync, page-number citations, glossary, scheduled sync. Please file issues and suggestions on GitHub Issues.
Installation
Requirements
- Node.js ≥ 22.19 (uses built-in
node:sqlite) - A local Zotero library or a Zotero Web API key
- (for
parse) a MinerU token (from mineru.net) and a DeepSeek API key
Install from source (recommended during MVP)
git clone https://github.com/Wechsels/dsh-zotero-wiki.git && cd dsh-zotero-wiki
npm install
cp .env.example .env # then edit; see Configuration below
npm run build
Register as a dsh plugin (local-path install)
npx -y @deepseek-ai/dsh plugin --profile web add file:/path/to/dsh-zotero-wiki
Once loaded, dsh silently runs an incremental sync at startup and rebuilds the query index; the three native tools become available in chat.
Configuration
All settings live in .env inside the plugin directory (see .env.example). Key entries:
| Key | Required | Default | Purpose |
|---|---|---|---|
ZOTERO_MODE | yes | local | local / web |
ZOTERO_DATA_DIR | local, optional | auto-detect | Directory containing zotero.sqlite and storage/ |
ZOTERO_API_KEY / ZOTERO_USER_ID / ZOTERO_GROUP_ID | web | — | Web API credentials (Group wins over User) |
OBSIDIAN_VAULT_PATH | yes | — | Vault root |
SYNC_SCOPE_JSON | no | interactive | Persisted sync scope, e.g. {"mode":"all","collectionKeys":[],"tags":[]} |
MINERU_TOKEN | parse | — | MinerU official platform token |
MINERU_MODEL_VERSION | no | pipeline | vlm for higher quality |
DEEPSEEK_API_KEY | parse/reviews | — | DeepSeek API key |
DEEPSEEK_MODEL | no | deepseek-chat | Model for full-text note generation |
REVIEW_MODEL | no | deepseek-v4-flash | Model for topic review generation (compile) |
NOTE_TOKEN_LIMIT | no | 100000 | Per-paper truncation cap (conservative char-based estimate) |
MAX_PARSE_PER_SYNC | no | 50 | Max uploads per run (protects MinerU free quota) |
PARSE_CONCURRENCY | no | 3 | Parse concurrency |
REVIEW_REGEN_THRESHOLD | no | 5 | Regenerate a topic review after N accumulated new notes |
Usage
CLI (full capabilities; first-run configuration entry point)
node dist/cli.js sync # incremental sync; interactive scope picker on first run
node dist/cli.js sync --interactive # re-select sync scope
node dist/cli.js parse --dry-run # preview pending candidates and quota usage
node dist/cli.js parse # MinerU parsing + DeepSeek note generation
node dist/cli.js compile # reviews / indexes / cross-links / archive marks
node dist/cli.js compile --no-review # skip LLM reviews (no DEEPSEEK_API_KEY needed)
dsh native tools (agent side)
| Tool | Description |
|---|---|
query_zotero_wiki(query, topic?, max_results?) | Search the wiki; returns snippets, metadata and [Zotero key, §section] citations; replies "nothing found in the wiki" when empty |
sync_zotero_wiki() | Manual incremental sync + index rebuild |
parse_zotero_wiki() | Manual parse & note generation (quota-limited) + index rebuild |
Sync behavior contract
- Startup sync silently reuses the last persisted scope; interactive selection only happens on first run or with
--interactive - Existing pages are updated/extended, new items create new pages,
log.mdis append-only; pages are never physically deleted — items removed from Zotero getstatus: archivedand are auto-restored if they come back - Items without any Collection are skipped until classified in Zotero
- An item in multiple Collections: one copy in
raw/(first Collection), one note page per topic inwiki/
Development
npm run typecheck # tsc --noEmit
npm test # vitest (18 test files / 82 cases)
npm run build # vite → dist/cli.js + dist/plugin.js
npm run dev # watch build
Design docs (Chinese): deepseek-zotero-plugin方案.md (overall plan) and M1–M4-实现计划.md (per-milestone implementation plans).
FAQ
Q: Startup says "SYNC_SCOPE_JSON not configured"?
Run node dist/cli.js sync once in a terminal to complete the interactive scope selection; the dsh runtime has no interactive TTY, so first-time configuration must go through the CLI.
Q: Local mode can't find the Zotero data directory?
Set ZOTERO_DATA_DIR in .env explicitly to the directory containing zotero.sqlite.
Q: parse is slow or items stay pending?
MinerU's free quota is 2000 high-priority pages/day; beyond that, jobs queue at lower priority. Lower MAX_PARSE_PER_SYNC and run in multiple rounds.
Q: Chinese search quality?
Tokenization is bigram-based keyword search (zero native dependencies). Try more specific keywords or a topic filter; vector retrieval is on the roadmap.
Q: npx @deepseek-ai/dsh says 'dsh' is not recognized?
npx may fail to create the executable shim on some Windows setups. Use the CLI entry from a local dsh source checkout instead: node <dsh-repo>/apps/cli/lib/bin.js plugin --profile web add file:/path/to/dsh-zotero-wiki.
Q: dsh boot fails with Cannot find module .../dist/plugin.js?
For local file: installs, pnpm packing honors .gitignore; make sure package.json has an explicit files field including dist (already configured in this repo).
Q: Can I hand-edit notes in Obsidian?
Yes. Only the ## See Also section, the index pages (index/authors/years) and archive notice blocks are rewritten automatically; everything else is preserved.