npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

dsh-plugin-zotero

v0.8.1

Published

Map your Zotero library into DSH: let AI operate Zotero for you and help you read papers. Browse collections and tags in the sidebar, read PDFs with highlights in place, and cite excerpts, annotations, notes or whole items into the chat. The model works f

Readme

dsh-plugin-zotero

把 Zotero 文献库映射进 DSH:用AI管理操作Zotero,读文献时让AI辅助你。

本插件把 Zotero 的目录分类、条目元数据、PDF 全文、笔记与标注接入 DSH,将「检索文献 — 精读全文 — 摘录标注 — 与模型讨论 — 形成稿子」收进同一条工作流:右侧栏按分类与标签浏览文库,按标题 / 摘要筛选当前范围,双击条目即在 DSH 内打开独立阅读页,PDF 整页渲染、高亮原位叠加,同一篇文献的原文与译本附件可在页内切换;读到关键段落时可直接划词摘录、划词翻译,公式图表这类没法划选的内容还能框一块正文截图,也可引用该条标注、笔记乃至整篇文献,以引用胶囊写进当前会话草稿,模型随即基于原文接续完成综述、方法对比、数据提取与引文核对。

模型侧同样具备完整的检索与整理能力:检索文库、精读 PDF、汇总高亮与笔记、按主题新建分类并归类,也可以把本地下载的论文导入 Zotero,读完外文文献后把译文作为附件回挂到对应条目。凡 Zotero 本地接口与集成 MCP 能提供的操作,均可由模型代劳。

不用写代码,也不用记命令。第一次使用照着安装与设置点 5 步就行(装插件、给 Zotero 装个桥接小插件、打开一个通信开关、确认连上、按需开写权限),全都是一次性的,以后打开 Zotero 和 DSH 直接用。

截图

DSH 右侧栏中的 Zotero 文献库面板

上图为 DSH 会话与右侧「Zotero 文献库」面板:左侧分类树与标签面板,右侧是当前范围的条目列表;双击条目会在右侧栏顶层单开一个标签页,整页展示 PDF(可缩放、叠加高亮标注),元数据、摘要、笔记、标注与附件收进左上角的信息按钮。点击图片可查看原图。

在 DSH 内边读 PDF 边与 AI 交互

上图为 DSH 内的文献阅读现场:右侧标签页整页渲染 PDF(图为译文附件,原文与译本可在信息面板切换),点正文里的高亮标注即弹出标注卡片,原文、类型与「引用 / Zotero」入口都在手边;左侧会话里该段原文已作为引用写入草稿,模型据此继续作答。点击图片可查看原图。

它能替你做的事,举几个常见例子:

  • 找文献:按标题、年份、全文关键词检索,也能跨库搜高亮和批注,快速回答「我收过哪些讲 XX 的文章」;右侧栏里还能按分类、标签和标题 / 摘要逐层缩小范围。
  • 读文献:双击条目就在 DSH 内开独立阅读页,PDF 整页渲染、高亮原位叠加,原文与译本附件随时切换;摘要、全文、笔记与标注都能在这里读完,写综述、做对比、提取数据都行,需要精确引用时会保留原文措辞。外文段落划选即弹出「翻译」浮层,原文 / 译文左右对照、默认按语种自动中英互译,可拖动缩放,也能临时换成模型精翻;左上角一枚目录按钮把 PDF 书签、网页快照标题、笔记标题统一收进同一份大纲。开启写权限后,正文里划选即选颜色落一条高亮或下划线(跨页自动按页拆条)、随手带一句评论,改色、改评论、改页码、加标签、高亮↔划线互转、删除都在同一处;笔记也能新建、编辑、删除。改动直接进 Zotero 库,不是插件里的副本。
  • 整理文库:新建、重命名、移动、删除分类,批量把条目加入或移出分类。你说一句「把这几篇归到『待读』里」,它就照做。
  • 帮你入库:把本地下载好的论文、PDF 交给 DSH 导入 Zotero;也可以让它读完外文文献后,把译文作为附件挂回条目。
  • 带进对话:右侧面板单条目引用、列表多选批量引用、阅读页划词摘录与点高亮引用、单标签或多标签引用、整分类引用、划词翻译与正文截图,都能一键写进当前会话草稿(不自动发送),你再接着说要求。独立笔记会自动改插笔记正文,不给模型一个只剩标题的空壳。全部以「引用胶囊」的形式出现,草稿里一眼看清引了哪几篇 / 哪几段,单独删掉某一条也不影响其他内容;完整文本在发送那一刻才展开给模型,发出去之后胶囊仍留在会话历史里,悬停可预览、点开可看全文。读到公式、图表、版式这类没法划选的内容时,用左上角的**「截图加入对话」按钮**框一块正文——微信式定格框选,一张图片附件与出处说明(文献身份、页码、章节、区域文字)作为同一条消息发出。
  • 安全可控:写能力默认全关 —— 「设置 → Zotero文献库」里的「Zotero 写权限」不开启,面板就是纯只读,模型也看不到任何写工具。开启后写操作优先走集成 MCP(在 Zotero 进程内执行,不触发本地 API 授权弹窗),标注与笔记这两类 MCP 覆盖不到的才走本地 API,需要一次性点「始终允许」授权;模型侧每一项工具都能单独开关。

面板布局与 Zotero 本体一致:顶部状态栏显示连接状态并提供刷新;左侧是分类树,树下是可拖高、可折叠的标签面板;右侧列表显示当前范围(分类 / 全库 / 标签筛选后)的条目。分类树与条目列表之间的分隔条可拖动,宽度按本机记住。列表里单击条目选中、Ctrl / Cmd 点选多选,双击才在右侧栏顶层单开一个标签页看详情。阅读页就开在会话旁边的标签里,边读边摘、边问边改,不必在 Zotero 与 AI 两个窗口之间来回切换。

