Files
dsh_shenxian/dsh-server-docs/04-调整方案/89-对话内文件预览-采纳官方推荐库现成插件.md
T
admin 5ad755116e chore(docs): 文档库并入代码仓(R4 选 a)+ 索引/台账跟进
1) dsh-server-docs/ 从工作区(原 E:\...\aliyun-dsh-server\dsh-server-docs)**整体并入本仓**,
   保留目录名 ⇒ 仓库内 dsh-server-docs/... 的相对引用天然继续有效;旧目录(含其 .git)已归档到
   工作区 _中间产物_待清理/,未随本提交带入。
2) .gitattributes:新增 `dsh-server-docs/** -text` —— 原文档库是 `* -text` + autocrlf=false,
   必须保持纯 LF,否则会被本仓的 CRLF 规则翻掉。
3) 活引用里的绝对路径已全部改到新位置(docs 的 INDEX / README / scripts / skills + 用户级 skills
   + ~/.workbuddy/settings.json 的 hooks);历史档案(04-调整方案/、archive/)按「只增不改」未动。
   ⚠️ hooks 路径改动需「完全重启会话」才生效(配置是会话启动快照)。
4) 交接单/T08:新增 §16「生产整体切换执行记录」(形态 / 落地动作 / **4 个只有真上线才暴露的真 bug** /
   验收证据 / 回滚命令 / 残留项);台账 T08 行 → 已完成并归档;03-路线图 §二 登记 T08 收尾项。
5) 统一称谓:**「本机」只指跑 WorkBuddy 的开发机**,47 / 106 一律写「远程服务器」。
2026-09-15 18:47:13 +08:00

