Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ Add an entry here when the project meaningfully changes for users, for example:

## Unreleased

### Added

- Added a built-in, read-only Zotero Local API integration with exact DOI, arXiv, title, and item-key matching, safe local PDF attachment discovery, `auto` / `off` / `required` resolution policies, and environment diagnostics.

### Changed

- Converted the repository to a dual-stack Claude Code and Codex plugin layout with the canonical skill under `skills/deeppapernote/`.
Expand Down
31 changes: 24 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -268,14 +268,30 @@ Domain routing is controlled by the editable taxonomy in `skills/deeppapernote/r
### Optional: Zotero for local-library-first workflows

DeepPaperNote can work without Zotero.
But if you want the agent to search your local Zotero library first, you should expose a Zotero integration that your agent runtime can actually use.
If you already keep papers in Zotero, DeepPaperNote now has a built-in, read-only integration with the desktop [Zotero Local API](https://www.zotero.org/support/dev/web_api/v3/local_api). It queries only the loopback API at `127.0.0.1:23119`, requires no API key or third-party Python package, and never reads the Zotero SQLite database directly.

This is most worth setting up if you already use Zotero as your main paper-management or reading workflow.

Recommended ways to think about it:
To enable it:

1. Keep the Zotero desktop app running.
2. In Zotero, enable **Settings → Advanced → Allow other applications on this computer to communicate with Zotero**.

DeepPaperNote probes the Local API automatically during paper resolution. Its `--zotero-mode` policy has three options:

| Mode | Behavior |
| --- | --- |
| `auto` (default) | Prefer a unique local item; retain web fallback for title, DOI, and arXiv queries when Zotero is unavailable or has no match |
| `off` | Make no Zotero Local API request and preserve the previous resolution path |
| `required` | Stop unless Zotero uniquely resolves the reference; a missing local PDF does not invalidate confirmed Zotero metadata |

An ambiguous local match always fails closed instead of choosing an arbitrary item. An explicit Zotero key also fails closed when it cannot be verified locally because it has no safe web fallback. Explicit local PDFs and trusted JSON artifacts bypass the lookup in every mode.

Compatible agent-runtime or MCP integrations remain optional alternatives:

| 🧩 Option | 🎯 Best for | 📝 Notes |
| --- | --- | --- |
| Built-in Local API | Normal local-library-first use | Recommended path; read-only, offline-capable, no API key, and no extra integration layer |
| [kujenga/zotero-mcp](https://github.com/kujenga/zotero-mcp) | Lightweight read access | Closer to a minimal Zotero MCP server for search, metadata, and text access, but it usually still needs some adaptation for your agent runtime |
| [54yyyu/zotero-mcp](https://github.com/54yyyu/zotero-mcp) | Richer research workflow features | More feature-rich, but stable use usually still requires some integration work on your side |

Expand All @@ -290,9 +306,10 @@ Why it matters:

Important note:

- DeepPaperNote does **not** require one specific Zotero integration
- for DeepPaperNote, the key capability is that the agent can search Zotero items, inspect metadata, and ideally read local PDF attachments
- the two routes above are **not** always plug-and-play, so stable use may still require some adaptation on your side
- the built-in client sends only read-only `GET` requests and does not expose or forward Zotero's unauthenticated loopback port
- the built-in client currently targets the logged-in user's personal library; group-library select links are rejected instead of silently querying the wrong library
- no local PDF is required for a successful Zotero identity match; DeepPaperNote can keep the confirmed metadata and use its normal PDF acquisition fallback
- third-party runtime integrations are **not** always plug-and-play and are not required by the built-in workflow

### Optional: Semantic Scholar API key

Expand Down Expand Up @@ -394,7 +411,7 @@ For release-level updates, see [CHANGELOG.md](./CHANGELOG.md).
| v0.3.0-alpha | ✅ Released | Major quality upgrade: dedicated innovation section, explicit mechanism flow, stronger workflow discipline, final readability review, math syntax gate, and the new `Original Abstract Translation` front-matter block |
| v0.2.0-alpha | ✅ Released | Replication-oriented note-writing upgrade: explicit `note_plan`, equation-aware output, stricter final self-review, bilingual abstract handling, and stronger formatting checks |
| v0.1.0-alpha | ✅ Released | First public alpha: evidence-bundle workflow, Zotero-first helpers, placeholder-first figure handling, workspace fallback, OCR fallback, tests, and CI |
| Unreleased | 🕒 No new release-level changes yet | There are currently no additional public release notes beyond v2.0.0 |
| Unreleased | 🛠️ In development | Built-in read-only Zotero Local API resolution, safe attachment reuse, explicit lookup policies, and environment diagnostics |

## ⚙️ Workflow

Expand Down Expand Up @@ -495,7 +512,7 @@ DeepPaperNote/
| Python 3.10+ | Required | Runs the helper scripts |
| PyMuPDF | Required | Core PDF dependency; install it with `python3 -m pip install PyMuPDF` |
| Local Obsidian vault | Recommended | Writes directly into a long-term note system; otherwise uses the current workspace's fallback output folder |
| Zotero integration | Optional | Helpful for local-library-first paper workflows |
| Zotero Local API / compatible integration | Optional | Reuses local metadata and PDF attachments before web resolution |
| OCR tools | Optional | Improves handling of scanned PDFs |

## 🧭 Design Principles
Expand Down
31 changes: 24 additions & 7 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -263,16 +263,32 @@ setx DEEPPAPERNOTE_PAPERS_DIR "Research/Papers"
### 可选:用于本地文献库优先工作流的 Zotero

DeepPaperNote 不依赖 Zotero 才能工作。
但如果你本来就用 Zotero 做文献管理,配置一个你的 agent 真的能用的 Zotero 集成会很值
如果你本来就在 Zotero 里管理论文,DeepPaperNote 现在可以直接使用桌面端的只读 [Zotero Local API](https://www.zotero.org/support/dev/web_api/v3/local_api)。它只访问本机回环地址 `127.0.0.1:23119`,不需要 API key 或额外 Python 包,也不会直接读取 Zotero 的 SQLite 数据库

它最适合这样的人:
- 你本来就用 Zotero 做文献管理
- 你平时主要在 Zotero 里读论文、整理附件和元数据

可以这样理解不同路线:
启用方法:

1. 保持 Zotero 桌面应用运行。
2. 在 Zotero 中启用 **设置 → 高级 → 允许此计算机上的其他应用程序与 Zotero 通信**。

DeepPaperNote 会在论文解析时自动探测 Local API。其 `--zotero-mode` 策略有三个选项:

| 模式 | 行为 |
| --- | --- |
| `auto`(默认) | 优先采用唯一的本地条目;标题、DOI 和 arXiv 查询在 Zotero 不可用或未命中时保留联网回退 |
| `off` | 不请求 Zotero Local API,完整保留以前的解析路径 |
| `required` | 只有 Zotero 唯一解析出论文时才继续;没有本地 PDF 不会否定已经确认的 Zotero 元数据 |

如果本地出现多个同样可信的候选,解析会明确失败,而不是随意选一个。明确给出的 Zotero key 也必须在本地验证;它没有安全的联网回退。用户明确提供的本地 PDF 和可信 JSON artifact 在所有模式下都会直接使用。

agent runtime 或 MCP 提供的兼容集成仍可作为可选替代路线:

| 🧩 方案 | 🎯 更适合什么场景 | 📝 说明 |
| --- | --- | --- |
| 内置 Local API | 常规的本地文献库优先工作流 | 推荐路线;只读、可离线工作、不需要 API key,也不需要额外集成层 |
| [kujenga/zotero-mcp](https://github.com/kujenga/zotero-mcp) | 轻量的只读访问 | 更接近一个最小化 Zotero MCP 服务,适合搜索条目、读元数据、读文本,但通常仍需要你自己做一点适配 |
| [54yyyu/zotero-mcp](https://github.com/54yyyu/zotero-mcp) | 更完整的研究工作流能力 | 功能更丰富,但稳定接进你的 agent 环境时通常也需要额外改造 |

Expand All @@ -287,9 +303,10 @@ DeepPaperNote 不依赖 Zotero 才能工作。

⚠️需要特别说明的是:

- DeepPaperNote **不强依赖某一个固定的 Zotero 集成仓库**
- 对 DeepPaperNote 来说,需要的关键能力是:让 agent 能搜索 Zotero 条目、查看元数据、最好还能读取本地 PDF 附件
- 上面提到的两条路线目前都**不一定是即插即用方案**,如果你想稳定使用,通常还需要自己做一层适配或改造
- 内置客户端只发送只读 `GET` 请求,不会暴露或转发 Zotero 无认证的本机回环端口
- 内置客户端目前只查询已登录用户的个人文献库;遇到 group library 的选择链接会明确拒绝,不会静默查询错误的库
- Zotero 身份命中不要求一定存在本地 PDF;DeepPaperNote 可以保留确认过的元数据,再走正常的 PDF 获取回退
- 第三方 runtime 集成**不一定即插即用**,内置工作流也不依赖它们

### 可选:Semantic Scholar API Key

Expand Down Expand Up @@ -385,7 +402,7 @@ python3 -c "import pytesseract; print(pytesseract.get_tesseract_version())"
| v0.3.0-alpha | ✅ 已发布 | 一次较大的质量升级:新增固定创新点章节、显式机制流程、更强的整条 workflow 约束、最终可读性质检、公式语法检查,以及新的 `原文摘要翻译` 前置区块 |
| v0.2.0-alpha | ✅ 已发布 | 复现级技术笔记写作升级:显式 `note_plan`、公式感知输出、更强的最终自检、摘要中英双写,以及更严格的格式校验 |
| v0.1.0-alpha | ✅ 已发布 | 第一个公开 alpha 版:综合证据包流程、Zotero 优先辅助能力、占位优先图表处理、工作区回退输出、OCR 回退、测试与 CI |
| 未发布 | 🕒 暂无新的 release 级变化 | 当前还没有下一版 release 的公开更新内容,最新版本为 v2.0.0 |
| 未发布 | 🛠️ 开发中 | 内置只读 Zotero Local API 解析、安全复用本地附件、显式查询策略和环境诊断 |

## ⚙️ 工作流

Expand Down Expand Up @@ -485,7 +502,7 @@ DeepPaperNote/
| Python 3.10+ | 必需 | 运行辅助脚本 |
| PyMuPDF | 必需 | 核心 PDF 依赖,可用 `python3 -m pip install PyMuPDF` 安装 |
| 本地 Obsidian 库 | 推荐 | 配好后可直接写入长期笔记体系;未配置时使用当前工作区下的回退输出目录 |
| Zotero 集成 | 可选 | 对本地论文库工作流很有帮助 |
| Zotero Local API / 兼容集成 | 可选 | 联网解析前优先复用本地元数据和 PDF 附件 |
| OCR 工具 | 可选 | 对扫描版 PDF 更友好 |

## 🧭 设计原则
Expand Down
9 changes: 5 additions & 4 deletions skills/deeppapernote/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,14 +116,15 @@ Prefer the strongest available source in this order:
4. arXiv or open-access PDF sources
5. Semantic Scholar or OpenAlex for metadata backfill

Before resolving the paper, actively check Zotero integration: attempt to call the Zotero MCP tool (for example, search for the paper title or list libraries). If the tool responds without error, Zotero is available and the local-library-first rule below applies. If the call fails or the tool is not present, record "Zotero not available" and proceed without it. Do not skip this check — the check itself determines whether local-library-first applies.
Before web resolution, use the bundled `scripts/resolve_paper.py` Zotero Local API path to check the desktop library. Its default `--zotero-mode auto` prefers a unique local match and falls back to the existing providers when Zotero is unavailable or has no match. An explicit Zotero key has no safe web fallback and must be verified locally. Use `off` to make no Local API request, or `required` when the reference must resolve through Zotero. A trusted JSON artifact or explicit local PDF remains authoritative and bypasses this lookup. A compatible session-scoped Zotero/MCP integration may still provide a trusted input artifact when available, but it is not required for the built-in path.

Local-library-first rule (applies only when the Zotero check above succeeds):
- search the local Zotero library first using the paper title, DOI, or arXiv id
Local-library-first rule:
- search the local Zotero library first using the paper title, DOI, arXiv id, or exact Zotero item key
- If Zotero finds the paper, treat that result as the canonical identity resolution step.
- If the attachment path is not exposed by the integration, use `scripts/locate_zotero_attachment.py` with the attachment key and filename to find the local PDF under the user's Zotero storage.
- Prefer the safe local attachment path returned by the built-in Local API. If another compatible integration exposes only an attachment key and filename, use `scripts/locate_zotero_attachment.py` to find the PDF under the user's Zotero storage.
- If a local attachment path is available, pass it forward as the preferred PDF source.
- If no local attachment is found, still use the library-resolved metadata to avoid title ambiguity, then fall back to network PDF acquisition only for the file itself.
- If multiple local items are equally plausible, fail closed and request a DOI, arXiv id, or exact Zotero key rather than selecting one arbitrarily.
- Do not let a weaker title-only internet match override a confident local-library hit.

## Output Rules
Expand Down
4 changes: 3 additions & 1 deletion skills/deeppapernote/references/metadata-sources.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,10 @@ Use the strongest available source first, but backfill aggressively.

## Rules

- If the paper is already in the local Zotero library, treat Zotero as the identity anchor before doing title-based web resolution.
- Use the bundled read-only Zotero Local API client first when the desktop API is enabled; compatible runtime or MCP integrations may provide the same trusted local metadata as an optional alternative.
- If the paper is already in the local Zotero library, treat a unique Zotero match as the identity anchor before doing title-based web resolution.
- If Zotero resolves the paper but does not expose a local attachment path, still use the Zotero metadata to avoid title ambiguity.
- Distinguish an ambiguous local identity from an unavailable attachment: never guess between equally plausible items, but keep a uniquely resolved parent item's metadata even when no local PDF is accessible.
- Do not let a weaker internet title match override a confident Zotero hit.
- Do not invent missing metadata.
- If a Chinese title is assistant-generated, mark it as a translation.
Expand Down
Loading