Skip to content

dsh-documents

Verified

dsh-documents · v1.2.1 · MIT · Web UI

Session-linked document library for DSH Desktop: in-app Markdown viewer, zoom, provenance and edit history.

Install

dsh plugin add dsh-documents

Confirm the layer applied with dsh --profile default --dump-config — see the install guide.

Source

Tags

Creators

Readme

文档库(Document Library)

DSH Desktop 插件:把会话生成、编辑或交付过的文档集中成一个列表,每个文档都能追溯到具体会话和事件位置。

你不再需要回忆「刚才那个报告是哪个会话写的、写到哪一步了」——打开侧边栏的「文档」,路径、来源会话、每次修改的事件坐标都在里面。

  • 包名:dsh-documents(npm)· 版本 1.2.1 · MIT
  • 要求:DSH Desktop >= 0.2.1-rc.3,Node.js >= 22.19.0

功能

  • 目录树浏览:左侧按 工作区 → 会话 → 文档 三级展开,一个工作区一个目录、一个会话一个目录,文件夹显示文档数。默认全部收起,展开状态会记住(刷新窗口也不变)。
  • 自动收录,不用手动添加:只读 DSH 会话日志,凡是会话里 write / edit 过的文件、或被 present 标记为交付物的文件,自动进入文档库。不扫描目录、不索引全盘。
  • 来源可追溯:每个文档带创建它的会话、编辑过它的其他会话,以及每次变动的事件坐标(轮次 / #seq / 时间)和内容片段。
  • 一键回到现场:点「打开会话」跳到对应会话,并把历史加载到那条事件。
  • 内置查看器:Markdown 阅读模式(标题、列表、表格、引用、任务列表、代码块、链接)与源码切换、纯文本等宽预览、图片与 PDF 内嵌显示、60%–200% 缩放。
  • 左侧目录导航:Markdown 阅读模式下只收一级、二级标题(开头的文档标题不重复出现),停在正文左边的留白里;当前小节清晰突出,离得越远的标题越小、越淡;鼠标悬停时当前位置的标题再放大,远处标题依旧更小更淡,点击跳到对应小节。滚动时目录自动跟随阅读位置并平滑居中。
  • 代码高亮:代码块按语言着色(JS/TS、Python、Bash、PowerShell、JSON、CSS、HTML、SQL、YAML、Go、Rust、Java、C/C++、diff),带语言标签和一键复制;语言不认识时原样显示,不做猜测。
  • 配色分级:每个工作区有固定色调(由名字推导,稳定不变),目录图标、名称、计数和缩进竖线共用这一色调;会话用同一色调的浅色,文档类型另有 Word/Excel/PPT/PDF/Markdown/文本 各自的色块。
  • 筛选与搜索:按类型筛选,按文件名 / 文件夹 / 工作区 / 会话标题搜索(有搜索词时自动展开命中目录),按最近活动、名称、大小排序。
  • 文件操作:用桌面应用打开、在文件夹中显示、复制路径、重命名、移入回收站。
  • 快:分块流式加载,先扫完的先显示;每 60 秒增量刷新,没有变化时完全不重绘。
  • 版本自检:npm 上有新版本时,面板顶部给出一条升级提示和可复制的升级命令(只提示,不自动安装)。

安装

方式一:界面安装(推荐)

DSH Desktop → 设置 → 插件 → 安装,输入:

dsh-documents

需要固定版本时写 [email protected]。

「插件」页有两个容易混淆的入口:安装是输入包名安装;发现是搜索第三方插件市场索引,不会列出 npm 上的包。

方式二:命令行安装(desktop 以外的 profile)

dsh plugin add dsh-documents --profile web

dsh plugin 只是把参数转发给 profile 目录里的 pnpm。desktop 这个 profile 由桌面应用独占,CLI 会直接拒绝:

error: profile "desktop" is managed exclusively by the Electron application

所以桌面版的安装和升级走方式一(界面)或方式三(本地构建)。

方式三:本地构建(自测刚发布、甚至还没发布的版本)

npm run install:local                            # 校验 → 打包到 dist/ → 装进 desktop profile
npm run install:local -- -Version 1.0.4-local.1  # 顺便换成独立的本地版本号
npm run install:local -- -Restore                # 切回 npm 上的版本

脚本在 profile 目录里直接 pnpm add <tarball>。tarball 是 pnpm 的 file: 依赖,不查 registry、不查发布时间,正好绕过 minimumReleaseAge。装到别的 profile 加 -Profile web。

装完按 Ctrl+R;index.js(宿主侧)的改动要完全退出 DSH 再启动才生效。

dist/ 里的 tarball 是 profile 依赖的来源,不要手动删。git clean -xdf 清掉之后重跑一次脚本即可。

方式四:直接从 GitHub 安装(desktop 以外的 profile)

仓库没有构建步骤,源码即产物:

dsh plugin add github:aerfaman/dsh-documents --profile web

安装之后

按 Ctrl+R 刷新窗口,侧边栏出现「文档」图标。

升级

桌面版不会自动更新第三方插件:插件页那个「可更新 / 更新」按钮只对官方按需目录里的包生效,普通 npm 包不会出现。升级要手动触发:

  • 桌面版:设置 → 插件 → 安装里再输入一次 dsh-documents;自己改过源码就用 npm run install:local。
  • 其他 profile:dsh plugin add dsh-documents@latest --profile <name>。
  • 刚发布就装、结果还是旧版本:这是 pnpm 的发布时间策略,见 FAQ「发布后立刻升级,装上的还是旧版本」。

半自动提示:打开文档库时,插件会向 npm registry 查一次当前版本(最多 6 小时一次,只取版本号、不上传任何内容)。有新版本就在顶部显示:

有新版本 1.2.1 · 升级后按 Ctrl+R 生效 dsh plugin add dsh-documents@latest [复制命令] [跳过此版本]

桌面版这条命令会被 CLI 拒绝,按上面「设置 → 插件 → 安装」那条走即可。点「跳过此版本」后,同一个版本不再提示;出现更新的版本会重新提示。离线或 registry 不可达时静默跳过,不影响使用。

卸载

dsh plugin remove dsh-documents --profile <name>   # desktop profile 在插件页里卸载

快速上手

  1. 在任意会话里让 Agent 写一份文件(例如让它在工作区里生成 report.md)。
  2. 打开侧边栏的「文档」——这份文件会出现在所属工作区 → 该会话的目录下。
  3. 点开它看内容;点工具条上的「详情」可以看到它是哪个会话、在哪条事件写下的。
  4. 需要回到当时那一刻,点「打开会话」。

界面说明

左侧:目录树

左侧始终保留目录树,右侧是查看器;点树里的另一份文档即可直接切换,不会丢失位置。

▾ dsh-documents            12        ← 工作区
  ▾ 文档库重构 · 3                      ← 会话
      report.md
      spec.docx
  ▸ 发布收尾 · 2
▸ 另一个工作区              4
  • 三级结构:工作区(目录)→ 会话(目录)→ 文档。层级由会话日志推导:文档归到创建它的会话下;被别的会话编辑过的,文档行右侧标「其他会话改过」,鼠标悬停显示是哪些会话。
  • 每个工作区一种颜色:色调由工作区名推导,同一工作区永远是同一个颜色,展开后的竖线、文件夹图标、名称和计数都用它;会话图标是同色的浅一档。选中的文档行用主题品牌色,和目录色区分开。
  • 默认全部收起:第一次打开只列出工作区,点文件夹逐级展开到会话、文档。
  • 展开状态按目录记在本地(localStorage),刷新窗口、切走再切回来都保持原样,不会被重新展开或收起;顶部有「全部展开 / 全部收起」。
  • 文件夹右侧数字是该目录下的文档数。
  • 默认按最近活动排序:工作区、会话都按各自最新文档排序,同层的文档按所选排序方式。
  • 顶部搜索框匹配文件名、文件夹路径、工作区名和会话标题;输入搜索词时自动展开命中的目录。
  • 类型 chips 按 Word / Excel / 幻灯片 / PDF / Markdown / 文本 过滤,并显示各类型数量。
  • 标题右侧的徽章显示当前文档数与会话数。
  • 首次打开时列表边扫边显示,底部提示「正在继续扫描会话…已显示 N 个」;扫描结束提示消失。

右侧:查看器

类型 显示方式
Markdown(.md .markdown .mdx) 阅读模式渲染,可切「源码」
纯文本(.txt .log .tex .json .yml .csv 等) 等宽源码预览
图片(.png .jpg .jpeg .webp .gif) 内嵌显示,支持大图
PDF 内嵌显示(支持 Range 分段读取)
Office 文档(.docx .xlsx .pptx 等) 不做内嵌渲染,用「打开」交给桌面应用
  • 阅读排版:正文按 65 字符左右的行宽收敛(最大 760px),标题按层级收紧字距,引用块、表格(隔行浅色、表头独立底色)、任务列表、图片圆角阴影分别处理。
  • 目录导航:阅读模式左侧有一条随位置呼吸的目录,只收 H1/H2(开头的文档标题除外)。平时按与当前小节的距离缩放和透明,当前位置最清晰;悬停时当前位置再放大、周围标题略微放大,远处标题依旧更小更淡;点击平滑跳转。目录自动避开正文(宽窗口显示标题、窄窗口收成刻度条),正文滚动时当前条自动居中。每份文档从自己的开头开始,切换文档不会继承上一篇的滚动位置。
  • 代码块:标题栏显示语言并带「复制」按钮;按语言做词法着色(关键字、字符串、数字、函数名、类型、注释、变量、HTML 标签、diff 的增删行),不认识的语言原样显示。
  • 缩放按钮 60% → 200%,每次 10%;点中间百分比回到 100%。
  • 大文件预览会截断并提示。
  • 文件已被删除时显示「文件已不存在」。

详情面板

「详情」默认收起,展开后:

  • 元信息卡:完整路径、所在工作区、类型、大小、修改时间。
  • 会话卡:创建它的会话,以及编辑过它的其他会话(色条和徽章区分「创建 / 编辑」)。每张卡默认收起,点卡片标题展开该会话的变动列表;收起时卡片副标题仍显示工作区、变动次数和最近一次时间,头部也保留「打开会话」。
  • 变动列表:每次写入 / 修改 / 交付一行,带事件坐标、行数变化和内容片段;每条都有「打开会话」。

窄屏时列表和详情变成可切换的抽屉。

操作

操作 说明
打开 用系统默认应用打开,走 DSH 的桌面打开接口
在文件夹中显示 在资源管理器 / Finder 中定位
复制路径 复制绝对路径
重命名 改名后即使会话日志里还是旧路径,文档也不会从列表消失
移入回收站 移到 %USERPROFILE%\.dsh\documents-trash\,不直接删除

支持的文件类型

类型 扩展名
Word doc docx docm rtf odt pages
Excel xls xlsx xlsm csv ods
幻灯片 ppt pptx pptm odp key
PDF pdf
Markdown md markdown mdx
文本 txt log tex

数据来源与收录规则

文档库不扫描目录,内容全部来自 DSH 会话日志:

  • write / edit / apply_patch 等写文件工具调用 → 记为一次「写入」或「修改」,记录行数变化与内容片段。
  • deliverables/presented(present 工具)→ 记为一次「交付」。
  • 只有能映射到上述事件、且当前仍存在于工作区内的文件才会出现在列表里。

同一个文件被多个会话碰过时,会合并成一份文档,下面挂多条会话记录。


性能

  • 渐进加载:列表接口按会话日志分块返回(NDJSON 流),先扫完的先上屏,其余在后台继续扫描。会话日志多的机器(几十个会话、几十 MB)不必等整体扫完。
  • 增量刷新:每 60 秒后台刷新一次(仅页面可见时),只回传新增 / 变化 / 删除的文档;没有变化时服务端只回一个「无变化」,界面不重绘、不闪、不跳滚动位置。
  • 面板复用:切走再切回文档页,直接用上次的列表做增量校验,不重新拉全表。
  • 预览缓存:切换文档不重复请求,点右上角「刷新」才清空。
  • 目录树在客户端拼装:层级直接用已拿到的文档数据分组,不额外请求接口;几百份文档的分组开销可以忽略。

配置(可选)

在 profile 的插件行里配置,例如 ~/.dsh/profiles/<profile>/cordis.patch.yml:

- id: dsh-documents
  config:
    extraRoots:
      - "D:/Documents/Reports"
    # 可选:自定义版本自检使用的 registry(默认同时问 npmjs 与 npmmirror)
    registry: "https://registry.npmjs.org"
    # 可选:关掉版本自检,完全不联网
    updateCheck: false
  • extraRoots:在工作区之外额外纳入的目录。文件操作仍限制在这些根目录内(realpath 校验,不允许越界)。
  • registry:版本自检查询的 registry。不填时同时请求 registry.npmjs.org 与 registry.npmmirror.com,取先返回的可用结果(优先官方源)。
  • updateCheck:设为 false 时完全不查 npm,面板不显示新版本提示。

常见问题

装好了但侧边栏没有「文档」图标 按 Ctrl+R 刷新窗口;仍没有就去「设置 → 插件」确认 dsh-documents 已启用、没有加载失败。

打开面板只看到几个工作区,文档去哪了 目录树默认全部收起:点工作区展开到会话,再点会话才看到文档;也可以点顶部「全部展开」。展开状态会记住,刷新窗口不会重置。

列表是空的 / 少了很多文件 文档只从会话事件推导,下面这些情况不会出现:用 bash / pwsh 跑脚本生成、没经过 write / edit / present 的文件;扩展名不在支持列表里的文件;已被移动或删除出工作区的文件。

文档行右侧的「其他会话改过」是什么 表示这份文档除了创建它的会话,还被另一个会话写过/改过——徽章是提示,不是错误。判断依据是会话日志里同一路径的写事件来自多个会话;只有一个会话碰过的文档就不会有这条标记。鼠标悬停能看到具体是哪些会话,点「详情」能看到每次变动的事件坐标。文档本身只挂在创建会话的目录下,不会重复出现。

安装时报 ERR_PNPM_EPERM ... importPackage 通常是 node_modules 里留了旧的同名目录(例如早期用本地目录安装留下的链接),pnpm 无法覆盖。删掉再装:

$nm = "$env:USERPROFILE\.dsh\profiles\desktop\node_modules"
Remove-Item "$nm\dsh-documents" -Recurse -Force -ErrorAction SilentlyContinue
Get-ChildItem $nm -Filter 'dsh-documents_tmp_*' | Remove-Item -Recurse -Force

发布后立刻升级,装上的还是旧版本(pnpm 的 minimumReleaseAge) pnpm 11 默认带供应链策略:发布不足 24 小时的版本不参与解析。于是 dsh plugin add dsh-documents@latest 会解析回 lockfile 里的旧版本,看起来像「有新版本但升级无效」。三种绕法:

  1. 本地 tarball(推荐自测):npm run install:local,走 file: 依赖,不查发布时间。
  2. 把该版本加进豁免:在 ~/.dsh/profiles/<profile>/pnpm-workspace.yaml 的 minimumReleaseAgeExclude 列表里加一行 dsh-documents@<要装的版本>(例如 [email protected]),再装一次。
  3. 等冷却期:发布满 24 小时后 dsh plugin add dsh-documents@latest 自然可装。

点「打开」没反应 / 提示无法打开 打开动作交给 DSH 的桌面接口执行。插件进程本身不直接启动 GUI 程序(会被沙箱拦截),失败时界面会给出原因。

「打开会话」跳过去了,但没有高亮到具体那一行 Harness 目前没有公开「滚动并高亮某条事件」的客户端 API,所以只做到打开会话并加载到该事件;事件坐标(轮次 / #seq / 时间)显示在按钮旁,方便手动定位。


已知限制

  • 列表中最多显示 800 个文档,超出会提示截断。
  • 列表和预览按文件内容读取,超大文件的预览会被截断(默认 400 KB)。
  • 文档的「创建会话」由会话事件时间推断:如果一个文件在多个会话里都被首次写入,取最早的那次。
  • 目录树里每份文档只出现一次,挂在创建它的会话下;被其他会话编辑过的不会重复挂载,「详情」里能看到全部会话。

开发

npm run check       # node --check + 包结构校验
npm run pack:dry    # 查看 npm 包内容

本地自测(不经过 npm)

改完代码要在 DSH 里看效果,打成本地 tarball 装回去就行,不需要发布、也不会被 minimumReleaseAge 挡住:

npm run install:local                    # 校验 + 打包到 dist/ + 装进 desktop profile
npm run install:local -- -Version 1.0.4-local.1   # 顺便换一个本地版本号
npm run install:local -- -Profile web    # 装到别的 profile

脚本做这些事:校验包结构 → npm pack 到 dist/ → 清掉上次中断留下的 dsh-documents_tmp_* 目录(避免 ERR_PNPM_EPERM)→ 在 profile 目录里 pnpm remove + pnpm add <tarball>(同版本号重装时 pnpm 只会报 Already up to date,必须先 remove)→ 用 SHA256 比对装进去的文件和本地构建是否一致。

装完按 Ctrl+R 刷新窗口;index.js(宿主侧)改动要完全退出 DSH 再启动才生效。想回到 npm 正式版:npm run install:local -- -Restore。

包内容固定为:index.js、client.js、cordis.patch.yml、locale/*.json、icon.svg、README.md、LICENSE。

文件 作用
index.js Host 半:读会话日志、聚合文档、流式/增量列表、预览、raw 文件流、文件操作、documents 工具、本地 API
client.js Client 半:侧边栏入口、文档库、查看器、Markdown 渲染、会话溯源与跳转
cordis.patch.yml 插入 dsh-documents 行
locale/*.json 插件管理器显示用的标题与描述
icon.svg 插件图标
scripts/verify.mjs 校验包名 / 客户端模块 id / patch 行名一致
scripts/local-install.ps1 本地打包 + 装进 profile,用于自测未发布版本
.github/workflows/ci.yml 推送与 PR 时校验包结构
.github/workflows/release.yml 推 main / v* tag 时发布到 npm 并创建 GitHub Release

发布(维护者)

推 main 即自动发布,前提是版本号变了:

npm version patch     # 或 minor / major
git push origin main

.github/workflows/release.yml 做这些事:校验包结构 → 查 npm 上是否已有该版本(已有就跳过,所以只推代码不会失败)→ 用 npm trusted publishing(OIDC) 发布并生成 provenance → 创建 v<version> tag 与 GitHub Release(附 .tgz)。

配置要点(一次性):

  • npmjs 包设置 → Trusted publishing → GitHub Actions:aerfaman / dsh-documents / release.yml / Environment release(必须与 workflow 的 environment: release 一致,否则 OIDC 交换返回 404、npm 报含糊的 ENEEDAUTH)。
  • 不要在仓库里配 NPM_TOKEN,workflow 里也不要用 registry-url——两者都会让 npm 退回 token 认证而放弃 OIDC。

本地接口(开发用)

  • GET /dsh-documents/api/list — { documents, sessionCount, truncated, rev }
  • GET /dsh-documents/api/list?stream=1 — NDJSON:每扫完一块会话输出一行 { t: "docs", documents, scanned, sessions, sessionCount },结束为 { t: "done", rev, total, limit, truncated }
  • GET /dsh-documents/api/list?since=<rev> — 增量:{ rev, added, updated, removed };无变化 { unchanged: true };rev 已过期(宿主重启或落后太多){ full: true, documents }
  • GET /dsh-documents/api/version — { current, latest, source, updateAvailable, checkedAt };?force=1 绕过 6 小时缓存;latest 为 null 表示查不到(离线 / registry 不可达)
  • GET /dsh-documents/api/preview?path=... — 文本预览
  • GET /dsh-documents/api/raw?path=... — 图片 / PDF 内嵌流(支持 Range)
  • POST /dsh-documents/api/action — { action: "open" | "reveal" | "rename" | "trash", path, name? }

POST 需要请求头 x-dsh-documents: 1;所有路径先做 realpath 校验,必须落在已配置的工作区根目录内。