dsh-zotero-skill 0.5.4 → 0.5.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-zotero-skill",
3
- "version": "0.5.4",
3
+ "version": "0.5.5",
4
4
  "description": "Zotero skill for DeepSeek Harness: find papers on OpenAlex or Crossref, import Chinese CNKI export files, track research fronts, screen core papers, manage and classify the library, batch-read, map the landscape, and surface research gaps. Also exports BibTeX and cites into LaTeX/Markdown.",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
package/zotero/SKILL.md CHANGED
@@ -33,6 +33,7 @@ description: 面向不同研究领域的 Zotero 技能:原文定位问答、
33
33
  用户只问具体段落、公式、已有批注或要求证据对比表时,按需读 [references/focused-reading.md](references/focused-reading.md),只检索所需片段、复用已读成果,展示本次任务必要的选项。不要为一个局部问题默认重新生成全文译文、询问全部导出选项。
34
34
  使用宿主当前模型生成,一份分析与译文复用于 Markdown、Zotero 笔记和 PDF;默认省用量,用户可选继承当前模型配置的受限并行。
35
35
  通过 `read prepare/accept/status/export/publish` 建立可恢复、可定位到原文的阅读任务;多篇综述用 `review prepare/render/search`,材料不足时明确不足并自动搜索带理由的补充候选。
36
+ `read status` 只列前 20 个未翻译块与前 40 条复核提示(并给 `untranslated_total` / `translation_audit_total`),完整复核列表用 `read audit`;长论文可把分块任务交给子任务写 `<job>/results/t-*.json`,`read status` 会实时计入,最后一次 `read accept` 汇总。
36
37
  运行入口为技能资源目录内 `scripts/reader-runner.mjs`(Node 20+),包安装也提供 `lib/reader-runner.js`;首次按需准备本地 Python/PDF/OCR 组件,现有 Python CLI 也保留。
37
38
  当前选中论文需安装包内配套 Zotero 扩展;分类、标签、检索和明确 item key 继续使用已有 API。
38
39
  不把元数据模板当成精读结论,不把局部语料统计当成已证明的研究空白,不承诺未经实测的完成时间。
@@ -25,7 +25,22 @@
25
25
 
26
26
  **同模型并行(用户选择)**:先检查宿主实际可用的内部子任务能力。仅使用继承当前模型配置的本地子任务,不指定不同模型或外部后端;最大并发由 max_workers 控制,不嵌套创建子任务。每个任务读取独立块、生成独立 JSON,交给主任务顺序 accept。由主任务统一术语、消除重复、检查矛盾,再导出。若宿主缺少此能力,说明后按省用量模式继续,不声称已经并行。并行可能增加重复上下文和用量,不能承诺固定加速倍数。
27
27
 
28
- 按 priority 先交付有依据的速读卡、首批笔记或译文。第一份内容必须来自实际原文,可以明确是阶段性成果。其后继续完成全部用户选择的输出。`read status <job>` 返回未翻译块与未覆盖分析项;恢复任务时只处理缺少内容。
28
+ 按 priority 先交付有依据的速读卡、首批笔记或译文。第一份内容必须来自实际原文,可以明确是阶段性成果。其后继续完成全部用户选择的输出。`read status <job>` 返回未翻译块与未覆盖分析项:未翻译块默认只列前 20 个并给 `untranslated_total`,复核提示默认只列前 40 条并给 `translation_audit_total`,完整复核列表用 `read audit`。恢复任务时只处理缺少内容。
29
+
30
+ ## 运行环境与网络
31
+
32
+ 首次运行会在 `~/.zotero-skill/reader-runtime/` 准备私有 Python 与 PDF/OCR 组件。以下环境变量用于适配内网、镜像和已有环境,都是可选的:
33
+
34
+ | 变量 | 作用 | 默认 |
35
+ |---|---|---|
36
+ | `ZOTERO_SKILL_CONFIG_DIR` | 状态目录(任务、证据、授权凭据) | `~/.zotero-skill` |
37
+ | `DSH_READER_PYPI_INDEX` | pip 索引,逗号或空格分隔,按顺序尝试 | `https://pypi.org/simple` 然后 `https://mirrors.aliyun.com/pypi/simple` |
38
+ | `DSH_READER_PYTHON` | 指定系统解释器(需 3.10+);uv 下载失败时用它建私有环境 | 自动探测 `py -3` / `python` / `python3` |
39
+ | `DSH_READER_FONT` | 指定 CJK 字体文件,避免下载 Noto Sans SC | 下载并按需嵌入;失败时回退系统字体(微软雅黑/黑体/宋体等) |
40
+ | `ZOTERO_LOCAL_BASE_URL` | Zotero 本地 API 地址 | `http://127.0.0.1:23119` |
41
+ | `ZOTERO_LOCAL_API_KEY` | 写操作凭据;不设则读 `~/.zotero-skill/local-key.json` | 由 `authorize` 生成 |
42
+
43
+ 镜像或代理受限时先设 `DSH_READER_PYPI_INDEX` 与 `DSH_READER_PYTHON`;字体下载失败不影响文字输出,只影响嵌入字形。
29
44
 
30
45
  ## 模型结果 JSON 与引用
31
46
 
@@ -33,6 +48,8 @@
33
48
 
34
49
  `read status <job>` 与 `read accept` 统计的是「已接受快照 + 之后写入的分块结果」:子任务写出的 `t-*.json` 即使还没单独提交,也会被算进译文与结论数量,不会被上一次快照盖住,因此可以分批交付、边写边看。已接受的内容始终优先,后写入的分块不会覆盖它;两个尚未接受的分块互相矛盾时仍会报 `Conflicting translations`,需要先改掉其中一个再接受。
35
50
 
51
+ 长论文的并行做法:主任务读 `<job>/tasks/chunk-*.json`,把每个分块交给一个子任务;子任务只写自己那份,格式同上(可以只有 `translations`),保存成 `<job>/results/t-<任意序号>.json`,文件名互不相同即可。写完后 `read status` 立刻能看到进度,最后一次 `read accept --input` 汇总成快照。这样不必等所有译文回齐才提交,也不会因为中途 accept 而丢掉后续分块。
52
+
36
53
  ```json
37
54
  {
38
55
  "source_hash": "prepare返回的精确SHA256",
@@ -18,6 +18,7 @@ CATEGORIES = {"overview": "研究问题与章节逻辑", "method": "方法与结
18
18
  KINDS = {"reported", "interpretation", "proposal"}
19
19
  KIND_LABELS = {"reported": "原文报告", "interpretation": "分析解释", "proposal": "待验证建议"}
20
20
  AUDIT_INLINE_LIMIT = 40
21
+ UNTRANSLATED_INLINE_LIMIT = 20
21
22
 
22
23
 
23
24
  def now():
@@ -386,7 +387,9 @@ def inspect(job_id):
386
387
  unreadable = [p["number"] for p in document["pages"] if not p["readable"]]
387
388
  issues = quality.audit(document, translations, manifest["profile"])
388
389
  return {"id": job_id, "revision": result_revision(directory), "translations": len(translations), "claims": len(claims),
389
- "untranslated_blocks": untranslated, "uncovered_categories": absent,
390
+ "untranslated_blocks": untranslated[:UNTRANSLATED_INLINE_LIMIT],
391
+ "untranslated_total": len(untranslated),
392
+ "uncovered_categories": absent,
390
393
  "unreadable_pages": unreadable, "ready": not (untranslated or absent or unreadable),
391
394
  "warnings": document["warnings"], "translation_audit": issues[:AUDIT_INLINE_LIMIT],
392
395
  "translation_audit_total": len(issues),