当用户明确要求转换、修改或批量转换图片格式时使用。支持常见本地或网络图片输入与常见目标格式输出。⚠️ 不适用:仅调整尺寸/裁剪、查看图片信息,或没有明确格式转换意图。
The English summary is being prepared. Showing the original description.
当用户明确要求"下载文献全文"或"获取论文PDF"时使用。通过 DOI 号下载学术论文全文 PDF,支持 arXiv、Sci-Hub、Unpaywall、期刊官网等多源策略。
⚠️ 不适用:用户只是想解析或处理已有的 PDF 文件(应使用 pdf skill)、只是想搜索论文信息而无需下载全文、没有提供 DOI/标题/BibTeX 任何标识符。
The English summary is being prepared. Showing the original description.
Run score Not tested
See how to installReview the instructions the agent will receive before you install.
当用户明确要求"下载文献全文"或"获取论文PDF"时使用。通过 DOI 号下载学术论文全文 PDF,支持 arXiv、Sci-Hub、Unpaywall、期刊官网等多源策略。⚠️ 不适用:用户只是想解析或处理已有的 PDF 文件(应使用 pdf skill)、只是想搜索论文信息而无需下载全文、没有提供 DOI/标题/BibTeX 任何标识符。
输入至少包含 DOI、标题或 BibTeX 之一,并指定输出目录/文件路径;可选输入包括来源开关、Unpaywall 邮箱、验证阈值和覆盖策略。输出路径必须存在或可创建且可写,触发边界以本 Skill 的 ## 目标 为准。
必需参数:
doi: DOI 号(如 10.1038/nature09492)output_path: 输出目录或完整 PDF 文件路径可选参数:
title: 论文标题(作为 DOI 的备选)bibtex: BibTeX 条目(包含 DOI 或标题信息)验证逻辑:
# 由 scripts/validate_input.py 处理
- DOI 格式规范化(移除多余空格、补全前缀)
- 输出路径检查(目录存在性、写入权限)
- 至少提供一种标识符(DOI/title/bibtex)
优先级顺序(按成功率和速度排序):
| 优先级 | 数据源 | 优势 | 局限 | 触发条件 |
|---|---|---|---|---|
| 1 | arXiv | 稳定可靠 | 仅限预印本论文 | 检测到 arXiv ID(如 10.48550/arXiv.*) |
| 2 | Sci-Hub | 覆盖较广、速度快 | 可能有 CAPTCHA | 非 arXiv 或 arXiv 失败 |
| 3 | Unpaywall | 合法开放获取(OA) | 取决于论文是否 OA | Sci-Hub 失败时兜底 |
| 4 | 期刊官网 | 合法渠道 | 常需订阅/登录 | 最后兜底 |
策略执行:
# 由 scripts/download_pdf.py 实现
1. 如 DOI 可解析出 arXiv ID → 优先 arXiv
2. 尝试 Sci-Hub(通过 scihub 库)
3. 尝试 Unpaywall(合法 OA 获取)
4. 尝试 DOI 落地页并猜测常见 PDF 路径(期刊官网兜底)
必需检查(由 scripts/verify_pdf.py 处理):
%PDF-)失败处理:
成功时:
✅ 成功下载论文全文
**来源**: Sci-Hub
**DOI**: 10.1038/nature09492
**文件**: /path/to/paper.pdf
**大小**: 2.3 MB
失败时:
❌ 无法下载论文全文
**尝试过的源**:
- Sci-Hub: CAPTCHA 验证失败
- arXiv: 非 arXiv 论文
- Unpaywall: 无开放获取版本
- 期刊官网: 未找到直接 PDF 链接
**建议**:
1. 手动访问 Sci-Hub 并完成 CAPTCHA 验证
2. 检查 DOI 是否正确
3. 尝试通过期刊官网获取
AI 需要动态处理的场景:
| 场景 | 处理方式 |
|---|---|
| CAPTCHA 检测 | 识别错误消息中的 "captcha" 关键词 → 切换数据源 |
| 网络超时 | 增加重试次数(最多 3 次)或切换源 |
| 404/未找到 | 直接切换下一个源,不重试 |
| 文件损坏 | 删除已下载文件,尝试下一个源 |
| arXiv 检测 | DOI 中包含 arXiv ID → 优先使用 arXiv 源 |
输入验证与规范化脚本:
import sys
import re
from pathlib import Path
def normalize_doi(doi: str) -> str:
"""规范化 DOI 格式"""
doi = doi.strip()
if not doi.startswith("10."):
doi = f"10.{doi}" # 尝试补全
return doi
def validate_output_path(path: str) -> Path:
"""验证输出路径"""
path = Path(path).expanduser().resolve()
if path.exists() and path.is_dir():
# 目录:自动生成文件名
return path / "paper.pdf"
if path.parent.exists():
# 完整路径:确保父目录可写
return path
raise ValueError(f"输出路径无效: {path}")
def main():
if len(sys.argv) < 3:
print("用法: python validate_input.py <doi> <output_path>", file=sys.stderr)
sys.exit(1)
doi = normalize_doi(sys.argv[1])
output_path = validate_output_path(sys.argv[2])
print(f"DOI:{doi}")
print(f"OUTPUT:{output_path}")
if __name__ == "__main__":
main()
核心下载逻辑(多源策略):
import sys
import requests
from pathlib import Path
from typing import Optional, Tuple
# 尝试导入 scihub 库(可选依赖)
try:
from scihub import SciHub
HAS_SCIHUB = True
except ImportError:
HAS_SCIHUB = False
class PDFDownloader:
"""多源 PDF 下载器"""
def __init__(self, doi: str, output_path: Path):
self.doi = doi
self.output_path = output_path
self.sources_tried = []
def download_from_scihub(self) -> Tuple[bool, str]:
"""从 Sci-Hub 下载"""
if not HAS_SCIHUB:
return False, "scihub 库未安装"
try:
sh = SciHub()
result = sh.download(self.doi, path=str(self.output_path))
if result and self.output_path.exists():
return True, "Sci-Hub"
return False, "下载失败"
except Exception as e:
error_msg = str(e).lower()
if "captcha" in error_msg:
return False, "CAPTCHA 验证失败"
return False, str(e)
def download_from_arxiv(self) -> Tuple[bool, str]:
"""从 arXiv 下载(检测 arXiv ID)"""
# 简化实现:arXiv 直接下载 URL
arxiv_id = self._extract_arxiv_id()
if not arxiv_id:
return False, "非 arXiv 论文"
url = f"https://arxiv.org/pdf/{arxiv_id}.pdf"
try:
response = requests.get(url, timeout=30)
if response.status_code == 200:
self.output_path.write_bytes(response.content)
return True, "arXiv"
return False, f"HTTP {response.status_code}"
except Exception as e:
return False, str(e)
def download_from_unpaywall(self) -> Tuple[bool, str]:
"""从 Unpaywall 下载(合法 OA)"""
# Unpaywall API 端点
# email 参数建议从 config.yaml 读取;可配置 emails 列表做负载均衡
url = f"https://api.unpaywall.org/v2/{self.doi}"
try:
response = requests.get(url, timeout=30)
if response.status_code == 200:
data = response.json()
if data.get("is_oa"):
pdf_url = data.get("best_oa_location", {}).get("url_for_pdf")
if pdf_url:
pdf_resp = requests.get(pdf_url, timeout=30)
if pdf_resp.status_code == 200:
self.output_path.write_bytes(pdf_resp.content)
return True, "Unpaywall"
return False, "无开放获取版本"
except Exception as e:
return False, str(e)
def _extract_arxiv_id(self) -> Optional[str]:
"""从 DOI 或上下文中提取 arXiv ID"""
# 简化实现:检测 DOI 中是否包含 arXiv 信息
# 实际应解析 BibTeX 或标题
return None
def download(self) -> Tuple[bool, str, str]:
"""执行多源下载策略"""
# 策略 1: Sci-Hub
self.sources_tried.append("Sci-Hub")
success, source = self.download_from_scihub()
if success:
return True, source, "成功"
# 策略 2: arXiv(如果是 arXiv 论文)
self.sources_tried.append("arXiv")
success, source = self.download_from_arxiv()
if success:
return True, source, "成功"
# 策略 3: Unpaywall
self.sources_tried.append("Unpaywall")
success, source = self.download_from_unpaywall()
if success:
return True, source, "成功"
# 所有源失败
return False, "", f"尝试过的源: {', '.join(self.sources_tried)}"
def main():
if len(sys.argv) != 3:
print("用法: python download_pdf.py <doi> <output_path>", file=sys.stderr)
sys.exit(1)
doi = sys.argv[1]
output_path = Path(sys.argv[2]).expanduser().resolve()
downloader = PDFDownloader(doi, output_path)
success, source, message = downloader.download()
if success:
print(f"SUCCESS:{source}")
print(f"FILE:{output_path}")
print(f"SIZE:{output_path.stat().st_size}")
else:
print(f"FAILURE:{message}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
PDF 验证脚本:
import sys
from pathlib import Path
def verify_pdf(path: Path) -> Tuple[bool, str]:
"""验证 PDF 文件完整性"""
if not path.exists():
return False, "文件不存在"
if path.stat().st_size == 0:
return False, "文件大小为 0"
# 检查 PDF 文件头
with open(path, "rb") as f:
header = f.read(5)
if header != b"%PDF-":
return False, "无效的 PDF 文件头"
# 尝试用 PyPDF2 解析
try:
import PyPDF2
with open(path, "rb") as f:
PyPDF2.PdfReader(f)
return True, "有效 PDF"
except ImportError:
# PyPDF2 未安装,跳过深度验证
return True, "未安装 PyPDF2,跳过深度验证"
except Exception as e:
return False, f"PDF 解析失败: {str(e)}"
def main():
if len(sys.argv) != 2:
print("用法: python verify_pdf.py <pdf_path>", file=sys.stderr)
sys.exit(1)
path = Path(sys.argv[1]).expanduser().resolve()
is_valid, message = verify_pdf(path)
if is_valid:
print(f"VALID:{message}")
sys.exit(0)
else:
print(f"INVALID:{message}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
# 下载策略配置
download:
# Sci-Hub 配置
scihub:
enabled: true
timeout: 30 # 秒
retries: 3
# arXiv 配置
arxiv:
enabled: true
timeout: 30
# Unpaywall 配置
unpaywall:
enabled: true
emails:
- "hwb2012@qq.com"
- "huangwb886@gmail.com"
email_strategy: "round_robin" # round_robin | hash_doi | random
state_file: ".bensz-api/task-{yyyymmdd-hhmm}-{简短描述}/download-fulltext-pdf/state/unpaywall_email_state.json"
email: "" # 兼容旧字段(可选)
# 验证配置
verification:
check_pdf_header: true
require_pypdf2: false # 是否强制要求 PyPDF2
max_file_size: 100_000_000 # 100 MB
# 输出配置
output:
default_filename: "paper.pdf"
overwrite: false # 是否覆盖已存在文件
必需依赖:
requests(网络请求)可选依赖(自动安装):
scihub(Sci-Hub 支持,首次使用时自动安装)PyPDF2(PDF 验证,推荐安装)当 AI 执行下载任务时,scripts/download_pdf.py 会:
📦 检测到缺失依赖: scihub)pip install)用户无需手动安装,skill 会"开箱即用"。
如果自动安装失败,用户可以手动安装:
pip install requests scihub PyPDF2
示例 1:使用 DOI 下载
/skill download-fulltext-pdf "10.1038/nature09492" ./downloads/
示例 2:使用标题下载
/skill download-fulltext-pdf --title "Deep Learning" ./downloads/
示例 3:批量下载(从 BibTeX 文件)
/skill download-fulltext-pdf --bibtex references.bib ./downloads/
成功时交付经 %PDF- 文件头和可选 PyPDF2 解析验证的 PDF,并报告来源、规范化 DOI、文件路径和大小;失败时列出尝试过的来源、具体原因和可操作建议。状态文件、日志和调试材料留在任务工作区。
10. 开头)| 错误类型 | 表现 | 处理方式 |
|---|---|---|
| CAPTCHA | Sci-Hub 返回验证码页面 | 切换到 Unpaywall 或期刊官网 |
| 未找到 | 404 或 "not found" | 切换下一个数据源 |
| 超时 | 请求超时 | 重试(最多 3 次) |
| 文件损坏 | PDF 头无效 | 删除并重新下载 |
本块由 docs/templates/skill-common-constraints.md 统一维护;每个 SKILL.md 的 ## 约束 必须逐字同步本块,不得在副本中改写公共规则。
./.bensz-api/task-{yyyymmdd-hhmm}-{简短描述}/ 根目录;共享材料放入 shared/,Skill 专属材料放入该 Skill 的 input/、output/、log/。config.yaml:skill_info.version;公开 API、协议、目录或配置变更同步文档与 CHANGELOG.md。bensz-collect-bugs 是一个 Agent Skill;仅将 Bensz Agent Skill 或 Bensz 基础设施本身的设计缺陷交给它。先脱敏写入 ~/.bensz-skills/bugs/,当前任务不中断,只有用户明确要求才公开上报,禁止直接修改用户已安装的 Skill 源码。No reviews yet. Tell others what you thought.
No login needed. Share how it worked for you, ask a question, or note where it did not run.
No comments yet. Be the first to write one.
当用户明确要求转换、修改或批量转换图片格式时使用。支持常见本地或网络图片输入与常见目标格式输出。⚠️ 不适用:仅调整尺寸/裁剪、查看图片信息,或没有明确格式转换意图。
The English summary is being prepared. Showing the original description.
根据用户描述生成高质量绘图 prompt,并按通用、roadmap、schematic 模式通过 BenszAPI 直接完成 gpt-image-2.5-flare、gpt-image-2.5-sunburst、gpt-image-2 或 Nano Banana/Gemini 出图、编辑和多轮迭代;这是自包含的图片生成工作流,选中后不得调用或依赖 imagegen,除非用户明确要求同时使用 imagegen。
The English summary is being prepared. Showing the original description.
当用户明确要求测试代码、代码审查或代码自检时使用。系统化发现并验证代码问题。⚠️ 不适用:用户只是想实现或优化功能、询问代码问题,或没有明确测试意图。
The English summary is being prepared. Showing the original description.
当用户明确要求“测试项目”、 “运行 auto-test-project”或“进行项目级测试”时使用。对完整项目执行多轮 A 轮批判性测试与 B 轮质量检查,发现、记录、修复并验证问题。⚠️ 不适用:用户只是想优化功能、询问项目问题,或没有明确测试意图。
The English summary is being prepared. Showing the original description.
当用户明确要求测试 Skill、运行 auto-test 或对 Skill 进行批判性测试时使用。系统化发现、记录并验证 Skill 问题。⚠️ 不适用:用户只是想开发或优化 Skill,或没有明确测试意图。
The English summary is being prepared. Showing the original description.
当用户明确要求使用 awesome-code、进行多代理协作或需要复杂任务规划时使用。它负责拆解任务、选择专业角色、设置门禁并审查结果;所有 Agent 的创建、隔离、串行或并行执行都必须交给 `parallel-vibe`。⚠️ 不适用:用户只需单一角色完成简单修改或咨询,或未表达多代理协作意图。
The English summary is being prepared. Showing the original description.