面向使用者的完整说明(入口、交互、toast 与错误对照表)见 插件使用说明。

安装与设置

第一次使用要走 5 步,全程点鼠标,不用敲命令、不用写代码。这 5 步都是一次性的,做完以后每天只要打开 Zotero 和 DSH 就能用。

| 步骤 | 在哪做 | 做什么 | 必须吗 | |---|---|---|---| | 1 | DSH | 安装本插件 | 必须 | | 2 | Zotero | 装桥接小插件 Zotero MCP Plugin | 想让 AI 动手就必须 | | 3 | Zotero | 打开「允许本机其他程序通信」开关 | 必须 | | 4 | DSH | 到「设置 → Zotero文献库」看一眼 | 必须(只是确认) | | 5 | DSH + Zotero | 打开写权限并授权 | 想改库 / 划高亮才需要 |

开始前请确认两件事:Zotero 桌面版已装好并且正开着(本插件读的是你本机 Zotero 里的文献,不是云端);DSH 桌面版 ≥ 0.2.1-rc.3。

第 1 步:在 DSH 里安装本插件

  1. 打开 DSH,进「设置」→ 左侧的「插件市场」。
  2. 如果页面提示「还没有插件索引」,点「添加索引源」,把这个地址填进去再点「添加」:https://awesome-dsh-plugin.com/index.json。这是社区维护的插件目录,只需加一次。
  3. 回到「发现」,搜索框里输入 zotero,找到 dsh-plugin-zotero(作者 peijiping),点开它。
  4. 点「安装」,在弹出的确认框里确认,等安装进度走完。
  5. 按提示重启 DSH。

怎么算装好了:重启后 DSH 右侧栏多出「Zotero 文献库」入口,「设置」左侧列表里(「Agent 预设」下面)多出「Zotero文献库」一页。看到这两个就对了。

dsh plugin --profile <profile> add dsh-plugin-zotero

包内是预构建产物(lib/ + client/client.js),安装时不运行构建脚本,无需 allowBuilds 授权。要求 dsh ≥ 0.2.1-rc.3(package.json 的 engines.dsh 为 >=0.2.1-rc.3 <0.3.0-0)。本地源码开发见方案一:本地路径安装。

第 2 步:给 Zotero 装一个桥接小插件

AI 要替你新建分类、导入论文、改条目信息,靠的是 Zotero 端的一个小插件(叫 Zotero MCP Plugin)。它装在 Zotero 里,装完不用配置。

  1. 打开 Zotero,菜单「工具 → 插件」。
  2. 在插件市场里搜 mcp。
  3. 安装列表第一行、标签是 ai / integration 的那个 Zotero MCP Plugin(包名 zotero-integrated-mcp)。
  4. 装好后不需要额外设置,它默认在 http://127.0.0.1:23120/mcp 上待命。

Zotero 插件市场中安装 Zotero MCP Plugin

上图为 Zotero 插件市场,第一行「Zotero MCP Plugin」已安装。

装完还要在它的设置里勾选「允许写操作」,否则 AI 能查能读,但让它新建分类会直接报「写操作已禁用」。

这一步不做也能用右侧面板浏览文献,只是 AI 那边的 Zotero 工具用不了。如果你装的是别的 MCP 插件、或端口不是 23120,见第 4 步改地址。

第 3 步:打开 Zotero 的本机通信开关

Zotero 默认不允许别的程序读它的文献库。这个开关就是放行同一台电脑上的程序(也就是 DSH)——数据不出本机,端口只对本机开放。

Zotero → 设置 → 高级 → 勾选「允许此计算机上的其他应用程序与 Zotero 通信」。

在 Zotero 高级设置中允许其他应用与 Zotero 通信

上图为 Zotero「设置 → 高级」中开启本地 API 的开关。

没勾选的话,DSH 面板会显示「Zotero 未连接」并提示你回来开这个开关。想自己确认一下,可以在浏览器里打开 http://127.0.0.1:23119/api/,看到 Zotero is running 就是通了(命令行等价写法:curl http://127.0.0.1:23119/api/)。

第 4 步:回到 DSH 确认已经连上

