@wszhoho/dsh-file-attachment 0.5.1 → 0.5.3
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 +33 -16
- package/lib/client.js +8 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,20 +1,27 @@
|
|
|
1
1
|
# dsh-file-attachment
|
|
2
2
|
|
|
3
|
-
DeepSeek Harness (dsh) web GUI 插件:在会话输入框中**拖入或 Ctrl+V
|
|
3
|
+
DeepSeek Harness (dsh) web GUI 插件:在会话输入框中**拖入或 Ctrl+V 粘贴文档/图片(支持多文件,一次可拖入/粘贴多个文件)**、或通过 **📎 附件按钮上传**时,浏览器端批量读取全文,保存到**当前会话工作区根目录下的 `.dsh-file-attachment/`**,并在输入框光标处插入 `@<保存副本绝对路径>` 引用。agent 读取 `@路径` 时直接读到落盘副本,不再依赖原始文件位置。
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
图片与文档走**同一条落盘管线**:图片在输入框**内联附件条**中以缩略图预览(点击放大),在聊天区渲染为**可点击放大的缩略图**;文档在附件条中以类型图标 + 文件名条目显示,在聊天区保持芯片样式。当前会话模型不支持多模态时,图片自动调用**可配置 VLM** 识别生成中文描述回填草稿,文本模型也能「看懂」图片。
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
插件接管 dsh 原生 **📎 附件上传按钮**(hero / composer 两种输入模式共用同一位置:加号右侧、modes 左侧),点击后弹出系统文件选择框,可多选文档/图片,复用与拖入/粘贴完全一致的落盘 + `@路径` 插入管线。PC 与移动端浏览器均适用(移动端走原生文件选择器)。
|
|
8
8
|
|
|
9
9
|
## 界面
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
**演示**:拖入/粘贴文档或图片 → 落盘并在输入框插入 `@` 引用 → 输入框内联附件条待发送状态(完整流程见 gif)。
|
|
12
12
|
|
|
13
13
|

|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
**内联附件条**:上传后在 composer 卡片内部、编辑区上方显示——图片为缩略图(点击放大),文档为类型图标 + 文件名条目;条目可移除(同步清除草稿中对应 `@引用`),发送后自动清空。
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
**聊天区图片缩略图**:历史对话中用户消息里的 `@图片路径` 渲染为缩略图(点击打开 Lightbox 放大层);`@文件路径` 保持芯片样式。
|
|
18
|
+
|
|
19
|
+
**上传按钮**:接管 dsh 原生 📎 附件按钮(加号右侧、modes 左侧),点击弹出系统文件选择框(可多选文档/图片)。
|
|
20
|
+
|
|
21
|
+
**设置页**:「设置 → 文件附件」页两部分:
|
|
22
|
+
|
|
23
|
+
- **可上传类型**:按 文档 / 代码 / 配置文件 三类增删扩展名(小写、不带点),图片恒可发送;
|
|
24
|
+
- **多模态识别参数(VLM)**:Base URL / API Key / 模型 / 思考模式开关(默认禁用),仅当前会话模型不支持多模态时调用,未填 API Key 时静默跳过。
|
|
18
25
|
|
|
19
26
|

