dshbase

插件目录 / Developer / dsh-file-viewer

dsh-file-viewer

已验证 · 实测可装 liguobao

✓ 持续维护 2 位贡献者 基于 8 个官方 DSH 包

查看 GitHub ↗ ← 返回插件目录

3Stars
0Forks
0未关闭 issue
语言
2026-08-21最近推送
跨平台平台

功能简介

DeepSeek Harness 通用只读文件预览插件,支持图片、PDF、CSV、Markdown、JSON、YAML、源码及大文件。

我们的评价
可用 — 实测通过,早期项目

DeepSeek Harness 通用只读文件预览插件,支持图片、PDF、CSV、Markdown、JSON、YAML、源码及大文件。 实测能干净安装、正常启动。早期项目,但功能可用。

「已验证」表示我们的自动化 CI 在干净 profile 里实际执行了 dsh plugin add 并启动成功——仅此而已。功能描述与版本兼容性均为作者声明。这不是安全审计,也不代表对第三方代码的背书。

README

DSH File Viewer

English | 中文

Online: dsh.r2049.cn

A universal, read-only file preview layer for DeepSeek Harness:
open and inspect files right inside the web UI — no external application needed.

Preview ≠ Execute. The viewer is strictly read-only: previewing a file never
runs shell commands, scripts, macros, or HTML. SVG is rendered through <img>,
and Markdown is sanitized before display.

Supported file types

Type Renderer
PNG / JPG / GIF / WEBP / SVG / BMP Image (fit, zoom, pan, dimensions)
PDF PDF.js (page nav, page input, zoom, fit width/page)
CSV / TSV Data table (delimiter auto-detect, sticky header, row numbers, search, sort, column resize, windowed rows, chunked loading)
TXT / LOG / OUT / INI / CONF Text (line numbers, wrap, search, font size, chunk navigation)
JS / TS / Python / Go / Rust / Java / C/C++ / C# / Shell / HTML / CSS / SQL / … Code (highlight.js, read-only)
Markdown Preview (sanitized) + Source
JSON / JSONL Tree (expand/collapse, copy value/path) + Source
YAML Source + parsed Tree
anything else Fallback (metadata + Open externally / Reveal / Copy path / optional Open as text)

How it works

  • Host half (dist/index.js) registers the /fileviewer loopback RPC
    channel and exposes both a fileViewerContent provider registry and a
    fileViewerHost bounded service for trusted transport plugins. The viewer does
    not assume content lives in a local folder: other host plugins can register
    readers for locators such as artifact://run/report.json, object storage,
    generated output, or remote APIs. A boundary-checked ctx.fs provider is
    installed only when that service is available, preserving local-file
    compatibility without making it a hard dependency.
  • Client half (dist/client.js) provides the fileViewer service
    (ctx.get('fileViewer')openFile(path, { line, renderer })) and renders
    a right-docked viewer column (styled like the Harness details panel)
    through the shell.overlay slot. It opens from:
    • produced-file chips in the conversation (conversation.chat.turnTail,
      priority -1 — clicking an agent-generated file previews it in-app), or
    • the "浏览文件 / Browse files" entry added to each workspace row's
      "…" menu (see the compatibility patch below).
  • Workspace "…" menu patch (scripts/patch-workspace-menu.mjs): the
    workspace browser renders its row menu from a hardcoded list with no slot
    hook, so this script applies three guarded, idempotent edits to the
    installed @deepseek-ai/dsh-client-ui-workspace client bundle: a
    browseFiles menu item (zh/en labels), an onSelect branch calling
    window.__dsfvBrowseWorkspace(workspaceId), and the two dictionary keys.
    It aborts loudly on version drift and can be re-run safely after Harness
    updates (node scripts/patch-workspace-menu.mjs).
  • Large-file strategy: < 5 MB whole-file, 5–50 MB chunked streaming,
    > 50 MB head-only with explicit "Load more / Go to end" navigation. Range
    reads are capped (8 MiB per call) and text/CSV rows are windowed, so a
    500 MB log never lands in browser memory.
  • Theming: styles use --dsw-alias-* tokens and match Harness's details
    panel proportions, so light/dark follow the Harness theme automatically.

Public API

// client side, any web plugin:
const fileViewer = ctx.get('fileViewer')
fileViewer.openFile('/workspace/output/report.csv')
fileViewer.openFile('artifact://run-42/report.csv')
fileViewer.openFile('/workspace/src/main.ts', { line: 125 })
fileViewer.openFile('/workspace/data.bin', { renderer: 'text' }) // force a renderer

Provide content from another host plugin

Register a provider once, then open its locators from any client plugin. The
provider owns locator matching, authorization, metadata, and range reads; the
viewer owns preview selection, bounded RPC transfer, and rendering.