打开 DSH 的「设置」,点左侧列表里的「Zotero文献库」。这一页就是本插件的全部设置,从上到下四块:Zotero 写权限、API 设置、MCP 设置(含下方的 MCP 工具清单)、划词翻译。

  • 正常情况一个字都不用改,默认值就是对的。每一项的含义见设置项说明。
  • 回到会话,打开右侧栏的「Zotero 文献库」:顶部状态栏显示连接状态,左边应该已经列出你在 Zotero 里的分类。看到分类树就说明整条链路通了。
  • 如果 Zotero 里装的 MCP 插件不是第 2 步那个、或者端口不是 23120:把「MCP 设置 → 集成 MCP 地址」改成实际地址(形如 http://127.0.0.1:<端口>/mcp)。改完自动保存、立即生效,不用重启。

第 5 步(可选):想让 AI 帮你改文献库

默认是只读的:面板只能看和引用,AI 也看不到任何写工具。想在读 PDF 时直接划高亮、写笔记,或者让 AI 帮你整理分类、导入论文,就打开写权限:

  1. 「设置 → Zotero文献库」最上面那块「Zotero 写权限」,打开「允许写入 Zotero」开关。
  2. 等一秒左右让它自动保存(页面会闪一下「正在自动保存…」),下面的按钮就可以点了。
  3. 点「授权 Zotero 写权限」。Zotero 会弹出一个确认框,一定要选「始终允许」——选「允许」只管一次,第二次写入就又失败了。
  4. 状态行变成「已授权(永久有效),重启 DSH 后继续可用」就完成了。以后重启 DSH、重启 Zotero 都不用再点。

DSH 设置里的 Zotero 写权限开关与授权按钮

上图为「设置 → Zotero文献库」顶部的写权限区块:开关已打开、状态显示「已授权(永久有效)」,主按钮已降级为「重新授权」——正常使用的情况下你不需要再点它。旁边的「重新读取」只是重新查一下本机保存的授权状态,写入报错时点它。

授权凭据存在本机 ~/.dsh/storages/dsh-plugin-zotero/local-api-key.json(权限 0600,不会出现在任何表单里)。要收回权限,在 Zotero 里清除本地 API 授权即可,插件下次写入被拒后会自动删掉本地副本、回到「未授权」。想临时全面止损,把「允许写入 Zotero」关掉就彻底回到只读。

写入是直接改你本机的 Zotero 库,插件不另存副本。删除类操作在面板里要点两次(「删除」→「确认删除」)才真删,而且不进 Zotero 回收站,撤销不了。

设置项说明(设置 → Zotero文献库)

入口只有一个:DSH 的「设置」→ 左侧「Zotero文献库」。

没有保存按钮:任何一项改完、停手约一秒就自动落盘,页面顶部会显示「正在自动保存…」,失败会显示红字提示(再改任意一项就会重试)。所有改动立即生效,不用重启 DSH。字段旁出现「已覆盖」表示这一项被你改过、不是默认值,点「恢复默认」即可还原。

Zotero 写权限

见第 5 步。一句话:开关管「有没有写入口」,授权按钮管「Zotero 认不认」,两件事都做完才写得进去。

API 设置

这块管右侧面板怎么连你本机的 Zotero。四项默认值适用于绝大多数人,不用动。

DSH 设置中的 API 设置四项

上图为「API 设置」区块,显示的是四项的默认值。

| 界面上的名字 | 默认值 | 说人话 | 什么时候才需要改 | |---|---|---|---| | Zotero 地址 | http://127.0.0.1:23119 | 本机 Zotero 的门牌号,面板所有数据都从这里取 | 你在 Zotero 里改过本地 API 端口 | | 请求超时(毫秒) | 5000 | 等 Zotero 回话最多等 5 秒,超了就报错 | 库特别大、经常提示超时,可以调到 10000 | | 全文上限(字节) | 204800 | 一篇附件的纯文本最多给这么多(约 200 KB,中文约 6~7 万字),超出部分截掉 | 想让 AI 一次读到更长的全文,可以调大(更费 token) | | 默认条目数 | 50 | 面板列表一次先拉 50 条,往下点「加载更多」再续 | 想一屏看到更多条目 |

对应配置字段名(写配置文件时才用得到):zoteroBaseUrl、requestTimeoutMs、fulltextMaxBytes、defaultLimit。

MCP 设置

这块管 AI 那边怎么连 Zotero 的桥接小插件。

| 界面上的名字 | 默认值 | 说人话 | 什么时候才需要改 | |---|---|---|---| | 集成 MCP 地址 | http://127.0.0.1:23120/mcp | 第 2 步装的那个小插件的接头地址 | 换了别的 MCP 插件,或它的端口不是 23120 | | MCP 探活超时(毫秒) | 800 | 每次判断「AI 工具能不能用」时,最多等 0.8 秒 | 机器很慢、状态栏老是误报「模型工具不可用」 |

对应配置字段名:mcpUrl、mcpProbeTimeoutMs。

MCP 工具(AI 能力逐项开关)

再往下是「MCP 工具」清单:现场列出桥接小插件提供的全部工具(本机实测 25 个),每行右边一个开关,顶部写着「共 N 个工具,已禁用 M 个」。

  • 关掉某一项,AI 就再也用不了那个能力(等于从 AI 的工具表里摘掉),比如你不想让 AI 删分类,就把 delete_collection 关掉。
  • 「重新读取」重新拉一次清单;显示「读取工具列表失败」通常是 Zotero 没开或小插件没装。
  • 清单里名字带 write_ / create_ / update_ / delete_ / add_ / remove_ 的是会改库的工具,其余是只读的。

DSH 设置中的 MCP 设置与 MCP 工具开关清单

上图为「MCP 设置」区块与下方的「MCP 工具」清单:共 25 个工具、已禁用 0 个,每行右侧的开关单独控制 AI 能不能使用该工具。

划词翻译

最后一块管「阅读页划选文字 → 译文浮层」。两项都是下拉,改完同样自动保存、立即生效。

| 界面上的名字 | 默认值 | 说人话 | 什么时候才需要改 | |---|---|---|---| | 默认翻译引擎 | Bing 免费翻译(快) | 免密钥、一般 1 秒内出结果,日常阅读够用 | 学术长句想要更顺的译文,换 DeepSeek 模型精翻(占额度)(走当前账号的 Flash 模型,1~3 秒、占额度);模型通道取不到时自动回落 Bing | | 目标语言 | 自动(中→英 / 英→中) | 按选区语种判向:中文原文译英文,英文及其它语种译中文简体 | 想固定译入某一门语言(简体 / 繁体中文、英、日、韩、法、德、俄) |

  • 译文浮层标题栏另有一枚引擎下拉:换一次就用新引擎立刻重译当前选区,是本次会话的临时覆盖,不写回这里;浮层上的徽标显示本次实际用到的引擎(选了精翻却显示 Bing,说明已自动回落)。
  • 单次翻译上限 4000 字,超限直接提示缩小选区,不静默截断;同一段文本重复翻译会命中进程内缓存。
  • 隐私:选中的文字会发给所选服务(Bing 即微软的翻译接口,DeepSeek 走你的账号模型)。涉密材料不要用划词翻译。
  • 对应配置字段名:translateProvider、translateTarget。

常见问题

| 你看到的 | 大概率原因 | 怎么办 | |---|---|---| | 面板显示「Zotero 未连接」 | Zotero 没开,或第 3 步的通信开关没勾 | 打开 Zotero,勾上「允许此计算机上的其他应用程序与 Zotero 通信」,回面板点刷新 | | 状态栏「模型工具不可用」,或工具清单读取失败 | 第 2 步的小插件没装 / 端口不是 23120 | 装 Zotero MCP Plugin;端口不同就改「集成 MCP 地址」,再点「重新读取」 | | 「设置」里没有「Zotero文献库」这一页 | 插件没装成功或没重启 | 回「插件市场」确认已安装,然后重启 DSH | | 划高亮 / 写笔记失败,提示未授权 | 第 5 步只开了开关、没点授权按钮 | 点「授权 Zotero 写权限」,弹窗里选「始终允许」 | | 每写一次就弹一次授权框 | 上次选的是「允许」,拿到的是一次性凭据 | 重新点授权,这次选「始终允许」 | | 授权按钮灰着点不动 | 上面的开关还没打开,或改动还没自动保存 | 先打开「允许写入 Zotero」,等「正在自动保存…」消失 | | 让 AI 新建分类,报「写操作已禁用」 | Zotero 里那个 MCP 小插件没开写操作 | 到 Zotero 的 MCP 插件设置里勾选「允许写操作」,重试即可,不用重启 DSH | | 提示「Zotero 里这条已经变了」 | 你(或 AI)在 Zotero 里同时改了同一条 | 刷新后重试;插件宁可报错也不覆盖你的新改动 | | 草稿里的引用胶囊发送失败,说找不到来源 | 插件被禁用或卸载了,胶囊没人展开 | 重新启用插件,或把胶囊删掉再发 | | 改了设置好像没生效 | 自动保存失败(顶部有红字) | 按红字提示再改一次任意字段触发重试;仍失败就看是不是被更高优先级配置覆盖 | | 译文浮层提示「翻译服务还没启动:请重启一次 DSH」 | 升级后宿主半(lib/)还是旧进程,路由表里没有翻译端点 | 完全退出并重开 DSH(刷新页面没用);重启前面板其余功能不受影响 | | 设置里选了 DeepSeek,浮层徽标却显示 Bing | 模型通道不可用或调用失败,已自动回落 | 属正常降级;检查「设置 → 模型」里有没有可用通道,或直接在浮层标题栏换引擎重试 | | 译文浮层提示「选区过长」 | 单次翻译上限 4000 字(与摘录同口径) | 缩小选区分段翻;整篇交给模型可改用条目引用 | | 截图发送被拒,提示「当前模型不支持图片」 | 当前模型没有读图能力(如 deepseek-v4-pro) | 换成支持图片的模型(如 deepseek-flash)后重发 | | 截图提示「会话正忙,图片未挂上」 | 草稿区正在发送 / 上传,暂时不接受新附件 | 等上一次发送结束再截一次 | | 网页快照的「截图加入对话」一直灰着 | 正文还没渲染完、桥接脚本没加载,或组件版本过旧 | 等正文出来;提示补构建产物就重新 pnpm build:client 后刷新页面;只有提示「组件版本过旧」才需要重启 DSH | | PDF 页面全白只剩彩色标注块,或网页快照没有高亮 | client/ 里的运行期资产(PDF 字体 / 快照桥接脚本)丢了 | 重新执行 pnpm build:client 后刷新页面即可,不用重启 DSH |

特性

  • 右侧栏面板「Zotero 文献库」:与 Zotero 本体同构——顶部状态栏(Zotero / 模型工具探活 + 刷新),左侧分类树与标签面板,右侧是当前范围的条目列表;条目独立成列。分类树与条目列表之间的分隔条可拖动,宽度按本机记住;选中的分类与展开状态也按本机记住,刷新页面或重开面板后回到上次的位置并重拉该目录的条目。
  • 分类筛选:分类树顶部可按名称筛选目录(同 Zotero 左栏:只筛目录名,命中项与祖先保留、自动展开,不影响右侧条目搜索)。
  • 条目列表:每行显示文献类型图标与作者 / 年份;读过的文献类型图标整体去饱和、淡化,标题同步略淡,悬停补上类型名与最后阅读时间。单击选中、Ctrl / Cmd 点选多选,双击在右侧栏顶层开独立详情页,右键单行可直接插引用;头部搜索框针对当前范围(分类 / 全库 / 标签筛选后)按标题与摘要过滤,列表可分页「加载更多」,选中多条时右上角一次「引用 N」。
  • 标签面板:树下方独立面板,可拖高 / 折叠;标签按 Zotero 的换行胶囊排布并跟随当前目录:选中分类时只列该分类自身条目里出现过的标签(不含子目录,自动标签弱化显示),选中文库根时列出全库标签;可按名称筛选、多选,并切换「全部(AND)/ 任一(OR)」。筛选作用于当前选择的范围,列表头部会显示已选标签胶囊与「清除筛选」;切换目录会自动清除已选标签,避免旧筛选作用到新范围。已选标签可从摘要行合并成一枚「标签组」胶囊引用。
  • 条目详情独立成页:双击条目在右侧栏顶层新开一个标签页,同一条目再次双击只回到已有页;详情页可同时开多个,切换标签页时各自的展开状态与滚动位置都保留(正文常驻挂载)。
  • 文档优先版面:详情页整页显示文献本体——PDF 走 PDF.js 渲染(顶部工具栏缩放、页码、当前页在 Zotero 中打开),网页快照与独立笔记按原样呈现,没有可用附件时回退到 API 全文文本;工具条中间恒显示当前文献标题(切到快照附件也不会变成 Snapshot)。左侧固定的 30px 工具栏不遮挡正文。选中正文即浮出划词工具条(复制 / 翻译 / 加入对话 / 新建标注),点正文里的高亮则弹出标注卡片(类型、原文、评论,以及「引用」与「在 Zotero 中打开」)。
  • 左上角信息面板:点左上角 i 按钮弹出浮层,把文献信息 / 摘要 / 标注 / 笔记 / 附件 / 参考文献分块竖排,每块可单独折叠;点浮层外或按 Esc 关闭,点标注定位时自动关闭把焦点还给文档。
  • 统一文档目录:i 左边的列表按钮是唯一一份大纲,PDF 书签、网页快照的 h1–h6 标题、笔记与 Markdown 里的标题都收在这里,标题下方一行小字说明当前来源;按层级缩进,点一条即跳转(PDF 跳页、其余滚到锚点),浮层不会关闭,可以连着点几条反复导航,没有大纲时按钮置灰。Zotero 本地 API 与集成 MCP 都没有目录数据,这份大纲由插件自己解析(上限 8 层 / 800 条)。
  • 笔记可读:独立笔记(文库里的全局笔记)打开后正文直接占据文档区,跟普通条目一样阅读;子笔记在信息面板的「笔记」块里折叠呈现,正文保留 Zotero 的引用块、标注高亮、表格与外链图片。Host 侧已清洗脚本与事件属性,避免注入。「加入对话」把该条笔记作为一枚胶囊写进会话草稿,发送时展开成完整纯文本;打开的条目本身就是独立笔记时,左上角那枚「加入对话」直接插整篇正文(列表单行与批量插入同样按笔记正文分派),不会给模型一个只剩标题的空壳。
  • 标注可读:PDF 上的高亮与划线原位叠加在页面上,点页内标注弹出卡片,可当场「引用」或跳回 Zotero 对应页;「标注」块按类型 / 颜色筛选,点条目可跨附件定位、滚动并闪烁,「引用」把该条标注作为胶囊写进会话草稿。
  • 划词翻译:PDF、网页快照、纯文本与笔记正文里划选文字,浮条上「复制」与「加入对话」之间多点一下「翻译」,选区旁弹出可拖动、可缩放的译文浮层——左右双栏「原文 / 译文」对照,中间一条实色竖分割线,右栏标出实际译入语言。默认自动判向(中文原文→英文,其余→中文简体),目标语言也可在设置里固定;引擎两档:Bing 免密钥(默认)或走当前账号的 DeepSeek 精翻(占额度,模型不可用时自动回落 Bing)。设置页定默认引擎,浮层标题栏的下拉是本次会话的临时覆盖,换一次立刻重译。单次上限 4000 字,浮层里的「加入对话」插一枚 翻译: 胶囊,提交时展开成「原文 + 译文」。
  • 多种插入方式:单条目、列表多选批量、单标签、多标签(合并成一枚「标签组」胶囊,AND/OR 在插入那一刻定格)、整目录、全文划词摘录、单条标注、单条笔记、划词翻译与正文截图全部以「引用胶囊」写进草稿——胶囊只显示短标签,发送那一刻才展开成完整引用文本,模型拿到的内容与以前一致;发出去之后,会话历史里仍是一枚胶囊,悬停即可预览完整引用,点击胶囊还能打开完整面板。所有方式都只写进会话草稿(不自动发送、不抢焦点),文本携带 itemKey / collectionKey / 标签名供模型接续操作。标签类引用始终按全库范围展开,不受你当时选中哪个分类影响;摘录 / 翻译 / 截图这几类胶囊把 itemKey、标题与内容一起自包含地定格在编码里,重开 DSH 后仍可展开,发送时不依赖 Zotero 在线(摘录单段上限 4000 字,自包含胶囊按编码后 8000 字节夹取)。独立笔记(itemType = note)无论从列表、批量还是阅读页插入,都按条目类型自动改走笔记正文引用——笔记没有作者 / 年份 / 刊物,走单条目引用只会给模型一个标题壳。
  • 正文截图加入对话:详情左上角「加入对话」右边那枚「截图加入对话」文字按钮,点一下正文定格压暗,拖框圈出区域,只有「取消 / 加入对话」两枚按钮(Esc 等同取消,小于 12×12 的误点不算数)。范围固定是正文显示区,不含工具条与浮层;PDF 直接取 pdf.js 页面位图(可跨页),纯文本、独立笔记与网页快照按当前可见区重绘。插入后是一张图片附件 + 一枚 截图: 胶囊的同一条消息:图片底部烙一条以「Zotero 截图」开头的水印(《标题》 · P3-4 · 章节),即使图片被单独转发也不丢出处;提交给模型的文本含文献身份(作者 · 年份 · 刊物 · DOI,网页类条目退化为「类型 · 站点域名」)、起止页码(仅 PDF,其余整行省略)、最近章节与框选区域的文字摘要,并注明「以图片为准,文本只用于定位」。网页快照由快照内的桥接脚本回传整页交给面板重绘,中文、表格、内联图片都能还原,滚到哪儿截哪儿;正文未渲染完或桥接脚本没就绪时按钮置灰并给出原因。输出 PNG(单张 50 MB、单会话最多 20 张),当前模型需支持读图(deepseek-flash 可以,deepseek-v4-pro 发送时会被拒)。
  • 胶囊依赖本插件展开:草稿里留着引用胶囊时禁用或卸载本插件,发送会失败并提示找不到引用来源,把胶囊删掉即可继续正常发送。
  • 分类只读:不提供任何新建 / 改名 / 删除分类的按钮——整理分类是模型的活,人在面板里只管浏览与引用。
  • 标注与笔记可写(默认关):在「设置 → Zotero文献库」打开「Zotero 写权限」并授权后,阅读页划选即写高亮 / 下划线(Zotero 色板七色 + 评论一次点明),点页内高亮弹出的标注卡片可当场「添加评论 / 改评论」,「标注」块还支持改色、改页码、加标签、高亮↔划线、删除,「笔记」块支持新建 / 编辑 / 删除。所有写入都直接进 Zotero 本地库,插件不存副本;所有笔记都能编辑(编辑框里是 Zotero 存的那份原始 HTML),含 Zotero 引文或标注锚点的笔记只多一句橙色提醒:改文字没事,别动 data-citation / data-annotation 属性。删除是硬删,不进 Zotero 回收站,面板里要点两次才会真删。开关关着时上述入口一个都不出现。
  • 模型侧工具可逐个开关:插件自持连接集成 MCP,把工具以 mcp__zotero__* 注册进 dsh,可在「设置 → Zotero文献库 → MCP 工具」里逐项启用 / 禁用。

以下面向开发者与想折腾配置的人,普通使用可以不看。

架构

从使用者视角看,插件分两半,职责不重叠、互不依赖:

| 半边 | 能力 | 通道 | |---|---|---| | 人侧面板 | 在 DSH 右侧栏浏览 Zotero 文库(分类树 / 标签面板 / 条目列表 / 搜索 / 条目详情 / 笔记 / 标注 / PDF 阅读),把条目(含多选批量)、摘录、标注、笔记、标签或整目录引用写进会话草稿;开启写权限后还能就地新建 / 修改 / 删除高亮、划线与笔记 | 插件在宿主 web server 自注册的 /dsh-zotero/api/* 路由(写 action 另需自定义写头) | | 模型侧 | 检索、精读、按需操作文库;条目 / 分类 / 标签 / 标识符的写走集成 MCP,标注与笔记的写走插件自带的 zotero_* 工具 | 插件自持连接本机 Zotero 集成 MCP,工具以 mcp__zotero__* 注册给模型 |

MCP 没起,面板照常可用;Zotero 没开,模型工具自然也不可用。

代码分布:

| 半边 | 代码位置 | 通道 | |---|---|---| | Host | src/index.ts、src/host/、src/zotero/ | 把 Zotero 本地 API 包装成 HTTP 端点(读 + 受开关约束的写),挂在 DSH 宿主 web server 上 | | Client | src/client/ | 在右侧栏注册 tab、面板正文,并在「设置」对话框注册独立一页;数据与选择状态放在模块级单例 |

两条数据流:

人侧    浏览器面板 ──同源 fetch──▶ /dsh-zotero/api/*(Host 路由)──HTTP──▶ Zotero 本地 API(127.0.0.1:23119)
模型侧  启动 / 设置页打开 ──sync──▶ 集成 MCP(127.0.0.1:23120)──注册──▶ dsh 工具表(mcp__zotero__*)
  • Host 路由为 GET /dsh-zotero/api/<action>,action 有 health / tree / items / tags / item / collection-bib / mcp-tools。items 支持 tag(重复出现为 AND,A || B 为 OR)与 q 组合过滤。
  • Host 侧带信任栅栏:仅接受 GET,拒绝 sec-fetch-site: cross-site,且 Host 必须是回环地址(防 DNS rebinding)。
  • 响应统一信封 {ok:true,data} / {ok:false,error:{code,message}},错误码见 src/zotero/types.ts。
  • 条目详情里的笔记由 Host 侧从 itemType: "note" 子条目提取并清洗 HTML(剥离脚本、事件属性与冗余 data-*,图片限宽),Client 只负责折叠展示。
  • 面板正文会被每个会话各挂一份,因此分类树 / 条目列表 / 标签选中 / 搜索词等状态放在 src/client/paneStore.ts 的模块级单例里,各会话看到的是同一块面板;右侧栏的展开状态与 tab 则按会话持久。条目详情的取数状态在各自 tab 组件内,互不干扰。
  • 无会话时面板仍可通过右侧栏的 guide 入口(「Zotero 文献库」)打开。

目录结构

src/                      # 插件源码(主包,ESM / NodeNext / strict)
├── index.ts              # Host 半入口:Config schema、HTTP 路由、MCP 桥接与写工具注册
├── host/
│   ├── router.ts         # HTTP 路由 /dsh-zotero/api/<action>,含回环 + 写头栅栏
│   ├── mcp-bridge.ts     # 自持集成 MCP 连接 + 按开关过滤注册模型工具
│   ├── write-tools.ts    # 模型侧标注 / 笔记写工具(writeEnabled 关时不注册)
│   └── static.ts         # PDF.js  worker 等静态资源
├── zotero/
│   ├── client.ts         # Zotero 本地 API 读取 + 笔记提取清洗 + 集成 MCP JSON-RPC
│   ├── write.ts          # 本地 API 写通道:授权复用、版本前置条件
│   ├── key-store.ts      # 写权限凭证落盘(0600)+ 从 Zotero 密钥库导入「始终允许」
│   ├── annotation-writes.ts / notes.ts   # 标注与笔记的增改删语义校验
│   ├── palette.ts        # 从真实库里枚举出的 Zotero 标注色板
│   ├── config.ts         # 端点 / 超时 / 截断阈值 + 运行时设置读取器
│   └── types.ts          # Host ↔ Client 数据契约
└── client/               # Client 半(浏览器)
    ├── index.ts          # 注册右侧栏 tab(面板 + 条目详情)、面板正文与「设置」独立页
    ├── ZoteroCard.tsx    # 设置页正文(写权限 / API 设置 / MCP 设置 / 工具开关,防抖自动保存)
    ├── ZoteroPane.tsx    # 面板容器:状态栏 + 分类树 / 标签面板 + 条目列表
    ├── CollectionTree.tsx / TagPanel.tsx / ItemList.tsx
    ├── SearchField.tsx   # 目录筛选 / 条目搜索 / 标签筛选共用的紧凑搜索框
    ├── itemType.tsx / readState.tsx       # 文献类型图标与已读标记
    ├── ZoteroItemPane.tsx  # 条目详情 tab 的正文与标题
    ├── ItemDetail.tsx    # 文档优先详情:选附件 / 跨附件定位 / 打开 Zotero
    ├── InfoPanel.tsx     # 左上角悬浮信息面板(可分块折叠)
    ├── OutlinePanel.tsx  # 左上角目录浮层(PDF 书签,点条目跳页)
    ├── viewer/           # 渲染器注册表 + PDF.js 渲染 / 文本回退 / 标注叠加与几何换算
    ├── viewer/shot/      # 截图加入对话:状态机 / 定格遮罩 / 裁切水印 / PDF、DOM、iframe 三种采集适配器
    ├── AnnotationList.tsx / NoteList.tsx    # 标注与笔记列表
    ├── Toast.tsx         # 插入结果等轻提示
    ├── reference.ts / cite.ts  # 引用胶囊的 ref 编码与提交时的文本展开
    ├── useInsertion.ts / inline.ts        # 往会话草稿插入引用胶囊
    ├── styles.ts         # 强调色等共用样式常量
    ├── paneStore.ts      # 跨会话共享的面板状态
    ├── compose.ts        # 插入文本模板
    ├── api.ts            # 调 Host 端点
    └── locales.ts        # zh / en 文案

client/client.js          # tsdown 产物(勿手改)
lib/                      # tsc 产物(勿手改)
cordis.patch.yml          # bundle patch 层:把本插件插入 profile 层栈
docs/                     # 使用说明、Zotero API / MCP 参考、发布与 node 学习笔记
tstest/                   # 独立测试沙盒(commonjs + tsx,与主包隔离)
plugin_helloword/         # 官方插件示例(学习用,勿放正式代码)
.trae/documents/          # 设计与实施方案(本地,未纳入版本控制)

主包与子项目分别有各自的 package.json;测试沙盒 tstest/ 环境独立,其依赖不得引入主包。

环境要求

  • Node + pnpm(主包与 tstest/ 统一用 pnpm,勿与 npm / yarn 混用)。
  • TypeScript ^5.9:[email protected] 的 peer 依赖不支持 TypeScript 7.x。
  • Zotero 桌面版已运行,且已开启本地 API(见第 3 步)。
  • 模型侧必需:Zotero 已安装集成 MCP 插件(插件市场中的 Zotero MCP Plugin / zotero-integrated-mcp),监听 23120——若用其他 MCP 插件或端口不同,需在设置页改「集成 MCP 地址」(mcpUrl);并在 MCP 插件设置中开启「允许写操作」。只装插件不开写操作时,模型侧读类工具照常,但让模型新建 / 修改分类会直接报错(插件返回「写操作已禁用」)。详见模型侧 MCP 与权限边界。
  • dsh CLI 可用。

构建

pnpm install
pnpm build            # tsc:src/ -> lib/(Host 半边)
pnpm build:client     # tsdown:src/client/ -> client/client.js(Client 半边)
pnpm typecheck:client # tsc --noEmit 校验客户端源码

本地测试启动

本地路径 link 的完整操作见 方案一:本地路径安装,核心三步:

dsh plugin --profile demo add ./
dsh --profile demo --dump-config   # 应能看到 dsh-plugin-zotero 一行
dsh --profile demo                 # 启动
  • 访问地址:启动后终端会打印 URL(web server 配置 printUrl: true),浏览器打开 http://127.0.0.1:3080。该地址来自 profile 组合配置里的 web server(host 默认 127.0.0.1、port 默认 3080),不是固定端口之外另开的服务。
  • 命令来源:dsh 是桌面 App 自带的 CLI(如 /usr/local/bin/dsh);仓库里也装了同一 CLI 的 devDependency,等价写法是 pnpm dsh --profile demo,两者读同一个 ~/.dsh/profiles/demo。
  • 启动前:Host 半边与 Client 半边加载的都是构建产物(lib/、client/client.js),改完 src/ 要先按上一节构建,再重启 dsh(见「日常迭代」)。

日常迭代

| 改了什么 | 要做什么 | |---|---| | src/(Host 半边) | pnpm build → 重启 dsh | | src/client/(Client 半边) | pnpm build:client → 重启 dsh → 浏览器重新打开页面 | | cordis.patch.yml | 重启 dsh |

客户端 bundle 没有热更新:改完必须重启 dsh 并重新加载页面。

配置层与权限实现

界面操作见安装与设置与设置项说明,这里只记实现。

设置怎么落盘

  • 入口是「设置」对话框的 settings.section 席位(section id zotero,order: 30,排在框架自带各页之后),仅当 Host 服务本插件的 settings 命名空间时才注册。命名空间 id dsh-plugin-zotero 必须与 cordis.patch.yml 的 insert 行 id 保持同步。
  • 表单没有保存按钮:最后一次改动后防抖 600ms 落盘;离开页面时合法草稿立刻冲盘、非法草稿直接丢弃;写盘失败不自动重试(否则每 600ms 打一次后端),等用户下一次编辑。
  • 落盘目标是 profile 的 patch 层 ~/.dsh/profiles/<profile>/cordis.patch.yml。所有字段走 Schemastery .volatile(),只提交新值并唤醒引用,无需重启即时生效。
  • 表单里露出的六个字段与界面标签的对照见设置项说明。另有两个不以文本框形式露出的字段:writeEnabled(布尔,写权限总开关)、disabledMcpTools(字符串数组,被停用的 MCP 工具原始名,由「MCP 工具」区的开关维护,模型侧据此过滤注册)。
  • 「已覆盖」表示该值来自 patch 层而非默认值,「恢复默认」清掉覆盖;若被更高优先级的 patch 层覆盖,保存会报「被覆盖」错误。「设置 → 内置插件」是只读清单,不提供编辑入口。
  • 实现:Host 半在 src/index.ts 导出 Config schema、注入读取器(src/zotero/config.ts 的 setSettingsReader)并驱动 src/host/mcp-bridge.ts;Client 半在 src/client/ZoteroCard.tsx 渲染表单,由 src/client/index.ts 注册席位。一次写入落地后重取工具清单与写权限状态。

模型侧 MCP 与权限边界

模型侧工具由插件自己桥接:src/host/mcp-bridge.ts 直连本机 Zotero 集成 MCP(本机实测暴露 25 个工具),按配置里的 disabledMcpTools 过滤后以 mcp__zotero__* 注册给模型。cordis.patch.yml 不再插入 @deepseek-ai/dsh-mcp-client —— 它不支持按工具开关,且同 serverName 会与自注册工具重名冲突。

⚠️ 前提是 Zotero 里已装好集成 MCP 插件(或改用其他 MCP 插件并在设置页填对 mcpUrl),并且开启了「允许写操作」。插件未安装或服务未起时,模型侧工具全部不可用;插件装了但没开写操作时,读类工具正常,create_collection 等写工具会被插件拒绝(返回「写操作已禁用」),表现为让模型帮忙新建分类直接报错——此时到 MCP 插件设置里打开写操作并重试即可,无需重启 dsh。

⚠️ 模型的写能力有两处来源,都要单独关才收得住:集成 MCP 的 25 个工具里有 10 个写工具(write_item / write_note / write_tag / write_metadata / add_by_identifier / create_collection / update_collection / delete_collection / add_items_to_collection / remove_items_from_collection),可在设置页的「MCP 工具」里逐个关掉;标注与笔记的写是插件自有的 zotero_update_annotation / zotero_delete_annotation / zotero_create_note / zotero_update_note / zotero_delete_note 五个工具,它们只在「Zotero 写权限」开关打开时才注册,关掉即从模型的工具表里消失。面板侧的分类操作始终只读。

写操作为什么优先走 MCP:这些工具在 Zotero 进程内直接改库,不经过本地 API,因此不会触发 Zotero 的「本地 API 授权」弹窗。反过来,若让模型用 shell/curl 直接打 127.0.0.1:23119 的写接口,就必须先用 POST /api/local/authorize 换 key —— 该端点每次调用都会弹一次授权框,用户点「允许」拿到的 key 还是一次性的(首个写请求即被 Zotero 删除),这就是「每写一次就要点一次允许」的根源。为此插件在 mcp-bridge.ts 里给所有写工具的描述统一注入了「首选写通道」引导语,并点明标注 / 笔记这两类 MCP 做不到、只能走插件自带的 zotero_* 工具;「导入本地文件并挂到某条目下」用 write_item 的 action: "import" + filePath + parentItemKey,一条工具调用即可。

写权限与授权

点击路径见第 5 步。机制上分两道闸:writeEnabled 决定面板写入口与模型侧 zotero_* 工具是否注册,本地 API key 决定 Zotero 认不认这次写入,两者缺一不可。

  • 授权走 POST /api/local/authorize,Zotero 弹框会挂住这条请求直到用户点按钮,因此等待期间按钮禁用(再点只是多弹一个框,还可能撞上 Zotero 每分钟 5 次的授权限流)。
  • 选「始终允许」拿到的长期 key 存到 ~/.dsh/storages/dsh-plugin-zotero/local-api-key.json(0600,只在 Host 进程内读写,不进配置存储、不在表单里回显),之后重启 dsh / 重启 Zotero 都直接复用。选「允许」拿到的是一次性 key,首个写请求即被 Zotero 删除。
  • 升级到带本功能的新版本时,会自动从 Zotero 自己的密钥库(profile 下的 localAPIKeys.json)导入此前点过的「始终允许」,不需要再点一次。
  • 撤销在 Zotero 侧做即可:下一次写入收到 401,插件随即删掉本地副本并回到「未授权」。拿到长期授权后主按钮降级为「重新授权」,正常路径下不需要再点。

写请求一律带并发前置条件(条目版本),撞上并发改动返回「Zotero 里这条已经变了」而不是覆盖;删除类操作在面板里必须点两次(「删除」→「确认删除」)才会真删,且是硬删、不进回收站。含 Zotero 引文 / 标注锚点的笔记不能编辑,只能删除。出问题时的止血手段仍是那个开关:关掉即彻底回到严格只读。

相关文档

License

MIT