|
|
20
27
|
|
|
@@ -22,14 +29,15 @@ DeepSeek Harness (dsh) web GUI 插件:在会话输入框中**拖入或 Ctrl+V
|
|
|
22
29
|
|
|
23
30
|
| 操作 | 行为 |
|
|
24
31
|
| --- | --- |
|
|
25
|
-
|
|
|
26
|
-
| 拖入/粘贴
|
|
32
|
+
| 点击 **📎 附件按钮**(插件接管 dsh 原生按钮),在系统文件选择框中**多选**文档/图片 | 与拖入/粘贴同一管线:图片与文档统一落盘 + 光标插入全部 `@` 引用;移动端自动弹出文件选择器 |
|
|
33
|
+
| 拖入/粘贴 **文档/代码/配置文件**(默认 doc·code·config 三类扩展名,如 docx/xlsx/pdf/md/txt/js/json) | 浏览器读全文 → base64 → 宿主落盘 `<会话工作区>/.dsh-file-attachment/<日期>/<文件名>` → 光标插入 `@绝对路径` chip,成功不提示、失败简短 toast |
|
|
27
34
|
| 一次拖入/粘贴 **多个文件**(支持多文件) | 批量处理:逐个读取全文 → base64 → 落盘 → 在光标处一次性插入全部 `@` 引用;全部成功不提示,部分失败仅简短提示「N 个已跳过」 |
|
|
35
|
+
| 拖入/粘贴 **图片** | 与文档同一落盘管线:插入 `@绝对路径` 引用 + 附件条登记缩略图;聊天区渲染为可点击放大的缩略图 |
|
|
36
|
+
| 图片需要被理解,而当前模型**不支持多模态** | 粘贴/上传图片时自动调用可配置 VLM(OpenAI 兼容 `chat/completions`)生成中文描述回填草稿(仅注入模型上下文,不进对话界面);agent 也可主动调用 `describe_image` 工具识别已落盘图片(含历史消息中的 `@图片` 引用) |
|
|
28
37
|
| 拖入 **目录** | 拒绝,toast 提示「不支持拖入目录」,不插入引用 |
|
|
29
|
-
| 拖入/粘贴 **图片** | 接管后走 dsh 既有草稿图片流程(`addImages`):不落盘、不进文件条、不缩放;输入框未就绪且纯图片时原样交原生 |
|
|
30
38
|
| 粘贴 **纯文本**(含从地址栏复制的目录路径字符串) | 不改写,完全原生行为 |
|
|
31
39
|
| 重复拖入同名文件(同一天内) | 追加 `-1`、`-2` 序号,绝不覆盖 |
|
|
32
|
-
|
|
|
40
|
+
| 点附件条 `×` 移除 | 移除附件条目,并清除输入框中指向该文件路径的**全部** `@` 引用 chip(同一文件上传多次产生的多个 chip 一并清除);其他文件的引用不受影响 |
|
|
33
41
|
| 单文件 > 50MB | 跳过并提示 |
|
|
34
42
|
|
|
35
43
|
### 文件命名
|
|
@@ -82,21 +90,30 @@ packages/dsh-file-attachment/
|
|
|
82
90
|
├── package.json # dsh.client 声明 + bundle patch 指向
|
|
83
91
|
├── cordis.patch.yml # bundle 补丁:插入本插件行
|
|
84
92
|
└── lib/
|
|
85
|
-
├── index.js # Host 半:webServer
|
|
86
|
-
└── client.js # Client 半:document 级 capture drop/paste
|
|
93
|
+
├── index.js # Host 半:webServer 路由(/save /config /describe)+ describe_image 工具
|
|
94
|
+
└── client.js # Client 半:document 级 capture drop/paste 监听 + 📎 按钮接管 + 槽组件
|
|
87
95
|
```
|
|
88
96
|
|
|
89
|
-
- **Host 半**:`webServer.register` 前缀路由 `/dsh-file-attachment
|
|
90
|
-
-
|
|
91
|
-
-
|
|
97
|
+
- **Host 半**:`webServer.register` 前缀路由 `/dsh-file-attachment`:
|
|
98
|
+
- POST `/save`:接收 `{name, data(base64), sessionId}`,base64 解码后用 `node:fs/promises` 写盘到会话工作区 `.dsh-file-attachment/`,返回 `{ok, value:{path,dir,name,size}}`;
|
|
99
|
+
- GET/POST `/config`:读写插件配置(可上传类型 + VLM 参数);
|
|
100
|
+
- POST `/describe`:接收 `{dataUrl, prompt}`,调 VLM(OpenAI 兼容 `chat/completions`)识别图片,返回中文描述;
|
|
101
|
+
- `describe_image` 工具(Host 注册):agent 需要理解 `@图片` 引用时调用——读已落盘图片 → VLM 识别 → 描述直接作为工具输出返回(UI 展示 + 模型可见)。
|
|
102
|
+
- **Client 半**槽位:
|
|
103
|
+
- `conversation.input.attachments`(shadow 原生附件条,priority -100):**内联附件条**,渲染自维护的附件登记表——图片为 data URL 缩略图(点击放大)、文档为类型图标 + 文件名;条目可移除(同步清除草稿 `@引用`),发送后自动清空,不依赖 dsh 附件草稿链路(文本模型可正常发送);
|
|
104
|
+
- `conversation.chat.node` keyed `user`(shadow 原生用户消息渲染器,priority -100):聊天区 `@图片路径` 渲染为缩略图(经宿主 `/api/file?path=` 读取落盘图片,点击打开 Lightbox 放大层),`@文件路径` 保持芯片样式;原生 image/file 附件块(多模态模型场景)仍交 dsh 渲染;
|
|
105
|
+
- `conversation.input.dock`:仅保留 `FaBridge` 桥槽(经会话作用域同步 shell/actions/input 状态,hero 首轮空白态也挂载),原文件条渲染已移除;
|
|
106
|
+
- `shell.overlay`(list 槽,toast 通知展示)。
|
|
107
|
+
- **📎 按钮接管**:capture 阶段拦截原生 `fileInput` 的 change 事件,文件进入插件自定义管线(图片/文档统一落盘 + 插 `@引用`);纯文本粘贴完全原生,不做改写。document 级 capture 监听先于应用 bubble 监听执行。
|
|
92
108
|
- **通知**:`shell.overlay` frame-wide 浮动 toast(不参与文档流,不破坏布局),4 秒自动消失。
|
|
93
109
|
- **浮层**:拖入任何文件时 capture 阶段拦截应用自带「拖入图片…」DropOverlay(文案面向图片,对文档是误导)。
|
|
94
110
|
|
|
95
111
|
## 开发说明
|
|
96
112
|
|
|
97
113
|
- `lib/*.js`、`package.json`、`cordis.patch.yml`、`README.md` 当前均为 **UTF-8 无 BOM**(以仓库实测为准);编辑时保持原编码,不引入 BOM。
|
|
98
|
-
- Host 半用 `webServer.register({ kind: 'prefix', path: '/dsh-file-attachment', handler })`
|
|
114
|
+
- Host 半用 `webServer.register({ kind: 'prefix', path: '/dsh-file-attachment', handler })` 提供 `/save`、`/config`、`/describe` 三个路由,并经 `tools.register` 注册 `describe_image` 工具;纯 ESM 无构建,不依赖装饰器/远程反射。
|
|
99
115
|
- Client 半保存用 `fetch('/dsh-file-attachment/save', { method: 'POST', body: JSON.stringify({ name, data, sessionId }) })`,信封为 `{ ok, value | error }`。
|
|
116
|
+
- VLM 走 OpenAI 兼容 `chat/completions`(Base URL / API Key / 模型 / 思考模式可在设置页配置,默认关闭思考模式);未填 API Key 时识别静默跳过,不影响落盘。
|
|
100
117
|
- 项目根 = 会话工作区(`session.header.cwd` → `sandboxPolicy.workspaceRoot` → `process.cwd()` 兜底)。
|
|
101
118
|
- 50MB 上限两侧一致(client 跳过 + host 校验)。
|
|
102
119
|
|
package/lib/client.js
CHANGED
|
@@ -40,7 +40,7 @@ window.__ModuleLoader__.load({
|
|
|
40
40
|
let noticeTimer = null
|
|
41
41
|
const NOTICE_MS = 4000
|
|
42
42
|
const MAX_BYTES = 50 * 1024 * 1024
|
|
43
|
-
const MAX_DIM = 640 //
|
|
43
|
+
const MAX_DIM = 640 // 图片缩放:宽或高任一边 >640 时等比缩小(GIF 例外,原样保动画)
|
|
44
44
|
// 可上传类型(三类:文档/代码/配置文件);图片恒允许(image/*)。
|
|
45
45
|
// 首启为默认值,apply/设置页 fetch 持久化配置(~/.dsh/file-attachment.json)后覆盖。
|
|
46
46
|
const DEFAULT_TYPES = {
|
|
@@ -268,7 +268,7 @@ window.__ModuleLoader__.load({
|
|
|
268
268
|
throw new Error(errMsg)
|
|
269
269
|
}
|
|
270
270
|
|
|
271
|
-
// ---- 图片处理:扩展名 / GIF 判定 / 加载 /
|
|
271
|
+
// ---- 图片处理:扩展名 / GIF 判定 / 加载 / 缩放(宽或高任一边 >MAX_DIM 时处理,GIF 原样保动画,PNG 保透明) ----
|
|
272
272
|
function fileExt(name) {
|
|
273
273
|
const s = String(name == null ? '' : name)
|
|
274
274
|
const dot = s.lastIndexOf('.')
|
|
@@ -286,7 +286,7 @@ window.__ModuleLoader__.load({
|
|
|
286
286
|
img.src = url
|
|
287
287
|
})
|
|
288
288
|
}
|
|
289
|
-
//
|
|
289
|
+
// 缩放:宽或高任一边 > maxDim 时等比缩小(两边都不超过 maxDim 时原样);返回 { data, name }(data 为 Blob/File)。
|
|
290
290
|
// GIF 原样(canvas 取首帧丢动画 + 不支持 gif 输出);PNG 输出 PNG 保透明;其余 JPEG 0.85。
|
|
291
291
|
// 缩放失败/无需缩放时回退原文件。
|
|
292
292
|
async function downscaleImage(file, maxDim) {
|
|
@@ -565,10 +565,11 @@ window.__ModuleLoader__.load({
|
|
|
565
565
|
const it = pending[i]
|
|
566
566
|
try {
|
|
567
567
|
if (it.isImage) {
|
|
568
|
-
//
|
|
569
|
-
//
|
|
570
|
-
const
|
|
571
|
-
const
|
|
568
|
+
// 图片:落盘前等比缩小(宽或高任一边 >MAX_DIM 才处理;GIF 原样保动画),
|
|
569
|
+
// 再走 @路径 纯文本 + 附件条登记(方案 B:不触发 dsh 的 image 能力检查)
|
|
570
|
+
const sized = await downscaleImage(it.file, MAX_DIM)
|
|
571
|
+
const data = sized.data
|
|
572
|
+
const name = sized.name
|
|
572
573
|
if (data === null || typeof data.size !== 'number' || data.size === 0) throw new Error('size')
|
|
573
574
|
if (data.size > MAX_BYTES) throw new Error('size')
|
|
574
575
|
const buf = await data.arrayBuffer()
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wszhoho/dsh-file-attachment",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.3",
|
|
4
4
|
"description": "文件附件:拖拽/粘贴/上传文件(支持多文件);图片与文档统一落盘到 .dsh-file-attachment 并以 @绝对路径 引用发送(文本模型可正常使用);输入框内联显示图片缩略图预览与文件条目,聊天区图片同样渲染为可点击放大的缩略图、文件保持芯片样式;非多模态模型下图片自动调用可配置 VLM 识别生成中文描述回填草稿;文档/代码/配置文件可上传类型可在设置页配置;支持 PC 与移动端浏览器",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dsh",
|