dsh-plugin-library 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +154 -0
- package/cordis.patch.yml +9 -0
- package/dist/client.js +2730 -0
- package/dist/host.js +1626 -0
- package/locale/en.json +4 -0
- package/locale/zh.json +4 -0
- package/package.json +45 -0
package/README.md
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# dsh-plugin-library
|
|
2
|
+
|
|
3
|
+
M5:把 WorkDSH 的本地资料库复刻成 DSH 插件。
|
|
4
|
+
|
|
5
|
+
原生 DSH 没有"带修订的本地资料"这一层:文件要么在工作区里被就地改写,要么只是附件。
|
|
6
|
+
本包把导入的每个文件变成一个 **资产(asset)**,每次导入产生一个 **不可变修订(revision)**:
|
|
7
|
+
原始字节内容寻址存放、永不修改;检索读的是派生的纯文本;任务与项目只引用
|
|
8
|
+
`assetId + revisionId`,不引用可变路径。
|
|
9
|
+
|
|
10
|
+
## 安装
|
|
11
|
+
|
|
12
|
+
前置条件:DSH 0.2.0-rc.2+。
|
|
13
|
+
|
|
14
|
+
- **npm 包**:在 DSH 的插件市场/插件管理里安装 `dsh-plugin-library`,或在 profile 的 `package.json` 的 `dependencies` 里加 `"dsh-plugin-library": "^0.1.0"`
|
|
15
|
+
- **tarball**:`dependencies` 里写 `"dsh-plugin-library": "file:./dsh-plugin-library-0.1.0.tgz"`,然后重启 DSH 触发安装
|
|
16
|
+
|
|
17
|
+
安装后**完全退出并重启 DSH**(Host 半边只在启动时加载)。验证:重启后插件列表里本包显示「已启用」,且对应面板/工具可用。
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
## 做什么
|
|
21
|
+
|
|
22
|
+
- **从绝对路径导入**(Host 读文件,走 `ctx.fs`)。同一目录下同名导入 = 给该资产追加新修订。
|
|
23
|
+
- **不可变修订**:修订 id = 原始字节的 SHA-256。改动后重新导入产生新修订,旧修订仍可读。
|
|
24
|
+
- **内容寻址去重**:字节完全相同 ⇒ 复用已有修订(同一 id、同一编号、不再落一份盘)。
|
|
25
|
+
- **目录树**:新建文件夹、重命名、移动、移除。移除是**软移除** —— 只标记、不删字节。
|
|
26
|
+
- **检索**:跨派生正文搜索,返回资产、目录、类型、修订号与转换状态。
|
|
27
|
+
- **读取**:读派生正文(`read-text`)与读原始字节(`read-original`,base64)。
|
|
28
|
+
- **启停**:停用后读取与检索**立刻**拒绝(历史引用也不再解析),重新启用即恢复。
|
|
29
|
+
- **限额**:单文件 50 MiB、原件总量 5 GiB,越界给出明确拒绝码。
|
|
30
|
+
- **模型工具**:`library_search`、`library_read`,与面板走同一套服务方法。
|
|
31
|
+
- **面板**:`main`(key `dsh-plugin-library`)+ `sidebar.panellist`(order 46,`资料库`)。
|
|
32
|
+
布局照 WorkDSH 上游(`LibraryPanel.tsx` 111–122 行)复刻为**双栏应用壳**:
|
|
33
|
+
左侧 `wd-library-sidebar`(标题、搜索/最近/本地产物三行导航、我的资料 +、目录树、
|
|
34
|
+
页脚),右侧 `wd-library-content` 按 `view` 切换——选中即文档视图(面包屑 +
|
|
35
|
+
编辑/下载/•••),搜索视图带表单与「资料类型/资料来源/更新日期」筛选行,
|
|
36
|
+
最近/本地产物是裸列表,未选中时是欢迎页。导入按绝对路径进行(本 Host 没有
|
|
37
|
+
浏览器文件选择框),上游的 `<input type="file">` 槽位保留在样式表中但不再渲染。
|
|
38
|
+
|
|
39
|
+
## 明确不做(M5 范围外)
|
|
40
|
+
|
|
41
|
+
- **PDF / DOCX / PPTX / XLSX 的二进制预览渲染器**及其重依赖
|
|
42
|
+
(`pdfjs-dist`、`jszip`、`docx-preview`、`pptx-viewer`)——不装。
|
|
43
|
+
- **右侧栏预览页签**(`sidebar.right.pane.tab`)。
|
|
44
|
+
- **输入框 `@` 引用**(`inputTriggers` / `conversation.input.left`)。
|
|
45
|
+
|
|
46
|
+
因此只对**文本类格式**做正文转换:`.md` / `.markdown` / `.txt` / `.html` / `.htm` /
|
|
47
|
+
`.json` / `.csv` / `.log`。HTML 用去标签得到正文。其余扩展名一律按**原始字节**保存,
|
|
48
|
+
转换状态为 `unavailable`("无文本转换"),仍可下载、仍可按文件名搜到。
|
|
49
|
+
|
|
50
|
+
## 磁盘布局
|
|
51
|
+
|
|
52
|
+
根目录:`$DSH_HOME/dsh-plugin-library`(`DSH_HOME` 未设置时退回 `~/.dsh`)。
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
objects/<assetId>/<revisionId>/original.<ext> 原始字节,精确副本,mode 0600
|
|
56
|
+
objects/<assetId>/<revisionId>/content.md 派生检索文本(无转换时为空)
|
|
57
|
+
objects/<assetId>/<revisionId>/revision.json 小型元数据记录
|
|
58
|
+
.tmp/<uuid>/ 写入暂存区,成功后 rename 就位
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
- `revisionId` 就是 `sha256(原始字节)` 的小写十六进制。
|
|
62
|
+
- 每个修订目录先写进 `.tmp/<uuid>`,再 `rename` 到最终位置:崩溃不会留下"看起来权威"的半成品。
|
|
63
|
+
- `apply()` 不建目录、不写文件(`docs/PORTING-NOTES.md` §10);目录在第一次导入时出现。
|
|
64
|
+
- 读导入来源走 `ctx.fs`;写自有对象存储用 `node:fs`(`ctx.fs` 没有二进制写),
|
|
65
|
+
每一条路径都过 `safePath()`,越出根目录即 `library/path-escape`。
|
|
66
|
+
|
|
67
|
+
## 领域数据
|
|
68
|
+
|
|
69
|
+
| 域 | 表 | 键 | 内容 |
|
|
70
|
+
| --- | --- | --- | --- |
|
|
71
|
+
| `dsh_skills_library` | `states` | `local` | `nodes`(文件夹 / 资产节点)、`assets`(资产元数据)、`revisions`(修订记录,键 `${assetId}:${sha256}`) |
|
|
72
|
+
|
|
73
|
+
三个集合都是宽松 record:DTO 校验放在 manager 里,这样拒绝能指名到字段,而严格 schema
|
|
74
|
+
会让每次加字段都变成迁移。WorkDSH 的键是 `organizationId_principalId`;当前是个人 profile,
|
|
75
|
+
键用常量 `local`,多租户这一维**不存在**,不是假的。
|
|
76
|
+
|
|
77
|
+
注意:`revisionId` 是内容哈希,所以不同资产导入相同字节时 **id 相同、记录各自独立**
|
|
78
|
+
(对象目录含 `assetId`,因此各有自己的原件目录)。引用永远是 `assetId + revisionId` 的组合,
|
|
79
|
+
不会歧义。
|
|
80
|
+
|
|
81
|
+
## 路由端点
|
|
82
|
+
|
|
83
|
+
`POST /api/dsh-skills/library`,信封 `{ endpoint, payload } → { ok, value | error }`:
|
|
84
|
+
|
|
85
|
+
`overview`、`tree`、`asset`、`create-folder`、`import`、`rename`、`move`、`remove`、
|
|
86
|
+
`set-enabled`、`search`、`read-text`、`read-original`。
|
|
87
|
+
|
|
88
|
+
## 模型工具
|
|
89
|
+
|
|
90
|
+
| 工具 | 参数 | 行为 |
|
|
91
|
+
| --- | --- | --- |
|
|
92
|
+
| `library_search` | `query`(必填)、`kind` | 搜索派生正文,返回 `asset_id` / `revision_id` / 目录 / 类型 / 修订号 / 转换状态 / 摘要 |
|
|
93
|
+
| `library_read` | `asset_id`(必填)、`revision_id`、`offset`、`limit`(1–20000) | 读某个修订的派生正文,可分页 |
|
|
94
|
+
|
|
95
|
+
两者都调用与面板相同的 `LibraryManager` 方法,所以停用、移除、限额对两条路径同时生效。
|
|
96
|
+
`defineTool` 来自安装内的 `@deepseek-ai/dsh-tools`(经 `importDshPackage()`;
|
|
97
|
+
见 `docs/PORTING-NOTES.md` §9)。离线跑不了这个 specifier,`src/tools.js` 里有
|
|
98
|
+
一个只覆盖本包所用 schema 子集的本地编译器作兜底(见下"没验到的")。
|
|
99
|
+
|
|
100
|
+
## 错误码
|
|
101
|
+
|
|
102
|
+
| 码 | 含义 |
|
|
103
|
+
| --- | --- |
|
|
104
|
+
| `library/invalid-request` | 缺字段或字段类型不对 |
|
|
105
|
+
| `library/invalid-name` | 名称非法(空 / 超长 / 含路径分隔符) |
|
|
106
|
+
| `library/not-found` | 资产、修订或文件夹不存在(含来源文件不存在、已移除) |
|
|
107
|
+
| `library/not-a-file` | 导入来源不是普通文件 |
|
|
108
|
+
| `library/not-an-asset` / `library/not-folder` | 节点类型不符 |
|
|
109
|
+
| `library/name-conflict` | 同目录已有同名项目(大小写不敏感) |
|
|
110
|
+
| `library/cycle` | 文件夹移到自己的子目录 |
|
|
111
|
+
| `library/file-size` | 单文件超过 50 MiB(或读来源超过上限) |
|
|
112
|
+
| `library/quota-exceeded` | 原件总量将超过 5 GiB |
|
|
113
|
+
| `library/disabled` | 资产已停用,读取 / 检索被阻断 |
|
|
114
|
+
| `library/conversion-unavailable` | 该修订没有可读的派生正文(`unavailable` / `failed`) |
|
|
115
|
+
| `library/path-escape` | 记录里的对象路径越出资料库根目录 |
|
|
116
|
+
| `library/fs-unavailable` | `ctx.fs` 不可用 |
|
|
117
|
+
| `library/read-denied` / `library/read-failed` / `library/aborted` | 来源读取被沙箱拒绝 / 失败 / 取消 |
|
|
118
|
+
| `library/not-ready` | 存储域尚未就绪 |
|
|
119
|
+
| `library/invalid-page` | `library_read` 的 `offset` / `limit` 非法 |
|
|
120
|
+
|
|
121
|
+
## 验证
|
|
122
|
+
|
|
123
|
+
```sh
|
|
124
|
+
npm run gate
|
|
125
|
+
node --test "tests/library.test.mjs"
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
15 条测试**走真实 Host 入口**(`apply` + 注册出来的路由 + 注册出来的工具):
|
|
129
|
+
导入与派生正文、不可变修订(改字节出新修订且旧修订仍可读)、同字节去重、
|
|
130
|
+
目录新建 / 重命名 / 移动 / 环检测、检索命中、停用即刻阻断读取与检索、软移除保留字节、
|
|
131
|
+
单文件限额、总量配额、路径逃逸拒绝、来源缺失 / 目录拒绝、工具注册与执行、
|
|
132
|
+
未知端点信封、apply 不落盘。
|
|
133
|
+
|
|
134
|
+
### 没验到的
|
|
135
|
+
|
|
136
|
+
- **面板在真实页面上的渲染与浅深色**:`cordis_inspect_query` 的 Client `Slots` 查询本次
|
|
137
|
+
超时(页面未响应),所以 `main` / `sidebar.panellist` 的注册只按
|
|
138
|
+
`docs/PORTING-NOTES.md` §5 的实测契约与同仓 probe/connectors/projects 的既有写法对齐,
|
|
139
|
+
**没有**在运行中的页面上核对。
|
|
140
|
+
- **官方 `defineTool` 的编译路径**:离线无法解析 `@deepseek-ai/dsh-tools`,测试跑的是
|
|
141
|
+
`src/tools.js` 的本地兜底编译器。真实安装里走官方 `defineTool`,但这条路径**没有**被离线测试覆盖。
|
|
142
|
+
- **`ctx.fs` 的真实实现**:离线用的是一个 `node:fs` 替身;真实后端对路径解析、沙箱可见性
|
|
143
|
+
与 `FsError` 码的处理没有实测(本包只映射了 `FS_NOT_FOUND` / `FS_NOT_REGULAR_FILE` /
|
|
144
|
+
`FS_TOO_LARGE` / `FS_SANDBOX_DENIED` / `FS_ABORTED` / `FS_IO_ERROR`)。
|
|
145
|
+
- **默认限额本身**:测试用 `maxBytes: 64`、`maxTotalBytes: 24` 验证拒绝逻辑,
|
|
146
|
+
50 MiB / 5 GiB 这两个默认值没有真的导入过一个越界文件。
|
|
147
|
+
- **`ctx.storageDomain` 的真实后端**:离线是内存替身。领域 schema 是宽松 record,
|
|
148
|
+
真实 zod 校验是否接受本包的记录形状没有实测。
|
|
149
|
+
- **软移除的恢复**:只做了"移除后隐藏且读不到",没有做撤销 / 回收站界面。
|
|
150
|
+
- **`revision.json` 的下游消费者**:文件写了,但没有第二个读者。
|
|
151
|
+
- **跨资产同字节去重**:同一字节导入到两个不同资产时按设计各存一份原件
|
|
152
|
+
(对象路径含 `assetId`),磁盘上不共享;测试没有覆盖这个取舍。
|
|
153
|
+
- **`sidebar.panellist` 图标点击是否真的切到本面板**:面板 key 与入口 id 一致,
|
|
154
|
+
但没有真机点击验证。
|
package/cordis.patch.yml
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# dsh-skills library bundle patch.
|
|
2
|
+
#
|
|
3
|
+
# One insert row. The Host half owns POST /api/dsh-skills/library, keeps the
|
|
4
|
+
# library records in `dsh_skills_library`, stores original bytes content-addressed
|
|
5
|
+
# under $DSH_HOME/dsh-plugin-library/objects/<assetId>/<revisionId>/, and registers
|
|
6
|
+
# the model-facing library_search / library_read tools.
|
|
7
|
+
- insert:
|
|
8
|
+
- id: dsh-plugin-library
|
|
9
|
+
name: 'dsh-plugin-library'
|