DeepSeek Harness Hub
← 返回列表

图像生成工具Pappet/dsh-tool-imagegen

DeepSeek Harnessspec-screened在 GitHub 查看 ↗
未验证

用提示词或参考图生成图片并返回费用

尚未跑自动兼容性验证,可查看页面内的依赖与入口分析。 · 最近上游提交 2026/9/1 · 已提供中文文档

通过 OpenRouter 的统一 Image API 为 DeepSeek Harness 实现文本到图像和图像到图像生成,并带有能力门控参数

综合分
29.1
GitHub 分
29.1
用户评分
★ Stars
1
周下载量
安装插件(需先安装 dsh CLI 引擎:npm install -g @deepseek-ai/dsh)
dsh plugin --profile web add Pappet/dsh-tool-imagegen
该插件未发布到 npm,走 GitHub 源安装(pnpm 若拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑)
数据截至 2026/9/16(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/dsh-attachment@deepseek-ai/dsh-credentials@deepseek-ai/dsh-llm@deepseek-ai/dsh-tools@deepseek-ai/schemastery
用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动

README

dsh-tool-imagegen

CI
License: MIT
node

通过 OpenRouter 的统一 Image API(POST /api/v1/images —— 而非 兼容 OpenAI 的 /images/generations)为 DeepSeek Harness 提供图像生成能力。

只有一个工具,generate_image:它接收一个提示词,可选地接收若干参考图像,将结果写入工作区并返回路径和确切费用。生成的图像会内联显示在聊天中。

- 模型即别名。 别名既是模型使用的词汇,也是 允许列表 —— 没有别名的模型无法访问。
- 参数根据模型的能力记录进行校验(GET /api/v1/images/models),而非硬编码。如果调用请求了模型无法做到的事情,会失败并给出指明参数和模型的消息。
- 图生图 通过 input_references 实现:工作区路径或 URL,上限取决于模型接受的量(Seedream 为 14,GPT-Image 系列为 16)。
- 运行时可变。 Plugins 设置部分中的卡片可编辑别名和可调参数;更改实时生效,无需重启。

安装

dsh plugin --profile web add dsh-tool-imagegen

这会将包安装到配置文件中,并将其列在 dsh.profile.bundles 下;随附的 bundle 补丁会插入插件行。然后给它一个密钥。apiKeyEnv 指定的是凭据引用,绝不是密钥本身:

export OPENROUTER_API_KEY=sk-or-...

或者,更推荐的做法是将其放在 $DSH_HOME/.credentials.yaml 中的 refs.OPENROUTER_API_KEY 下。凭据接缝会首先尝试,同名的环境变量其次 —— 与 llm-pi-ai 和 dsh-github 相同的约定。该值永远不会进入配置、日志或模型可见的文本。

该插件不附带任何模型别名;请参阅配置。

工具:generate_image

| 参数 | 类型 | 说明 |
|---|---|---|
| prompt | string,必填 | 要描绘的内容。 |
| model | string | 已配置的别名;默认为 defaultModel。 |
| resolution | string | 例如 1K \| 2K \| 4K —— 取决于模型。 |
| aspect_ratio | string | 例如 1:1、16:9 —— 取决于模型。 |
| n | integer | 图像数量(默认 1,最多为 maxImagesPerCall)。 |
| seed | integer | 当模型支持时可用。 |
| output_format | string | 例如 png \| jpeg —— 大多数模型自行决定编码方式,不列出描述符。 |
| input_references | string[] | 用于编辑或变化的参考图像:工作区路径或 http(s) URL。 |
| output_path | string | 第一张图像的目标路径,绝对路径或相对于工作区。扩展名跟随返回的编码。 |
返回值携带 model、alias、images[](path、mediaType、
bytes)、costUsd(精确值,来自 API 的 usage.cost)、applied——即
实际发送的参数——以及 droppedDefaults。applied 让模型能够看到实际
使用了什么,例如在门控丢弃了某个配置默认值之后,并据此调整下一次尝试。

output_path 指定文件名,但由模型决定编码。一次调用请求 bild.png,
而模型输出 JPEG,就会得到 bild.jpg:文件绝不能对其内容撒谎。

能力门控

supported_parameters 使用带类型的描述符(enum、range、boolean);
某个键缺失意味着该参数不受支持。每个参数的解析顺序:
调用参数 → 别名 defaults → 省略。两类错误,刻意区别对待:

| 来源 | 参数不受支持 | 值超出描述符范围 |
|---|---|---|
| 在调用中指定 | 错误,指明参数和模型 | 错误,列出允许的值 |
| 配置 defaults | 静默丢弃(在 droppedDefaults 中报告) | 错误,归因于配置 |

默认值是愿望,不是承诺。显式的调用参数是模型在请求某个具体的东西,
因此绝不会被静默忽略。

缓存保存 /images/models 列表,时长为 capabilityTtlMs(默认
24 小时),并在遇到 400 时失效一次,然后重新门控并重试一次——因此
过期的记录会自我修复,而无需为每张图片额外往返一次。

记录并非最终定论:Seedream 4.5 将 1K 列为有效的 resolution,
但在调用时拒绝它(“requires at least 3,686,400 output pixels”)。
门控转发记录所允许的内容;API 自身的错误文本会原样传递。

图生图

{
"prompt": "Turn this into a soft watercolor painting, same composition.",
"input_references": ["bilder/vorlage.png", "https://example.com/style.jpg"]
}

每个值要么是 http(s) URL,原样传递,要么是路径(绝对路径或相对于
工作区的路径,像 output_path 一样相对于会话 cwd 解析)。路径会被
读取、限制大小、通过其魔数字节识别,并以内联 base64 data URL 的
形式嵌入。文件名从不被参考:名字可能对其编码撒谎——这个插件曾经
把 JPEG 载荷写在 .png 名称下——而一个被错误标记的 data URL 会在
提供商处失败,其错误指向的位置与真正原因相去甚远。

applied.input_references 回显调用所指定的内容,而绝不是载荷。

能力描述符是对数量的范围约束,而不是对某个值的约束:

"input_references": { "type": "range", "min": 0, "max": 14 }

因此它有自己的门控,并与其他所有内容一样具有相同的两类错误。
只有在门控通过之后才会读取文件:对不具备该能力的模型的调用绝不会
触碰磁盘。

上限为 maxReferenceBytes(每个文件)和 maxReferenceTotalBytes
(全部合计),两者均以磁盘上的字节数为准;base64 在传输时会增加大约
三分之一。
支持情况因模型而异。Seedream 4.5 / 5.0 最多接受 14 个引用,但
未列出 output_format;GPT-Image 系列接受 16 个,并额外支持 quality、
background 和 output_compression;Recraft 矢量模型仅输出 svg,
且部分模型要求至少一个引用(min: 1)。

配置

默认不附带任何别名,因此在你至少命名一个别名之前,该插件不会执行任何操作。将配置覆盖写入你的 profile 的 cordis.patch.yml:

- id: imagegen
config:
apiKeyEnv: OPENROUTER_API_KEY      # 凭据引用 / 环境变量名称,切勿填入密钥本身
baseURL: https://openrouter.ai/api/v1
outputDir: .dsh/images             # 相对于工作区
defaultModel: seedream
capabilityTtlMs: 86400000          # 24 小时
maxImagesPerCall: 4                # 防止模型幻觉出的 n
maxReferenceBytes: 8388608         # 每张引用图像(磁盘上 8 MiB)
maxReferenceTotalBytes: 33554432   # 单次调用的所有引用(32 MiB)
showInChat: true
models:
seedream:
id: bytedance-seed/seedream-4.5
defaults: { resolution: "2K", aspect_ratio: "16:9" }
seedream-pro:
id: bytedance-seed/seedream-5-0-pro
seedream-lite:
id: bytedance-seed/seedream-5-0-lite

配置覆盖会整体替换该行的配置——它绝不会进行
深度合并——因此所有重要的键都必须重复写出。你省略的键会回退到
其 schema 默认值,而不是 bundle patch 中的值。

已对照 GET /api/v1/images/models 验证 slug:Seedream 5.0 模型
为 seedream-5-0-pro / seedream-5-0-lite(使用连字符,而非点号),且 5.0-pro
仅接受 n ≤ 1 以及分辨率 1K|2K。slug 错误的别名
会表现为携带 API 响应正文的 HTTP 错误。

设置卡片

该插件注册了设置命名空间 dsh-tool-imagegen,浏览器端
在插件设置区域贡献了一张卡片:别名
表(别名、slug、以 JSON 表示的默认值)以及标量可调项。两个字节
上限以 MiB 输入;文档中保留字节。

配置与卡片是分层关系,而非二选一:

schema 默认值  →  基础层(此插件的 cordis 配置)  →  用户层(卡片)

因此 cordis.yml 仍是部署的既定意图,卡片编辑是在其之上的
覆盖,而重置会回退到恰好配置的值,
而不是无人选择的 schema 默认值。更改实时生效。

别名注册表在设置层中是一个列表,尽管配置
使用的是字典。这并非表面功夫:各层会递归合并普通对象,
并整体替换数组,因此用户层中的字典永远无法删除配置声明的
别名——被移除的行会静默地重新继承。作为列表,
卡片写入的就是整个注册表。

apiKeyEnv、baseURL 和 capabilityTtlMs 仅保留在配置中:它们是
部署决策,而能力缓存由后两者构建
在应用时只执行一次,因此实时编辑无法生效。

在没有设置服务(无头部署)的情况下,该工具会基于已配置的值运行——不可配置,但能正常工作。

在聊天中

启用 showInChat(默认 true)时,每张生成的图像都会提交到持久化附件存储,并且 execute 会延迟发送一条来自插件的消息,以便模型也能看到图片——这对迭代很有用;纯文本适配器会替换为其文本占位符。

阅读者看到的是工具卡片:lib/client.js 为 generate_image 注册了带键的 tool.call.toolview,并内联渲染图像,通过 session.readAttachment 从结果元数据中的持久化引用加载。点击会通过 Host 打开器打开该文件。

延迟消息会作为上下文注入行而不是历史画廊中的条目落地——来源不是 user 的消息会被归类为注入的上下文——因此它声明 notice 形式以及一行摘要,折叠后的行显示为 Image created: /path/to/file.jpg。

每一步都是隔离的:附件存储故障绝不会导致原本成功的生成失败,且不可附加的媒体(SVG)会被跳过。

所有面向用户的文案均为英文,旁边配有简体中文词典,并通过 harness 语言环境服务注册——UI 提供中文和 English,因此卡片会跟随所选语言。

策略边界

此插件中不包含任何权限逻辑。允许/拒绝/询问属于 tools/pre-execute 监听器,最终拒绝属于 ctx.tools.guard(),成本上限属于单独的 hook 插件。maxImagesPerCall 是针对幻觉产生的 n 的合理性防护,而不是预算控制。

开发

npm install          # prepare 构建;测试导入编译后的输出
npm run build        # tsc → lib/
npm test             # node:test,离线:宿主部分 + jsdom 中的浏览器部分
npm run typecheck    # tsc --noEmit

测试从不访问网络:fetch 被伪造,文件落在临时目录中,浏览器部分在 jsdom 中挂载并点击——展开、输入、保存——因为没有其他东西会查看该文件(tsc 忽略它,而 node --check 只能证明它能解析)。

@deepseek-ai/* 包是对等依赖:harness 在运行时提供它们,而身份敏感契约的第二份副本会遮蔽宿主的那一份。

对于实时安装,将检出目录链接到 dsh profile 中(dsh plugin add);在 npm run build 之后,重启 profile 会重新加载两部分。

applyWithDeps(ctx, config, { fetchImpl, workspaceRoot, attachments, settings }) 是测试使用的可注入入口点;apply(ctx, config) 是 harness 加载的内容。

布局

src/
index.ts         # apply()、工具注册、呈现器、execute 流程
config.ts        # cordis 入口配置的 Schemastery schema
settings.ts      # 配置卡片背后的设置命名空间
capabilities.ts  # 能力缓存 + 参数门控
openrouter.ts    # HTTP 客户端:/images、/images/models   (无 DSH 导入)
references.ts    # 参考图像 → data URL           (无 DSH 导入)
write.ts         # base64 → 文件、命名、冲突处理      (无 DSH 导入)
chat.ts          # 附件存储 + 延迟消息
key.ts           # 凭据解析
lib/client.js      # 浏览器部分:工具卡片 + 设置卡片(手写,无构建步骤)
test/
imagegen.test.mjs  # 宿主部分
client.test.mjs    # 浏览器部分,在 jsdom 中

许可证

MIT — 参见 LICENSE。

上游仓库有新提交时邮件通知你(每天最多一封,无更新不打扰),随时一键退订。

💬 加入 DPharness 群聊

插件用法、部署报错、新插件第一时间同步——群里问,比一个人翻文档快。

点击加入 QQ 群
DPharness 群聊二维码,手机 QQ 扫码进群
扫码进群