dsh-plugin-read-image-preview 1.4.1
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/LICENSE +21 -0
- package/README.md +64 -0
- package/client.js +1162 -0
- package/cordis.patch.yml +9 -0
- package/index.js +279 -0
- package/package.json +36 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 dsh-plugin contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# dsh-plugin-read-image-preview
|
|
2
|
+
|
|
3
|
+
把**任何工具产出的图片直接画在会话里**——`read_image` 读的文件图,和 computer-use 截图这类**结果附件图**,共用同一张卡片与同一套交互。
|
|
4
|
+
|
|
5
|
+
## 通用模式(v1.4)
|
|
6
|
+
|
|
7
|
+
卡片按数据源分两轨,注册时一次认领所有图像工具(`tool.call.toolview` 的对应键,priority `-1`):
|
|
8
|
+
|
|
9
|
+
| 轨道 | 触发条件 | 字节来源 | 元数据 |
|
|
10
|
+
| --- | --- | --- | --- |
|
|
11
|
+
| `file` | 调用参数里有 `file_path`(read 家族) | Host 半区回环路由 `/read-image-preview/resolve`(调用一开始就能出骨架/预览) | resolve 响应 |
|
|
12
|
+
| `attachment` | 结果 content 里有 `{type:'image', attachment}`(computer-use 截图及未来任何图像工具) | 会话授权的 `props.loadImage`(先 `peek` 缓存) | **全在附件引用上,零额外请求** |
|
|
13
|
+
|
|
14
|
+
没有图也没有报错的调用渲染一行结果摘要(失败标红),执行中渲染按真实宽高比撑开的骨架——认领的行永远不会是空壳。
|
|
15
|
+
|
|
16
|
+
**v1.4.1:图片加载零位移。** 两种模式下图片像素尺寸都在字节到达之前就已知(resolve 响应 / 附件引用),因此 `<img>` 直接带 `width/height` 渲染、信息行宽度也按已知比例预先定死。晚到的图片(上一张截图的 fetch/解码在新内容压上来之后才完成)落地时不再产生布局跳变——正是这个跳变会让 DSH 聊天流的吸底逻辑把浏览器自发的位移误读成「用户上滚」,从而停止自动跟随最新记录。
|
|
17
|
+
|
|
18
|
+
**dsh 0.1.7-rc.1 起工具调用分三阶段。** 官方把 `RunningToolCall` 拆成 `preparing`(参数还在流式生成,**没有 `argsRaw`**)与 `start`,并且参数开始流动时就把视图渲染出来(`tool.call.toolview` 的 owner 多了 `phase`)。因此判定「执行中」不能再只看 `argsRaw` 是否存在,否则我们认领的行在整个 preparing 阶段会是空壳——`isRunningBlock()` 现在把 `phase: 'preparing' | 'start'` 都算执行中,形状判断继续兼容更早的版本。`tests/phases.test.mjs` 用官方三种形状锁住这条约束(设 `READ_PREVIEW_CLIENT` 指向未修复的 `client.js` 可以验证它确实会失败)。
|
|
19
|
+
|
|
20
|
+
**接入新工具 = 在 `client.js` 的 `TOOL_LABELS` 加一行**,交互(缩略图、点击放大、Ctrl+滚轮、拖动、双击适应、骨架、透明棋盘格)全部自动继承。
|
|
21
|
+
|
|
22
|
+
## 它解决什么
|
|
23
|
+
|
|
24
|
+
DSH 自带的 `read_image` 卡片(`dsh-client-ui-tool` 的 `read-image-toolview`)有三个让人看不到图的地方:
|
|
25
|
+
|
|
26
|
+
1. 图片是 `ToolRow` 展开区里的内容,**默认折叠**,不点开那一行就没有画面;
|
|
27
|
+
2. 官方派生逻辑明确写着运行期的调用没有 content,所以 **AI 正在看图的那几秒卡片里是空的**;
|
|
28
|
+
3. 折叠状态只有一行路径摘要。
|
|
29
|
+
|
|
30
|
+
这个插件接管这些工具的展示位(`tool.call.toolview` 的对应键,priority `-1`,同时遮蔽内置行与动态插件的兜底卡片),把图片提到最外层:
|
|
31
|
+
|
|
32
|
+
- **调用一开始就出图**,不等 tool result;
|
|
33
|
+
- 加载中是按**真实宽高比**撑开的骨架(扫光动画,`prefers-reduced-motion` 下停用);
|
|
34
|
+
- 图下一行信息:状态点(蓝闪=正在看 / 绿=看完 / 红=失败)、路径、像素尺寸、体积、格式;
|
|
35
|
+
- 默认是克制的缩略图(`min(420px, 100%)` × `max-height: 300px`),不占聊天流;
|
|
36
|
+
- **点图进入缩放视图**:`Ctrl + 滚轮` 连续缩放(0.2×–8×,锚定光标位置;滚轮只在按住 Ctrl 时被消费,所以不与页面滚动打架)、**按住拖动平移**、双击复位、`Esc` 或点背景关闭;底部有当前缩放百分比与 `−` / `+` / `100%`;
|
|
37
|
+
- 透明容器(PNG/WebP/GIF)自动铺棋盘格;
|
|
38
|
+
- 操作:复制路径、在编辑器中打开。
|
|
39
|
+
|
|
40
|
+
## 两半的分工
|
|
41
|
+
|
|
42
|
+
Slot 视图没有文件权限,所以字节要走页面自己的传输:
|
|
43
|
+
|
|
44
|
+
| 半边 | 文件 | 职责 |
|
|
45
|
+
| --- | --- | --- |
|
|
46
|
+
| Host | `index.js` | 用组合的 `fs` 服务解析路径、按魔数校验容器、解析像素尺寸,签发能力 token,并在插件私有前缀上提供两个回环路由 |
|
|
47
|
+
| Client | `client.js` | 接管 `read_image` 展示位并渲染卡片;通过 `GET /read-image-preview/resolve` 拿描述与 URL |
|
|
48
|
+
|
|
49
|
+
路由:
|
|
50
|
+
|
|
51
|
+
- `GET /read-image-preview/resolve?path=…&cwd=…` → JSON 描述 + 能力 URL
|
|
52
|
+
- `GET /read-image-preview/<token>` → 图片字节,供 `<img src>` 使用
|
|
53
|
+
|
|
54
|
+
安全边界:只放行 PNG / JPEG / WebP / GIF 四种位图,且 `Content-Type` 用的是**嗅探结果而非扩展名**,所以 SVG / HTML 永远不会被协商成脚本;URL 里带的是不透明 token 而非路径,页面无法让宿主读取任意路径。两条路由都是插件私有前缀上的普通 HTTP,**不向 Cordis 服务命名空间发布任何东西**,不会和别的插件撞名。
|
|
55
|
+
|
|
56
|
+
## 安装
|
|
57
|
+
|
|
58
|
+
```sh
|
|
59
|
+
dsh plugin --profile web add <本包路径或 tgz>
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
包内的 `cordis.patch.yml` 通过 `dsh.bundle.patch` 自 wiring(安装即注册),不需要手改 profile 的 `cordis.patch.yml`。装完**重启 profile**,然后随便让模型 `read_image` 一张图即可看到。
|
|
63
|
+
|
|
64
|
+
卸载:`dsh plugin --profile web remove dsh-plugin-read-image-preview`。
|