import type { FileViewerContentRegistry } from 'dsh-file-viewer'
const report = new TextEncoder().encode('{"status":"ok"}')

ctx.inject(['fileViewerContent'], runtime => {
  const content = runtime.get<FileViewerContentRegistry>('fileViewerContent')!
  runtime.effect(() => content.register({
    id: 'run-artifacts',
    supports: locator => locator.startsWith('artifact://'),
    async stat(locator) {
      if (locator !== 'artifact://run-42/report.json') return undefined
      return {
        name: 'report.json',
        mime: 'application/json',
        size: report.byteLength,
      }
    },
    async read(locator, { offset, length }) {
      if (locator !== 'artifact://run-42/report.json') throw new Error('Not found')
      return report.slice(offset, offset + length)
    },
  }), 'register run artifact viewer')
})

Providers may additionally implement list() for directory-like locators and
openExternal() for source-specific hand-off. register() returns an
unregister function, making provider lifetime follow the supplying plugin.

Trusted transport plugins can inject fileViewerHost and forward an explicit
allowlist of its endpoints. This is how dsh-remote previews files on a Remote
Host: access checks remain owned by the selected File Viewer content provider,
while the transport applies its own authentication, size limits, and method
allowlist. openExternal is intentionally not part of that remote surface.

Browser-only plugins can register the same reader directly on the client
service—no host RPC or local path is required:

import type { FileViewerClientService } from 'dsh-file-viewer'
const markdown = new TextEncoder().encode('# Live preview')

ctx.inject(['fileViewer'], runtime => {
  const viewer = runtime.get<FileViewerClientService>('fileViewer')!
  runtime.effect(() => viewer.registerContentProvider({
    id: 'live-preview',
    supports: locator => locator === 'memory://preview.md',
    async stat() { return { name: 'preview.md', size: markdown.byteLength } },
    async read(_locator, { offset, length }) {
      return markdown.slice(offset, offset + length)
    },
  }), 'register live preview')
  viewer.openFile('memory://preview.md')
})

Configuration

# cordis.patch.yml / settings
- id: dsh-file-viewer
  name: dsh-file-viewer
  config:
    enabled: true
    extraRoots:
      - /srv/data          # optional extra directories the viewer may read

Development

npm install            # (use a reachable registry if npmjs TLS is flaky)
npm run build          # declarations + esbuild → dist/types + dist/index.js + dist/client.js
npm run check          # tsc (strict) over src and tests
npm test               # vitest: mime, renderer, paths, large-file, csv, json, file-service

Install into a DSH profile

# from the repo root (the profile resolves relative specs from your cwd)
dsh plugin --profile web add /path/to/dsh-file-viewer
# compatibility patch: add "浏览文件" to each workspace's "…" menu
node scripts/patch-workspace-menu.mjs
# then restart the web service (preflight on 43124 → 43123), see
# scripts/restart-dsh-web.sh for the safe pattern used in this repo.

Client-only changes hot-reload via dsh-client-hmr; node-half changes need a
web restart. Re-run scripts/patch-workspace-menu.mjs after any Harness
update that reinstalls @deepseek-ai/dsh-client-ui-workspace.

Security notes

  • Path validation is enforced host-side on realpath'd targets against allowed
    roots (fs.contains) by the optional local-files provider. Custom providers
    are responsible for authorization within their own locator namespace.
  • Markdown is rendered with html: false and sanitized with DOMPurify
    (scripts, iframes, event handlers and javascript: URLs removed).
  • SVG is never injected as HTML — it is displayed through <img>.
  • Binary detection: NUL scan + magic bytes; "Open as text" is always an
    explicit user action.
  • Per-renderer error boundaries: a broken PDF/JSON can never crash the
    Harness UI.

License

MIT

安装

🧩 让 Agent 自动装(推荐)

装一次目录插件,之后本站所有插件都能让 DeepSeek Harness 自动找、自动装:

dsh plugin add dshbase-catalog

然后对 agent 说「帮我装 dsh-file-viewer」,它会在目录里找到并自动安装。文档:dshbase-catalog · 已验证场景包

该插件是 GitHub 源码(未发 npm)——直接从仓库装:

Web profile:

dsh plugin --profile web add github:liguobao/dsh-file-viewer

Headless(CLI)profile:

dsh plugin --profile headless add github:liguobao/dsh-file-viewer

实测报告

验证通过:从 GitHub 源码完成 L1 安装 + L2 加载 + L3 运行(dsh 0.1.0-rc.6)。

安全:尚未扫描——我们的每日静态扫描将很快覆盖它。

分享徽章

Developer 里更多

浏览全部 7789 个插件 →