npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

dsh-plugin-library

v0.1.3

Published

本地文件资料库:内容寻址的不可变修订、派生的可检索正文、文件夹与模型工具。

Readme

dsh-plugin-library

M5:把 WorkDSH 的本地资料库复刻成 DSH 插件。

原生 DSH 没有"带修订的本地资料"这一层:文件要么在工作区里被就地改写,要么只是附件。 本包把导入的每个文件变成一个 资产(asset),每次导入产生一个 不可变修订(revision): 原始字节内容寻址存放、永不修改;检索读的是派生的纯文本;任务与项目只引用 assetId + revisionId,不引用可变路径。

安装

前置条件:DSH 0.2.0-rc.2+。

  • npm 包:在 DSH 的插件市场/插件管理里安装 dsh-plugin-library,或在 profile 的 package.json 的 dependencies 里加 "dsh-plugin-library": "^0.1.0"
  • tarball:dependencies 里写 "dsh-plugin-library": "file:./dsh-plugin-library-0.1.0.tgz",然后重启 DSH 触发安装

安装后完全退出并重启 DSH(Host 半边只在启动时加载)。验证:重启后插件列表里本包显示「已启用」,且对应面板/工具可用。

做什么

  • 从绝对路径导入(Host 读文件,走 ctx.fs)。同一目录下同名导入 = 给该资产追加新修订。
  • 不可变修订:修订 id = 原始字节的 SHA-256。改动后重新导入产生新修订,旧修订仍可读。
  • 内容寻址去重:字节完全相同 ⇒ 复用已有修订(同一 id、同一编号、不再落一份盘)。
  • 目录树:新建文件夹、重命名、移动、移除。移除是软移除 —— 只标记、不删字节。
  • 检索:跨派生正文搜索,返回资产、目录、类型、修订号与转换状态。
  • 读取:读派生正文(read-text)与读原始字节(read-original,base64)。
  • 启停:停用后读取与检索立刻拒绝(历史引用也不再解析),重新启用即恢复。
  • 限额:单文件 50 MiB、原件总量 5 GiB,越界给出明确拒绝码。
  • 模型工具:library_search、library_read,与面板走同一套服务方法。
  • 面板:main(key dsh-plugin-library)+ sidebar.panellist(order 46,资料库)。 布局照 WorkDSH 上游(LibraryPanel.tsx 111–122 行)复刻为双栏应用壳: 左侧 wd-library-sidebar(标题、搜索/最近/本地产物三行导航、我的资料 +、目录树、 页脚),右侧 wd-library-content 按 view 切换——选中即文档视图(面包屑 + 编辑/下载/•••),搜索视图带表单与「资料类型/资料来源/更新日期」筛选行, 最近/本地产物是裸列表,未选中时是欢迎页。导入按绝对路径进行(本 Host 没有 浏览器文件选择框),上游的 <input type="file"> 槽位保留在样式表中但不再渲染。

明确不做(M5 范围外)

  • PDF / DOCX / PPTX / XLSX 的二进制预览渲染器及其重依赖 (pdfjs-dist、jszip、docx-preview、pptx-viewer)——不装。
  • 右侧栏预览页签(sidebar.right.pane.tab)。
  • 输入框 @ 引用(inputTriggers / conversation.input.left)。

因此只对文本类格式做正文转换:.md / .markdown / .txt / .html / .htm / .json / .csv / .log。HTML 用去标签得到正文。其余扩展名一律按原始字节保存, 转换状态为 unavailable("无文本转换"),仍可下载、仍可按文件名搜到。

磁盘布局

根目录:$DSH_HOME/dsh-plugin-library(DSH_HOME 未设置时退回 ~/.dsh)。

objects/<assetId>/<revisionId>/original.<ext>   原始字节,精确副本,mode 0600
objects/<assetId>/<revisionId>/content.md       派生检索文本(无转换时为空)
objects/<assetId>/<revisionId>/revision.json    小型元数据记录
.tmp/<uuid>/                                    写入暂存区,成功后 rename 就位
  • revisionId 就是 sha256(原始字节) 的小写十六进制。
  • 每个修订目录先写进 .tmp/<uuid>,再 rename 到最终位置:崩溃不会留下"看起来权威"的半成品。
  • apply() 不建目录、不写文件(docs/PORTING-NOTES.md §10);目录在第一次导入时出现。
  • 读导入来源走 ctx.fs;写自有对象存储用 node:fs(ctx.fs 没有二进制写), 每一条路径都过 safePath(),越出根目录即 library/path-escape。

领域数据

| 域 | 表 | 键 | 内容 | | --- | --- | --- | --- | | dsh_skills_library | states | local | nodes(文件夹 / 资产节点)、assets(资产元数据)、revisions(修订记录,键 ${assetId}:${sha256}) |

