🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

PDF 阅读工作台 dingyiliao/dsh-bundle-pdf

DeepSeek Harness
dingyiliao16 天前有提交已提供中文文档扫描:含敏感能力

PDF 阅读、批注、OCR、翻译与导航插件包,适用于 DeepSeek Harness

30.8/100
综合分
1
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/18 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add dingyiliao/dsh-bundle-pdf
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:仅索引
是什么
dsh 原生插件 · tool
装得上吗
本站尚未做安装检查
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 16 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 45 处,展示前 44 条)
  • 写入本地文件
    bench/browser.ts:21
    await mkdir(out, { recursive: true })
  • 写入本地文件
    bench/browser.ts:22
    const output = join(out, 'runs.jsonl'); await writeFile(output, '', { flag: 'wx' })
  • 写入本地文件
    bench/browser.ts:33
    await mkdir(join(ROOT, 'bench/.web-build'), { recursive: true })
  • 读取本地文件
    bench/browser.ts:38
    const bundle = await readFile(join(ROOT, 'bench/.web-build/app.js')), source = await sourceMetadata()
  • 读取本地文件
    bench/browser.ts:49
    const bytes = new Uint8Array(await readFile(join(corpusDirectory, document.file)))
  • 写入本地文件
    bench/browser.ts:78
    await writeFile(join(out, `${document.id}-${scenario.replace('.', '-')}-${iteration}-failure.json`), JSON.stringify({ state, errors }, null, 2))
  • 写入本地文件
    bench/browser.ts:95
    rows.push(row); await appendFile(output, `${JSON.stringify(row)}\n`)
  • 写入本地文件
    bench/browser.ts:102
    await writeFile(join(out, 'summary.md'), summaryMarkdown(rows))
  • 写入本地文件
    bench/compare.ts:10
    await writeFile(values.out!, compareMarkdown(before, after))
  • 写入本地文件
    bench/corpus.ts:12
    await mkdir(directory, { recursive: true })
  • 写入本地文件
    bench/corpus.ts:38
    await writeFile(join(directory, file), bytes)
  • 写入本地文件
    bench/corpus.ts:43
    await writeFile(join(directory, 'manifest.json'), `${JSON.stringify(manifest, null, 2)}\n`)
  • 读取本地文件
    bench/corpus.ts:48
    try { return corpusSchema.parse(JSON.parse(await readFile(join(directory, 'manifest.json'), 'utf8'))) }
  • 读取本地文件
    bench/indexing.ts:11
    for (const entry of await readdir(directory, {withFileTypes:true})) {
  • 读取本地文件
    bench/indexing.ts:14
    else if (entry.isFile()) { files++; bytes += (await stat(path)).size }
  • 删除本地文件递归
    bench/indexing.ts:65
    } finally {await service.dispose();await store.dispose();await rm(directory,{recursive:true,force:true})}
  • 写入本地文件
    bench/indexing.ts:69
    if (process.argv[2]) await writeFile(process.argv[2], JSON.stringify(result,null,2))
  • 执行外部命令固定命令
    bench/metadata.ts:11
    const files = execFileSync('git', ['ls-files', '--cached', '--others', '--exclude-standard', '-z'], { cwd: ROOT }).toString().split('\0').filter(Boole
  • 读取本地文件
    bench/metadata.ts:16
    try { bytes = await readFile(join(ROOT, path)) } catch (error) {
  • 执行外部命令固定命令
    bench/metadata.ts:25
    commit: execFileSync('git', ['rev-parse', 'HEAD'], { cwd: ROOT }).toString().trim(),
  • 执行外部命令固定命令
    bench/metadata.ts:26
    dirty: execFileSync('git', ['status', '--porcelain'], { cwd: ROOT }).length > 0,
  • 写入本地文件
    bench/persist.ts:9
    await writeFile(temporary, serialized, { flag: 'wx' })
  • 写入本地文件
    bench/persist.ts:10
    await rename(temporary, path)
  • 读取本地文件
    bench/persist.ts:11
    if (await readFile(path, 'utf8') !== serialized) throw new Error('Final benchmark file does not match measured rows')
  • 读取本地文件
    bench/report.ts:12
    const lines = (await readFile(path, 'utf8')).split('\n').filter(x => x.trim())
  • 读取本地文件
    bench/retrieval-integration.ts:32
    if (!existsSync(executable)) throw new Error('The native PDFium helper is required; run the native build first.')
  • 读取本地文件
    bench/retrieval-integration.ts:137
    for (const bucket of await readdir(cacheDirectory, { withFileTypes: true })) {
  • 读取本地文件
    bench/retrieval-integration.ts:139
    for (const record of await readdir(join(cacheDirectory, bucket.name), { withFileTypes: true })) {
  • 读取本地文件
    bench/retrieval-integration.ts:141
    records++; diskBytes += (await stat(join(cacheDirectory, bucket.name, record.name))).size
  • 写入本地文件
    bench/retrieval-integration.ts:223
    if (values.out) await writeFile(values.out, JSON.stringify(output, null, 2) + '\n')
  • 删除本地文件递归
    bench/retrieval-integration.ts:227
    finally { await rm(cacheDirectory, { recursive: true, force: true }) }
  • 写入本地文件
    bench/retrieval.ts:291
    if (values.out) await writeFile(values.out, serialized, { flag: 'wx' })
  • 写入本地文件
    bench/run.ts:21
    await mkdir(out, { recursive: true })
  • 写入本地文件
    bench/run.ts:24
    await writeFile(output, '', { flag: 'wx' })
  • 写入本地文件
    bench/run.ts:47
    rows.push(row); await appendFile(output, `${JSON.stringify(row)}\n`)
  • 写入本地文件
    bench/run.ts:53
    await writeFile(join(out, 'summary.md'), summaryMarkdown(rows))
  • 读取本地文件
    bench/worker.ts:19
    const bytes = new Uint8Array(await readFile(file))
  • 读取本地文件
    src/entrypoints/native-host.ts:31
    manifest = JSON.parse(await readFile(join(directory, 'manifest.json'), 'utf8')) as NativeManifest
  • 读取本地文件
    src/entrypoints/native-host.ts:37
    readFile(executable), readFile(library), stat(executable),
  • 读取本地文件
    src/entrypoints/native-host.ts:37
    readFile(executable), readFile(library), stat(executable),
  • 读取本地文件
    src/entrypoints/native-host.ts:53
    const metadata = JSON.parse(await readFile(packageJson, 'utf8')) as { name?: unknown; version?: unknown }
  • 读取本地文件
    src/entrypoints/native-host.ts:66
    && await stat(new URL('native/dependencies.json', packageRoot)).then(value => value.isFile(), () => false)) {
  • 读取本地文件
    src/entrypoints/native-host.ts:71
    const nativeMetadata = JSON.parse(await readFile(nativePackageJson, 'utf8')) as { name?: unknown; version?: unknown }
  • 发起网络请求
    src/entrypoints/reader-host.ts:73
    fetch(request: Request): Promise<Response>
扫描于 2026/11/4(0 天前) · 范围 全包扫描(包内未声明入口) · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

依赖的 DSH / Cordis 模块
@deepseek-ai/dsh-util-workspace-path@deepseek-ai/cordis@deepseek-ai/dsh-attachment@deepseek-ai/dsh-app-boot@deepseek-ai/dsh-client-ui-settings@deepseek-ai/dsh-client-ui-sidebar-documentpreview@deepseek-ai/dsh-loader-smoke@deepseek-ai/dsh-sandbox@deepseek-ai/dsh-storage-domain@deepseek-ai/dsh-subprocess@deepseek-ai/dsh-tools@deepseek-ai/schemastery
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

README

由 DeepSeek 最新模型翻译生成
DSH PDF 阅读器 背景 我经常用 PDF 阅读论文和资料,但常见阅读器总会缺少一些顺手的功能,例如连续跳转多次后逐级返回原来的阅读位置;具备模型解读、翻译等功能的产品又往往需要额外付费。于是我借助 DeepSeek Harness(DSH) 写了这个自用插件,把 PDF 阅读、标注和 DSH 已有的模型能力放在同一个工作区,按自己的需求继续迭代。 使用方法 1. 在 GitHub Actions 选择 main 分支上与要安装的源码提交 SHA 一致、且构建成功的 native 工作流。从该运行的 Artifacts 下载与你的系统和 CPU 匹配的 dsh-pdf-npm-package-<target>:linux-x64、linux-arm64、darwin-x64、darwin-arm64 或 win32-x64。先解压下载的 ZIP,取出其中的 .tgz。目前这些包不在 Releases 中。 2. 将 .tgz 安装到要使用的 DSH profile,安装后重启 DSH。
展开完整文档(README 剩余 1 节)
DSH PDF 阅读器

背景

我经常用 PDF 阅读论文和资料,但常见阅读器总会缺少一些顺手的功能,例如连续跳转多次后逐级返回原来的阅读位置;具备模型解读、翻译等功能的产品又往往需要额外付费。于是我借助 DeepSeek Harness(DSH) 写了这个自用插件,把 PDF 阅读、标注和 DSH 已有的模型能力放在同一个工作区,按自己的需求继续迭代。

使用方法

1. 在 GitHub Actions 选择 main 分支上与要安装的源码提交 SHA 一致、且构建成功的 native 工作流。从该运行的 Artifacts 下载与你的系统和 CPU 匹配的 dsh-pdf-npm-package-<target>:linux-x64、linux-arm64、darwin-x64、darwin-arm64 或 win32-x64。先解压下载的 ZIP,取出其中的 .tgz。目前这些包不在 Releases 中。
2. 将 .tgz 安装到要使用的 DSH profile,安装后重启 DSH。例如,已有 Web profile 可以运行:

dsh plugin --profile web add /absolute/path/to/package.tgz
dsh web

Desktop 用户需先启动一次应用以初始化 desktop profile,然后完全退出应用;通过 Desktop 菜单“管理 dsh 命令…”安装其自带的 CLI,再运行 dsh plugin --profile desktop add /absolute/path/to/package.tgz,最后重新打开应用。普通 npm 版 dsh 命令不能管理 Desktop profile。
3. 在 DSH 的文件栏打开有权访问的本地 PDF。阅读器提供页码与目录跳转、逐级返回、个人书签、文字搜索、标注和选区翻译。解释模式可收集带问题的文字选段或单页框选区域,并作为一轮提词发送到所属会话。模型还可以在后台打开 PDF 工作副本、读页、搜索、列书签及按需获取页图像或 OCR 文字,不会自动打开侧栏标签。pdf_render_page 默认仍只向当前视觉模型返回页图;显式指定 mode: configured-backend 才使用 profile 选择的图像理解后端,其中 OCR 和辅助视觉路线只返回标注来源与局限的派生文字,不向当前会话返回图片。

翻译、解释以及首版 OCR 默认使用当前会话模型与 DSH 已配置的凭据,本插件不提供免费模型。框选解释默认要求当前会话模型明确支持图像输入;也可显式改用 ocr-text(只提取文字)或 auxiliary-vision(由另一视觉模型描述图像)。辅助路线会额外请求所配置的模型,可能产生费用;当前会话只接收派生描述,不接收原始截图,描述可能遗漏或误读细节。阅读器可按需识别整页或截图区域;内置 SessionLLM OCR 后端也需要视觉模型,仅返回可复制的转写文字,不生成可精确选中或标注的 PDF 文字层。加密 PDF 暂不支持。其他边界见 SPEC.md;package.json 的 peerDependencies 列出声明兼容的 DSH 版本,当前 CI 使用 0.2.0-rc.2 依赖验证。

从源码开发时,在本仓库目录执行 npm ci && npm run native:build && npm run build,再用 dsh plugin --profile web add . 链接本地目录。直接通过 Git URL 安装源码不会得到原生构建产物。

架构

flowchart LR
C["DSH Web / Desktop ClientPDF 阅读、标注、解释模式"] -->|DSH Connection| H["pdf-reader Host文件、草稿、书签、保存、PDF 工具"]
C -->|认证的区域图像请求| I["image-understanding Host可替换的图像处理后端"]
I -->|当前视觉模型可用性| M["DSH 会话模型"]
I -->|图像描述请求| A["可配置的辅助视觉模型"]
I -->|OCR 文字路线| O
C -->|一轮图文或派生文字提词| M
N["pdf-native Host校验平台产物"] -->|pdfNative 服务| H
O["image-ocr HostOCR 服务与可替换后端"] -->|ocr 服务| H
H -->|stdio IPC| W["独立 PDFium worker渲染与文字提取"]

同一个 bundle 通过 cordis.patch.yml 装入四个 Host 插件。pdf-reader 使用 pdf-native,并可调用独立的 ocr 服务;image-understanding 为解释模式的框选图像及模型工具显式请求提供同一后端选择。默认 session-vision 路线检查当前会话模型后发送原图;ocr-text 只返回带来源与局限说明的识别文字;auxiliary-vision 把截图交给显式指定的第二个视觉模型,再将其描述作为派生文字送入当前会话。三条路线不自动互相降级。其他 Host 插件仍可注册自己的 OCR 或图像理解后端,对应的类型契约由 @local/dsh-pdf/ocr-host 和 @local/dsh-pdf/image-host 导出。图像理解后端通过 profile patch 中 pdf-image-understanding 的配置选择;目前没有设置卡片。Client 经 DSH 的认证连接访问 Host,而不是直接调用原生库。Host 负责会话范围内的文件访问、批注写回和 PDF 模型工具;原生 worker 负责 PDF 渲染与文字提取。每个平台的安装包都包含这套 JS 插件及对应平台的 helper 和 PDFium 动态库,安装时不需要 C++ 编译环境。

例如,仅对指定 profile 使用 OCR 文字路线时,在该 profile 的 cordis.patch.yml 中合并以下覆盖项(不要覆盖文件内已有的 patch):

- id: pdf-image-understanding
config:
backend: ocr-text
此配置只选择图像理解路线;OCR 引擎仍由 image-ocr 自己配置。

使用内置辅助视觉路线时,改为以下配置;provider 和 model 必须是 DSH 已配置且声明支持图像输入的精确标识,reasoningEffort、maxOutputTokens 可省略:

- id: pdf-image-understanding
config:
backend: auxiliary-vision
auxiliaryVision:
provider: your-provider
model: your-vision-model
reasoningEffort: low
maxOutputTokens: 4096

这一路线会把框选截图和对应问题发送给该辅助模型;它返回的描述可能遗漏细节或出错,当前会话不会看到原图。若还需要其他路线,Host 插件仍可向 imageUnderstanding 注册自定义后端并在 config.backend 中选择其 ID。

界面契约(含自定义 UI 组件的现状清单与收敛待办)见 SPEC.md;已完成与待测的性能口径见 PERFORMANCE.md。

许可证

本项目代码采用 MIT License。PDFium、pdf-lib、Tesseract.js 等第三方组件遵循各自的许可证;构建包内附有 dist/THIRD_PARTY_NOTICES.md 与 dist/native/ 下的许可文本。
预览分享卡片长什么样 ↓dingyiliao/dsh-bundle-pdf
分享 · DeepSeek Harness Hub
dingyiliao/dsh-bundle-pdf

PDF 阅读、批注、OCR、翻译与导航插件包,适用于 DeepSeek Harness

这是你的仓库?认领条目

回到顶部