dsh-plugin-image-tools 0.4.0 → 0.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 +14 -25
- package/lib/index.js +30 -2
- package/package.json +2 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Pasumao
|
|
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
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
# dsh-plugin-image-tools
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+

|
|
4
|
+

|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
**dsh 插件市场里唯一支持「图片选择卡」的插件**:给 DeepSeek Harness Web GUI 增加图片能力,
|
|
8
|
+
三个工具覆盖三种场景——模型让你在选项里挑图、在回复正文里展示图、你把图发给盲模型。全部零 token 本地渲染:
|
|
4
9
|
|
|
5
10
|
| 工具 | 场景 | 效果 |
|
|
6
11
|
|---|---|---|
|
|
@@ -88,33 +93,17 @@ cordis.patch.yml bundle 补丁(挂载行)
|
|
|
88
93
|
docs/ 效果图(README 展示用)
|
|
89
94
|
```
|
|
90
95
|
|
|
91
|
-
##
|
|
96
|
+
## 安装
|
|
92
97
|
|
|
93
98
|
```powershell
|
|
94
|
-
#
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
# 2. 重启 dsh(launcher),然后刷新浏览器页面
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
profile 的 `package.json` 需要包含:
|
|
102
|
-
|
|
103
|
-
```jsonc
|
|
104
|
-
{
|
|
105
|
-
"dependencies": {
|
|
106
|
-
"dsh-plugin-image-tools": "link:D:/dsh/plugins/dsh-plugin-image-tools"
|
|
107
|
-
},
|
|
108
|
-
"dsh": {
|
|
109
|
-
"profile": {
|
|
110
|
-
"bundles": [ /* ... */, "dsh-plugin-image-tools" ]
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
}
|
|
99
|
+
# npm(推荐)
|
|
100
|
+
dsh plugin --profile web add dsh-plugin-image-tools
|
|
101
|
+
# 或 GitHub
|
|
102
|
+
dsh plugin --profile web add github:Pasumao/dsh-plugin-image-tools
|
|
114
103
|
```
|
|
115
104
|
|
|
116
|
-
|
|
117
|
-
|
|
105
|
+
装完重启 dsh(launcher),然后刷新浏览器页面。包自带 `cordis.patch.yml` 挂载行,
|
|
106
|
+
经 `dsh.profile.bundles` 自动应用(与 dsh-notify 同机制),无需手动改配置。
|
|
118
107
|
|
|
119
108
|
## 模型用法示例
|
|
120
109
|
|
|
@@ -176,4 +165,4 @@ profile 的 `package.json` 需要包含:
|
|
|
176
165
|
|
|
177
166
|
## 许可证
|
|
178
167
|
|
|
179
|
-
MIT
|
|
168
|
+
[MIT](./LICENSE)
|
package/lib/index.js
CHANGED
|
@@ -462,12 +462,35 @@ export function choiceTool(ctx, opts = {}) {
|
|
|
462
462
|
const now = Date.now()
|
|
463
463
|
prunePicks(now)
|
|
464
464
|
|
|
465
|
+
// 与浏览器端 askUserQuestionItemSchema(muxFrameSchema)对齐的必填/类型校验:
|
|
466
|
+
// 模型偶发漏传 question 等必填字段时,若原样转发,浏览器 zod 解析会把
|
|
467
|
+
// question/requested 整帧丢弃,选择卡静默不渲染(用户只见"图呢,看不到啊",
|
|
468
|
+
// 最终 ASK_ABORTED)。这里在服务端提前校验并抛面向模型的错误,让模型自我修正。
|
|
469
|
+
const questions = Array.isArray(args.questions) ? args.questions : []
|
|
470
|
+
for (let qi = 0; qi < questions.length; qi++) {
|
|
471
|
+
const q = questions[qi]
|
|
472
|
+
if (q === null || typeof q !== 'object') throw new Error(`questions[${qi}] 必须是对象`)
|
|
473
|
+
if (typeof q.id !== 'string' || q.id === '') throw new Error(`questions[${qi}].id 缺失或不是非空字符串(必填,稳定问题 id,随答案原样回传)`)
|
|
474
|
+
if (typeof q.question !== 'string' || q.question === '') throw new Error(`questions[${qi}].question 缺失或不是非空字符串(必填,用户看到的问题文本;请补上后重新调用 ask_user_choice)`)
|
|
475
|
+
if (q.header !== undefined && typeof q.header !== 'string') throw new Error(`questions[${qi}].header 必须是字符串`)
|
|
476
|
+
if (q.detail !== undefined && typeof q.detail !== 'string') throw new Error(`questions[${qi}].detail 必须是字符串`)
|
|
477
|
+
if (q.multi_select !== undefined && typeof q.multi_select !== 'boolean') throw new Error(`questions[${qi}].multi_select 必须是布尔值`)
|
|
478
|
+
const options = Array.isArray(q.options) ? q.options : []
|
|
479
|
+
for (let oi = 0; oi < options.length; oi++) {
|
|
480
|
+
const o = options[oi]
|
|
481
|
+
if (o === null || typeof o !== 'object') throw new Error(`questions[${qi}].options[${oi}] 必须是对象`)
|
|
482
|
+
if (typeof o.label !== 'string' || o.label === '') throw new Error(`questions[${qi}].options[${oi}].label 缺失或不是非空字符串(必填,选项文字/答案值)`)
|
|
483
|
+
if (o.description !== undefined && typeof o.description !== 'string') throw new Error(`questions[${qi}].options[${oi}].description 必须是字符串`)
|
|
484
|
+
if (o.image !== undefined && o.image !== null && (typeof o.image !== 'object' || o.image === null)) throw new Error(`questions[${qi}].options[${oi}].image 必须是对象(path / url / data 三选一)`)
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
|
|
465
488
|
// 本次 ask 创建的 pickId,无论成功/失败/中止都统一释放(含中途加载报错)。
|
|
466
489
|
const batches = []
|
|
467
490
|
try {
|
|
468
491
|
// 1) 逐题归一化图片,生成带图问题的 pickId 与标记。
|
|
469
492
|
const askQuestions = []
|
|
470
|
-
for (const question of
|
|
493
|
+
for (const question of questions) {
|
|
471
494
|
const options = Array.isArray(question.options) ? question.options : []
|
|
472
495
|
const imageIndexes = []
|
|
473
496
|
const normalized = []
|
|
@@ -485,7 +508,12 @@ export function choiceTool(ctx, opts = {}) {
|
|
|
485
508
|
let detail = typeof question.detail === 'string' ? question.detail : ''
|
|
486
509
|
if (imageIndexes.length > 0) {
|
|
487
510
|
const pickId = randomUUID()
|
|
488
|
-
|
|
511
|
+
// 按原始选项下标存图片(无图选项留空),保证客户端
|
|
512
|
+
// `/pickId/<原始下标>` 的 URL 与服务端索引一一对应;
|
|
513
|
+
// 紧凑数组会让带图选项下标不连续时错位/404。
|
|
514
|
+
const images = new Array(options.length).fill(undefined)
|
|
515
|
+
for (const index of imageIndexes) images[index] = normalized[index].image
|
|
516
|
+
picks.set(pickId, { createdAt: now, images })
|
|
489
517
|
batches.push(pickId)
|
|
490
518
|
detail = buildPickMarker(pickId, imageIndexes) + detail
|
|
491
519
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-plugin-image-tools",
|
|
3
3
|
"description": "DSH 图片插件:ask_user_choice 图片/图文混合选项(Web GUI 渲染图片选择卡,可放大查看)+ show_images 在回复中内嵌图片(图片与文字混排)。图片来源支持本地路径 / http(s) URL / base64 data URI。纯插件实现,不改核心包。",
|
|
4
|
-
"version": "0.4.
|
|
4
|
+
"version": "0.4.1",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"exports": {
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"docs",
|
|
16
16
|
"cordis.patch.yml",
|
|
17
17
|
"README.md",
|
|
18
|
+
"LICENSE",
|
|
18
19
|
"设计说明.md"
|
|
19
20
|
],
|
|
20
21
|
"scripts": {
|