三个集合都是宽松 record:DTO 校验放在 manager 里,这样拒绝能指名到字段,而严格 schema 会让每次加字段都变成迁移。WorkDSH 的键是 organizationId_principalId;当前是个人 profile, 键用常量 local,多租户这一维不存在,不是假的。

注意:revisionId 是内容哈希,所以不同资产导入相同字节时 id 相同、记录各自独立 (对象目录含 assetId,因此各有自己的原件目录)。引用永远是 assetId + revisionId 的组合, 不会歧义。

路由端点

POST /api/dsh-skills/library,信封 { endpoint, payload } → { ok, value | error }:

overview、tree、asset、create-folder、import、rename、move、remove、 set-enabled、search、read-text、read-original。

模型工具

| 工具 | 参数 | 行为 | | --- | --- | --- | | library_search | query(必填)、kind | 搜索派生正文,返回 asset_id / revision_id / 目录 / 类型 / 修订号 / 转换状态 / 摘要 | | library_read | asset_id(必填)、revision_id、offset、limit(1–20000) | 读某个修订的派生正文,可分页 |

两者都调用与面板相同的 LibraryManager 方法,所以停用、移除、限额对两条路径同时生效。 defineTool 来自安装内的 @deepseek-ai/dsh-tools(经 importDshPackage(); 见 docs/PORTING-NOTES.md §9)。离线跑不了这个 specifier,src/tools.js 里有 一个只覆盖本包所用 schema 子集的本地编译器作兜底(见下"没验到的")。

错误码

| 码 | 含义 | | --- | --- | | library/invalid-request | 缺字段或字段类型不对 | | library/invalid-name | 名称非法(空 / 超长 / 含路径分隔符) | | library/not-found | 资产、修订或文件夹不存在(含来源文件不存在、已移除) | | library/not-a-file | 导入来源不是普通文件 | | library/not-an-asset / library/not-folder | 节点类型不符 | | library/name-conflict | 同目录已有同名项目(大小写不敏感) | | library/cycle | 文件夹移到自己的子目录 | | library/file-size | 单文件超过 50 MiB(或读来源超过上限) | | library/quota-exceeded | 原件总量将超过 5 GiB | | library/disabled | 资产已停用,读取 / 检索被阻断 | | library/conversion-unavailable | 该修订没有可读的派生正文(unavailable / failed) | | library/path-escape | 记录里的对象路径越出资料库根目录 | | library/fs-unavailable | ctx.fs 不可用 | | library/read-denied / library/read-failed / library/aborted | 来源读取被沙箱拒绝 / 失败 / 取消 | | library/not-ready | 存储域尚未就绪 | | library/invalid-page | library_read 的 offset / limit 非法 |

验证

npm run gate
node --test "tests/library.test.mjs"

15 条测试走真实 Host 入口(apply + 注册出来的路由 + 注册出来的工具): 导入与派生正文、不可变修订(改字节出新修订且旧修订仍可读)、同字节去重、 目录新建 / 重命名 / 移动 / 环检测、检索命中、停用即刻阻断读取与检索、软移除保留字节、 单文件限额、总量配额、路径逃逸拒绝、来源缺失 / 目录拒绝、工具注册与执行、 未知端点信封、apply 不落盘。

没验到的

  • 面板在真实页面上的渲染与浅深色:cordis_inspect_query 的 Client Slots 查询本次 超时(页面未响应),所以 main / sidebar.panellist 的注册只按 docs/PORTING-NOTES.md §5 的实测契约与同仓 probe/connectors/projects 的既有写法对齐, 没有在运行中的页面上核对。
  • 官方 defineTool 的编译路径:离线无法解析 @deepseek-ai/dsh-tools,测试跑的是 src/tools.js 的本地兜底编译器。真实安装里走官方 defineTool,但这条路径没有被离线测试覆盖。
  • ctx.fs 的真实实现:离线用的是一个 node:fs 替身;真实后端对路径解析、沙箱可见性 与 FsError 码的处理没有实测(本包只映射了 FS_NOT_FOUND / FS_NOT_REGULAR_FILE / FS_TOO_LARGE / FS_SANDBOX_DENIED / FS_ABORTED / FS_IO_ERROR)。
  • 默认限额本身:测试用 maxBytes: 64、maxTotalBytes: 24 验证拒绝逻辑, 50 MiB / 5 GiB 这两个默认值没有真的导入过一个越界文件。
  • ctx.storageDomain 的真实后端:离线是内存替身。领域 schema 是宽松 record, 真实 zod 校验是否接受本包的记录形状没有实测。
  • 软移除的恢复:只做了"移除后隐藏且读不到",没有做撤销 / 回收站界面。
  • revision.json 的下游消费者:文件写了,但没有第二个读者。
  • 跨资产同字节去重:同一字节导入到两个不同资产时按设计各存一份原件 (对象路径含 assetId),磁盘上不共享;测试没有覆盖这个取舍。
  • sidebar.panellist 图标点击是否真的切到本面板:面板 key 与入口 id 一致, 但没有真机点击验证。