120 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 89-对话内文件预览——采纳官方推荐库现成插件(2026-09-14 落地)
- 日期:2026-09-14 | 状态:🔄 **进行中**(L2 机制级已验证;L5 用户实测待做)
- 触发:用户原话 ——「**这个 univer 太重了,有没有别的方式可以做个插件让用户点击对话中的文件,可以在会话栏旁边的窗口中打开展示**」→ 追加「**需要查官方推荐库是否有类似插件,是重新开发还是改造**」
> **TL;DR**
> **不重新开发、也不改造 univer** —— 官方推荐库里有现成的,且有一个与我们的 dsh 版本**精确匹配**:
> **`@softspark/[email protected]`(tgz 65 KB = univer 的 1/650)**。
> 它**包住官方的 `remote.session.openWorkspacePath`**,接管"对话里点文件"的手势,弹只读预览弹窗;卸载即恢复原生行为。
> 已导入候选池(**兼容预检 `level: ok`,无需声明信任**)→ 在 guest 启用 → 实例重启探活 `success`;
> 页面客户端插件 **46 → 47**,其 `inject` **4 个全部可满足**(避开"静默挂死"老坑)。
---
## 背景与动机
- univer 插件(`dsh-univer-office`)**重**:tgz 42 MB、网关进程常驻 ~350 MB、还带原生绑定(glibc 门禁)。
- 用户要的是**轻量替代**:**点对话里的文件 → 在会话栏旁边的窗口展示**。
- 用户明确要求先查**官方推荐库**再决定"重新开发还是改造"(对应 `dsh-decision-method` 的 **U2 能扩展就不新建**)。
## 「官方推荐库」是什么(本次查清)
| 来源 | 说明 |
|---|---|
| **`Awesome-DeepSeek-Harness-Plugins`**(`github.com/web-casa/Awesome-DeepSeek-Harness-Plugins`) | 社区整理的官方索引,数据源 = **cordis.run 插件索引**,自称 **331 个插件**(分 5 类:Dev Assistants 78 / Workflow 37 / Themes&UI 90 / Data Integration 8 / Productivity 118) |
| **npm** `keywords:dsh-plugin` 搜索 + 具体包元数据 | 取真名、版本、`dsh` 声明、依赖范围、体积 |
| ⚠️ `cordis.run/data/plugins.json` | **直连 403**(需要浏览器的 UA/上下文)⇒ 走 README 与 npm 两条路 |
**dsh 客户端能力现状(本次实测)**:
- **没有官方 viewer/preview 注册点**(全客户端包 grep 无 `registerViewer` 类 API);
- 但布局里有 **`details` 列**(会话栏旁边、可拖宽)与 **`shell.overlay`** 浮层;
- 官方 **`dsh-client-ui-deliverables`** 已把「本轮产出文件」渲染成**可点击 chips**(点击走 chat 视图的 `openFile`,该 opener 由宿主能力提供、在无桌面宿主的实例里基本是空转);
- 平台侧已有 **`GET /api/fs/download?path=`**(`requireAuth` + 限定调用者根内 + 大小限制)且**跨域放行**
(实测 `access-control-allow-origin: https://guest.alotbuy.com` + `allow-credentials: true` ⇒ 200、536 KB 真读到)。
## 方案对比(**含"不做"**)
| 方案 | 内容 | 判定 | 理由 |
|---|---|---|---|
| **A 复用现成插件** | 从官方推荐库挑一个,走既有投放通道 | ✅ **采纳** | 零开发、可回滚(卸载即恢复原生)、体积最小 |
| B 自己写轻量插件 | 纯客户端 + `shell.overlay` 右侧抽屉 + 拦截官方 chips 点击 | ❌ 否决 | 需复刻「产出文件」解析逻辑或做 DOM 拦截(耦合官方类名);**有现成的就不该造**(U2) |
| C 改造 univer | 让它变轻 | ❌ 否决 | 42 MB 与网关常驻是它的**架构**(协作网关 + 原生绑定),改造=重写 |
| D 改造官方 deliverables / sidebar | 直接改官方包 | ⛔ **不可** | **R2 不改官方 dsh 主程序与缓存** |
| **不做**(保持现状) | 用户只能下载后本地打开 | ❌ 否决 | 用户明确的痛点在"会话里看" |
## 候选体检(**判据三关**,可复用)
> **闸 1** 依赖的官方包**存在**吗(不存在的包 ⇒ 客户端 fiber **静默挂死**)|
> **闸 2** 有没有依赖**被平台角色补丁禁用**的官方包(`dsh-client-ui-settings-models` / `-settings-plugins` / `-settings-plugin-inventory` / `-cordis` / `dsh-client-hmr` / `dsh-host-directory-picker-auto`)(同上,静默挂死)|
> **闸 3** `peerDependencies` 的 `@deepseek-ai/*` 版本范围**是否覆盖我们的 dsh 版本**(**0.1.2-rc.1**)
| 候选 | 体积 | 判定 | 依据 |
|---|---|---|---|
| ✅ **`@softspark/dsh-file-preview` v2.0.0** | **65 KB** | **采纳** | peer **精确锁 `0.1.2-rc.1`(=本站版本)**;inject = `client-locale` / `api-remotes` / `api-session-controller` / `client-ui-renderer` **全在且未被禁**;`exports["./client"].default` 形态(被 dsh 接受);读文件走**官方 host Remote seam**;patch 自述"包住 `remote.session.openWorkspacePath` 接管对话文件打开手势,移除即恢复原生" |
| ❌ `dsh-file-viewer` v0.3.5 | 5.7 MB | 否决 | inject 含 **`@deepseek-ai/dsh-client-runtime`(本站不存在)** ⇒ 静默挂死 |
| ❌ `@deepseek-ai/dsh-client-ui-sidebar-documentpreview` | 6.8 MB | 否决 | 面向 **0.1.5** 系(依赖 `dsh-client-ui-sidebar-right`,本站只有 `-ui-sidebar`)⇒ 版本不匹配;且 **R1 不升 dsh** |
| ❌ `dsh-file-review` v0.8.1 | 1.5 MB | 否决 | inject 含 **`ui-settings-plugins`(被平台角色补丁禁)** ⇒ 静默挂死 |
| ❌ `dsh-at-file` / `@linxin666/dsh-client-ui-aionui-panel` | — | 否决 | 同样注入不存在的 `dsh-client-runtime` |
| ❌ `dsh-local-filetree` / `dsh-split-panes` | — | 不可得 | npm 无此名(README 未给包名)⇒ 需再溯源 |
| ⏸ `dsh-better-sidebar` + `@huanlin/…-office` | 14 MB + 22 MB | 备选 | 功能最强(VSCode 式右栏 + Office 预览),但**合计 ~36 MB**、30 依赖,且依赖 `dsh-client-ui-sidebar-right`(本站无)⇒ 与"轻量"诉求相悖 |
## 实现
1. `curl` 取 tgz(`https://registry.npmjs.org/@softspark/dsh-file-preview/-/dsh-file-preview-2.0.0.tgz`,65 247 B)→ scp 到服务器;
2. admin `POST /api/plugins/business`(base64 上传 + 安全/兼容预检)⇒
`{"ok":true, "version":"2.0.0", "compat":{"level":"ok","findings":[],"platformPkgs":223}, "trustedOverride":false}`
—— **预检全过,未使用 trust override** ✓(warning 有 `vm-eval`(打包产物里的动态求值)与 `network-egress`(README 链接),**非阻塞**);
3. `POST /api/plugins/mine/apply`(guest 启用)⇒ 任务 `success / 完成`(平台自动重启实例 + 探活);
4. 实装路径:`…/profiles/web/node_modules/@softspark/dsh-file-preview` ✓。
## 验证记录
| 级别 | 手段 | 结果 |
|---|---|---|
| L2 机制 | 实装存在性 | ✅ `node_modules/@softspark/dsh-file-preview` |
| L2 机制 | 实例页面 `__DSH_BOOT__` 清单 | ✅ 客户端插件 **46 → 47**;`@softspark/dsh-file-preview` 行 inject 4 个 **差集为空**(无可满足性问题) |
| L2 机制 | 平台侧预检 | ✅ `compat.level = ok`(判据 A/B 均过) |
| **L5 用户实测** | 硬刷新后**点击对话里的文件** | ⏳ **待用户确认**(本机无 Chromium,渲染类只能到此) |
## 事故 / 踩坑记录
- **`cordis.run/data/plugins.json` 直连 403** ⇒ 官方索引要走 README / npm 两条替代路径。
- **npm 包名不等于清单里的短名**:`dsh-local-filetree` / `dsh-split-panes` 在 npm 无此名(`dsh-local-filetree` 疑似本地/未发布)。
- **本机 shell 丢 PATH**:`rm`/`cat` 变 shim 报错、`curl "$(cat f)"` 空参数 ⇒ 每次先 export PortableGit 的 `usr/bin`+`mingw64/bin`。
- **Windows python 与 git-bash 的 `/tmp` 不是同一目录** ⇒ 两边传文件要统一用 `D:/...` 或在同一侧读写。
## 回滚 / 注意
- **回滚 = 在功能管理里停用该插件**(`mine/apply` 传 `enabled:false`)⇒ 平台 `pnpm remove` + 重启;**卸载即恢复原生文件打开行为**(patch 自述)。
- 与 univer **并存无冲突**(两者入口不同:univer 管 `.univer` 的协作预览,本插件管"对话里的文件"只读预览)。
- ⚠️ 第三方插件升级前**仍要过三关**(见上)——尤其别让它新版本引入 `dsh-client-runtime` 之类不存在的包。
- 候选池里新增了 `@softspark/[email protected]`(id 即包名)。
---
## 追加(2026-09-14 14:xx · **能力边界实测 + 三条后续建议的逐条处置**)
> 触发:用户「**按照你的建议处理**」。
### 一、该插件的能力边界(读包内 `lib/client.js` 的分派表实测)
| 类型 | 支持 | 渲染方式 |
|---|---|---|
| **文本类**(`md` `markdown` `txt` `log` `json` `yaml` `yml` `csv` `js` `ts` `tsx` `jsx` `py` `sh` `sql` `html` `css` `xml`) | ✅ | `kind: text` / `html`(**sanitize** 后渲染) |
| **图片**(`png` `jpg` `jpeg` `gif` `webp` `svg`) | ✅ | `kind: image` / `svg`(base64 内联) |
| **PDF** | ✅ | `kind: pdf` |
| **`xlsx` / `docx` / `pptx` / `.univer`** | ❌ | 命中 `unsupported`(有兜底提示);另有 **「too large」大小上限**(阈值写在代码里,未命名常量) |
- host 半边(`host.js` 15 KB)职责 = **会话授权 + 只读工作区文件**(`workspace` / `path.resolve` / `base64`)⇒ 与平台 `fs-guard` 同思路,**权限收窄** ✓。
### 二、三条建议的处置
| 建议 | 处置 | 理由 |
|---|---|---|
| ① L5(用户硬刷新后点对话里的文件) | ⏳ **归用户** | 本机无 Chromium,渲染类只能到此(`dsh-decision-method` §4.3 L5 口径) |
| ② Office 预览:装 36 MB 组合 **或** 让 AI 出 HTML | **两条都不做 —— 改走已有能力** | 用户早上问的"xlsx 能不能在会话里看",**答案已从「不能」变成「可以」**:`univer_import` 自 **0.2.28**(本日 §八 接通 glibc 2.35)起可用 ⇒ 导进 `.univer` 即在线看;要轻量则让 AI 出 `csv`/`html`。**无需再装任何东西** |
| ③ **停用 univer 省内存**(我上一条的💡建议) | **❌ 我自己否决**(记录在案) | 它承载用户**明说的核心用法** ——「AI 生成 md/doc/excel + Univer 在线看」;而"太重"的痛点已由本插件覆盖,且 univer 网关是**按需启动 + 空闲自停**(常驻成本主要就是 42 MB 磁盘)。⇒ **要停的前置动作** = 先把 `office-file-generation` 技能迁出 univer(改由独立载体承载),**之后**才可安全停用;该迁移等用户明确说"停"再做 |
> 📌 两者定位互补,**并存**:本插件管「对话里任意文件 → 只读预览」(文本/图片/PDF);univer 管「Office 双向 + `.univer` 协作预览/编辑」。