dsh-image-gen 0.1.0 → 0.1.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/README.en.md ADDED
@@ -0,0 +1,158 @@
1
+ <div align="center">
2
+
3
+ # 🎨 dsh-image-gen
4
+
5
+ ### Native Image Generation Plugin for DeepSeek Harness (DSH)
6
+
7
+ **Bring ChatGPT-like image generation into DeepSeek Harness conversation flows.**
8
+
9
+ Supports Google Gemini, OpenAI Images, OpenAI Compatible APIs, ByteDance Seedream / Volcengine Ark.
10
+
11
+ [![npm version](https://img.shields.io/npm/v/dsh-image-gen.svg?style=flat-square&color=blue)](https://www.npmjs.com/package/dsh-image-gen)
12
+ [![DSH Plugin](https://img.shields.io/badge/Plugin%20For-DeepSeek%20Harness-6366f1?style=flat-square)](https://github.com/deepseek-ai)
13
+ [![npm downloads](https://img.shields.io/npm/dm/dsh-image-gen.svg?style=flat-square&color=emerald)](https://www.npmjs.com/package/dsh-image-gen)
14
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square)](LICENSE)
15
+
16
+ **English** | [简体中文](README.md)
17
+
18
+ <br />
19
+
20
+ <p align="center">💬 <b>Just prompt your DeepSeek Harness Agent:</b></p>
21
+
22
+ ```text
23
+ Install the image generation plugin by running: pnpm dsh plugin --profile web add dsh-image-gen
24
+ ```
25
+
26
+ <p align="center"><sub>(Or run manually in terminal: <code>pnpm dsh plugin --profile web add dsh-image-gen</code>)</sub></p>
27
+
28
+ <br />
29
+
30
+ <p align="center">Once installed, configure your API Key in DSH Settings and prompt your Agent:</p>
31
+
32
+ ```text
33
+ Create an illustration of a cyberpunk cat in a neon rainy street.
34
+ ```
35
+
36
+ <p align="center">The Agent will automatically invoke <code>generate_image</code> and render the generated image directly in the conversation flow.</p>
37
+
38
+ <br />
39
+
40
+ <img src="docs/assets/chat-preview.png" alt="Conversational image generation preview" width="820" />
41
+
42
+ </div>
43
+
44
+ ---
45
+
46
+ ## 💡 What Problem Does It Solve?
47
+
48
+ **`dsh-image-gen` is an open-source multimodal image generation bundle built specifically for DeepSeek Harness (DSH).**
49
+
50
+ DeepSeek Harness already lets Agents dispatch tools to accomplish complex tasks; this plugin equips DSH with native **multimodal image generation capabilities**:
51
+
52
+ ```mermaid
53
+ graph LR
54
+ A[User Prompt] --> B[DeepSeek Harness Agent]
55
+ B --> C[generate_image Tool]
56
+ C --> D[Gemini / OpenAI / Seedream]
57
+ D --> E[Image Payload]
58
+ E --> F[Conversation Stream]
59
+ ```
60
+
61
+ ---
62
+
63
+ ## 🚀 Quick Start
64
+
65
+ ### 1. Install Plugin
66
+
67
+ Run the following command in your DeepSeek Harness workspace root:
68
+
69
+ ```bash
70
+ # Recommended: Install and register plugin via pnpm
71
+ pnpm dsh plugin --profile web add dsh-image-gen
72
+
73
+ # If dsh is installed globally:
74
+ dsh plugin --profile web add dsh-image-gen
75
+ ```
76
+
77
+ <details>
78
+ <summary><b>🛠️ Advanced Installation (Git Repository / Local Dev)</b></summary>
79
+
80
+ ```bash
81
+ # Option B: Direct install from GitHub repo
82
+ pnpm dsh plugin --profile web add git+https://github.com/shanliuling/dsh-image-gen.git
83
+
84
+ # Option C: Local clone for development
85
+ git clone https://github.com/shanliuling/dsh-image-gen.git
86
+ pnpm dsh plugin --profile web add ./dsh-image-gen
87
+ ```
88
+
89
+ </details>
90
+
91
+ ### 2. Configure API Key
92
+
93
+ Open DSH Web UI (default `http://localhost:3080`):
94
+
95
+ 1. Go to **Settings → Plugins → Image generation**.
96
+ 2. Select your Provider, enter your API Key, and click **Save**.
97
+
98
+ <div align="center">
99
+ <img src="docs/assets/settings-preview.png" alt="Settings Card Preview" width="720" />
100
+ </div>
101
+
102
+ ### 3. Start Generating Images in Chat
103
+
104
+ Simply prompt in the chat input:
105
+
106
+ ```text
107
+ Generate a minimalist illustration of a modern architectural living room.
108
+ ```
109
+
110
+ The Agent will automatically invoke `generate_image` and render the result in the conversation.
111
+
112
+ ---
113
+
114
+ ## ✨ Key Features
115
+
116
+ - 💬 **In-Conversation Image Generation**: No need to switch between external websites or manually copy prompts; ask your Agent naturally.
117
+ - 🎨 **Multi-Provider Support**: Out-of-the-box support for Google Gemini, OpenAI Images, OpenAI Compatible APIs (OneAPI, NewAPI), and ByteDance Seedream / Volcengine Ark. Models and endpoints can be customized directly in the settings UI.
118
+ - 🔑 **BYOK (Bring Your Own Key)**: Uses your own API credentials securely managed through DSH's write-isolated `credentials` service. Keys are never saved in plain text on the frontend.
119
+ - 🖼️ **Durable Session Attachments**: Images are attached to DSH's native Attachment / Conversation system and remain visible when returning to historical sessions.
120
+ - ⚙️ **Native Settings UI**: Change providers, API keys, models, and endpoints directly inside the DSH Web UI without manual config file editing.
121
+
122
+ ---
123
+
124
+ ## 📦 Supported Providers
125
+
126
+ | Provider | Default Model | Default Endpoint / Base URL |
127
+ | :--- | :--- | :--- |
128
+ | **Google Gemini** | `gemini-3.1-flash-image` | `https://generativelanguage.googleapis.com/v1beta/interactions` |
129
+ | **OpenAI Images** | `gpt-image-2` | `https://api.openai.com/v1` |
130
+ | **OpenAI Compatible** | Custom | Custom Base URL |
131
+ | **ByteDance Seedream / Volcengine** | `doubao-seedream-5-0-260128` | `https://ark.cn-beijing.volces.com/api/v3` |
132
+
133
+ ---
134
+
135
+ ## 🛠️ Development
136
+
137
+ ```bash
138
+ # Clone repository
139
+ git clone https://github.com/shanliuling/dsh-image-gen.git
140
+ cd dsh-image-gen
141
+
142
+ # Install dependencies and build
143
+ pnpm install
144
+ pnpm run typecheck
145
+ pnpm run test
146
+ pnpm run build
147
+
148
+ # Check package payload
149
+ pnpm run pack:check
150
+ ```
151
+
152
+ ---
153
+
154
+ ## 📄 License
155
+
156
+ This project is licensed under the [MIT License](LICENSE).
157
+
158
+ If this plugin helps you, consider giving it a ⭐️ **Star**!
package/README.md CHANGED
@@ -1,85 +1,158 @@
1
- # dsh-image-gen
1
+ <div align="center">
2
2
 
3
- English | [简体中文](README.zh-CN.md)
3
+ # 🎨 dsh-image-gen
4
4
 
5
- `dsh-image-gen` is an installable DeepSeek Harness (DSH) Bundle that contributes a native `generate_image` tool and renders durable image result cards directly in Web conversations.
5
+ ### DeepSeek Harness (DSH) 原生生图插件
6
6
 
7
- ![Chat Preview](docs/assets/chat-preview.png)
7
+ **让 DeepSeek Harness 像 ChatGPT 一样,在对话里直接生成图片。**
8
8
 
9
- ---
9
+ 支持 Google Gemini、OpenAI Images、OpenAI Compatible API、字节 Seedream / 火山方舟。
10
+
11
+ [![npm version](https://img.shields.io/npm/v/dsh-image-gen.svg?style=flat-square&color=blue)](https://www.npmjs.com/package/dsh-image-gen)
12
+ [![DSH Plugin](https://img.shields.io/badge/Plugin%20For-DeepSeek%20Harness-6366f1?style=flat-square)](https://github.com/deepseek-ai)
13
+ [![npm downloads](https://img.shields.io/npm/dm/dsh-image-gen.svg?style=flat-square&color=emerald)](https://www.npmjs.com/package/dsh-image-gen)
14
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square)](LICENSE)
15
+
16
+ [English](README.en.md) | **简体中文**
17
+
18
+ <br />
19
+
20
+ <p align="center">💬 <b>直接对你的 DeepSeek Harness Agent 发送以下提示词:</b></p>
10
21
 
11
- ## ✨ Features
22
+ ```text
23
+ 帮我安装生图插件,执行命令:pnpm dsh plugin --profile web add dsh-image-gen
24
+ ```
25
+
26
+ <p align="center"><sub>(也可以手动在终端执行:<code>pnpm dsh plugin --profile web add dsh-image-gen</code>)</sub></p>
27
+
28
+ <br />
12
29
 
13
- - **Multi-Provider Support**: Seamless integration with **Google Gemini**, **OpenAI / OpenAI-compatible relays**, and **ByteDance Seedream (Volcengine Ark)**.
14
- - **Secure Credential Management**: Write-only API Key storage powered by DSH `credentials` service. Keys are never logged or exposed in plaintext.
15
- - **Web Settings Integration**: Built-in settings card in DSH Settings with auto-filled defaults and one-click endpoint reset.
16
- - **Durable Media Persistence**: Generated images are automatically saved to DSH conversation attachment storage and rendered in rich UI cards.
30
+ <p align="center">安装完成后,在 DSH 设置中填入自己的 API Key,就可以直接对 Agent 说:</p>
31
+
32
+ ```text
33
+ 帮我画一张雨夜霓虹街头的赛博朋克猫咪。
34
+ ```
17
35
 
18
- ![Settings Preview](docs/assets/settings-preview.png)
36
+ <p align="center">Agent 会自动调用 <code>generate_image</code>,生成图片并直接显示在当前对话中。</p>
37
+
38
+ <br />
39
+
40
+ <img src="docs/assets/chat-preview.png" alt="对话生图效果预览" width="820" />
41
+
42
+ </div>
19
43
 
20
44
  ---
21
45
 
22
- ## 📦 Supported Providers
46
+ ## 💡 它解决什么问题?
23
47
 
24
- | Provider | Credential Key | Default Model | Default Endpoint / Base URL | Note |
25
- | :--- | :--- | :--- | :--- | :--- |
26
- | **Google Gemini** | `GEMINI_API_KEY` | `gemini-3.1-flash-image` | `https://generativelanguage.googleapis.com/v1beta/interactions` | Native Gemini Interactions API |
27
- | **OpenAI / Relay** | `OPENAI_API_KEY` | `gpt-image-2` | `https://api.openai.com/v1` | Standard OpenAI / OneAPI / NewAPI |
28
- | **ByteDance Seedream** | `ARK_API_KEY` | `doubao-seedream-5-0-260128` | `https://ark.cn-beijing.volces.com/api/v3` | Volcengine Ark Doubao T2I |
48
+ **`dsh-image-gen` 是专为 DeepSeek Harness (DSH) 打造的开源图像生成插件。**
49
+
50
+ DeepSeek Harness 已经可以让 Agent 调用不同工具完成任务,本项目为它补上了原生的**多模态生图能力**:
51
+
52
+ ```mermaid
53
+ graph LR
54
+ A[用户 Prompt] --> B[DeepSeek Harness Agent]
55
+ B --> C[generate_image 工具]
56
+ C --> D[Gemini / OpenAI / Seedream]
57
+ D --> E[图片数据]
58
+ E --> F[当前 Conversation 对话流]
59
+ ```
29
60
 
30
61
  ---
31
62
 
32
- ## 🚀 Installation & Usage
63
+ ## 🚀 快速安装与使用
33
64
 
34
- ### 1. Install Plugin
65
+ ### 1. 安装插件
35
66
 
36
- In your DeepSeek Harness workspace, add the plugin to your profile (default `web`):
67
+ 在你的 DeepSeek Harness 项目根目录下运行:
37
68
 
38
69
  ```bash
39
- # Install via npm (when published)
70
+ # 推荐方式:通过 pnpm 一键安装并注册插件
71
+ pnpm dsh plugin --profile web add dsh-image-gen
72
+
73
+ # 若已将 dsh 安装为系统全局命令:
40
74
  dsh plugin --profile web add dsh-image-gen
75
+ ```
76
+
77
+ <details>
78
+ <summary><b>🛠️ 其他安装方式(Git 仓库直装 / 本地调试)</b></summary>
41
79
 
42
- # Or install from local path (development)
43
- dsh plugin --profile web add /path/to/dsh-image-gen
80
+ ```bash
81
+ # 方式 B:从 GitHub 仓库直接安装最新代码
82
+ pnpm dsh plugin --profile web add git+https://github.com/shanliuling/dsh-image-gen.git
83
+
84
+ # 方式 C:本地克隆源码开发安装
85
+ git clone https://github.com/shanliuling/dsh-image-gen.git
86
+ pnpm dsh plugin --profile web add ./dsh-image-gen
44
87
  ```
45
88
 
46
- ### 2. Configure in Web UI
89
+ </details>
90
+
91
+ ### 2. 配置 API Key
92
+
93
+ 打开 DSH Web 页面(默认 `http://localhost:3080`):
94
+
95
+ 1. 进入 **Settings → Plugins → Image generation**。
96
+ 2. 选择 Provider,填写 API Key,点击 **保存** 即可。
47
97
 
48
- 1. Open DSH Web UI (e.g. `http://localhost:3080`).
49
- 2. Navigate to **Settings → Plugins → Image generation (图像生成)**.
50
- 3. Select your provider, enter the API Key, verify or customize endpoint / model, and click **Save**.
98
+ <div align="center">
99
+ <img src="docs/assets/settings-preview.png" alt="设置面板预览" width="720" />
100
+ </div>
51
101
 
52
- ### 3. Generate Images
102
+ ### 3. 开始对话生图
53
103
 
54
- Start a conversation and ask the agent naturally:
55
- > *"Generate a realistic picture of a Holstein cow in a green meadow with wildflowers under golden sunlight."*
104
+ 现在直接在聊天框输入:
56
105
 
57
- The model will automatically invoke `generate_image`, fetch the image, and render it inline.
106
+ ```text
107
+ 生成一张极简主义的现代建筑客厅插画。
108
+ ```
109
+
110
+ 当前 Agent 就会自动调用 `generate_image` 工具并在对话流中返回图片。
58
111
 
59
112
  ---
60
113
 
61
- ## 🛠️ Development
114
+ ## ✨ 主要能力
115
+
116
+ - 💬 **对话中直接生图**:不需要切换到其他网站,也不需要手动复制 Prompt,直接告诉 Agent 你想画什么即可。
117
+ - 🎨 **多 Provider 支持**:目前支持 Google Gemini、OpenAI Images、OpenAI Compatible API 以及 ByteDance Seedream / Volcengine Ark。Provider、模型和 Endpoint 都可以在设置界面中自由修改。
118
+ - 🔑 **BYOK (自带 Key)**:插件使用你自己的 API Key。API Key 通过 DeepSeek Harness 的 `credentials` 服务管理,采用写保护隔离,不需要写进项目源码或配置文件,前端不存明文。
119
+ - 🖼️ **图片跟随会话保存**:生成结果会接入 DeepSeek Harness 的 Attachment / Conversation 体系,重新打开历史会话后,仍然可以看到之前生成的图片。
120
+ - ⚙️ **原生设置界面**:Provider、API Key、模型和 Endpoint 都可以直接在 DSH Web 设置中修改,不需要手动编辑配置文件。
121
+
122
+ ---
123
+
124
+ ## 📦 支持的 Provider
125
+
126
+ | Provider | 默认模型 | 默认 Endpoint / Base URL |
127
+ | :--- | :--- | :--- |
128
+ | **Google Gemini** | `gemini-3.1-flash-image` | `https://generativelanguage.googleapis.com/v1beta/interactions` |
129
+ | **OpenAI Images** | `gpt-image-2` | `https://api.openai.com/v1` |
130
+ | **OpenAI Compatible** | 自定义 | 自定义 Base URL |
131
+ | **ByteDance Seedream / 火山方舟** | `doubao-seedream-5-0-260128` | `https://ark.cn-beijing.volces.com/api/v3` |
132
+
133
+ ---
134
+
135
+ ## 🛠️ 本地开发 (Development)
62
136
 
63
137
  ```bash
64
- # Install dependencies
65
- pnpm install
138
+ # 克隆仓库
139
+ git clone https://github.com/shanliuling/dsh-image-gen.git
140
+ cd dsh-image-gen
66
141
 
67
- # Typecheck
142
+ # 安装依赖与构建
143
+ pnpm install
68
144
  pnpm run typecheck
69
-
70
- # Run unit tests
71
145
  pnpm run test
72
-
73
- # Build host and client bundles
74
146
  pnpm run build
75
147
 
76
- # Verify packaging
148
+ # 检查 npm 打包内容
77
149
  pnpm run pack:check
78
150
  ```
79
151
 
80
152
  ---
81
153
 
82
- ## 📄 License
154
+ ## 📄 开源协议 (License)
83
155
 
84
- [MIT](LICENSE)
156
+ 本项目基于 [MIT License](LICENSE) 开源。
85
157
 
158
+ 如果这个插件对你有用,欢迎点一个 ⭐️ **Star** 支持!
package/README.zh-CN.md CHANGED
@@ -1,85 +1,158 @@
1
- # dsh-image-gen
1
+ <div align="center">
2
2
 
3
- [English](README.md) | 简体中文
3
+ # 🎨 dsh-image-gen
4
4
 
5
- `dsh-image-gen` 是适用于 DeepSeek Harness (DSH) 的多厂商生图 Bundle 插件。它向智能体注册 `generate_image` 工具,并在 Web 对话流中直接持久化渲染高清图片卡片。
5
+ ### DeepSeek Harness (DSH) 原生生图插件
6
6
 
7
- ![对话效果预览](docs/assets/chat-preview.png)
7
+ **让 DeepSeek Harness 像 ChatGPT 一样,在对话里直接生成图片。**
8
8
 
9
- ---
9
+ 支持 Google Gemini、OpenAI Images、OpenAI Compatible API、字节 Seedream / 火山方舟。
10
+
11
+ [![npm version](https://img.shields.io/npm/v/dsh-image-gen.svg?style=flat-square&color=blue)](https://www.npmjs.com/package/dsh-image-gen)
12
+ [![DSH Plugin](https://img.shields.io/badge/Plugin%20For-DeepSeek%20Harness-6366f1?style=flat-square)](https://github.com/deepseek-ai)
13
+ [![npm downloads](https://img.shields.io/npm/dm/dsh-image-gen.svg?style=flat-square&color=emerald)](https://www.npmjs.com/package/dsh-image-gen)
14
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square)](LICENSE)
15
+
16
+ [English](README.en.md) | **简体中文**
17
+
18
+ <br />
19
+
20
+ <p align="center">💬 <b>直接对你的 DeepSeek Harness Agent 发送以下提示词:</b></p>
10
21
 
11
- ## ✨ 核心特性
22
+ ```text
23
+ 帮我安装生图插件,执行命令:pnpm dsh plugin --profile web add dsh-image-gen
24
+ ```
25
+
26
+ <p align="center"><sub>(也可以手动在终端执行:<code>pnpm dsh plugin --profile web add dsh-image-gen</code>)</sub></p>
27
+
28
+ <br />
12
29
 
13
- - **多厂商生态支持**:原生支持 **Google Gemini**、**OpenAI / 兼容中转站 (OneAPI/NewAPI)** 以及 **字节火山方舟 Seedream (豆包绘图)**。
14
- - **安全凭证隔离**:借助 DSH `credentials` 服务实现 API Key 仅写入保护,前端防读取,后端内存透传,杜绝密钥泄露风险。
15
- - **开箱即用设置面板**:无缝集成至 DSH 设置中心,自动带出最新推荐模型与默认地址,支持自定义反代及一键还原官方地址。
16
- - **附件持久化存储**:生成的图片自动入库 DSH 附件体系(Attachment),会话历史完整可溯。
30
+ <p align="center">安装完成后,在 DSH 设置中填入自己的 API Key,就可以直接对 Agent 说:</p>
31
+
32
+ ```text
33
+ 帮我画一张雨夜霓虹街头的赛博朋克猫咪。
34
+ ```
17
35
 
18
- ![设置面板预览](docs/assets/settings-preview.png)
36
+ <p align="center">Agent 会自动调用 <code>generate_image</code>,生成图片并直接显示在当前对话中。</p>
37
+
38
+ <br />
39
+
40
+ <img src="docs/assets/chat-preview.png" alt="对话生图效果预览" width="820" />
41
+
42
+ </div>
19
43
 
20
44
  ---
21
45
 
22
- ## 📦 支持厂商与默认规范
46
+ ## 💡 它解决什么问题?
23
47
 
24
- | 厂商 (Provider) | 凭据环境变量 | 默认模型 | 默认接口地址 (Endpoint / Base URL) | 协议说明 |
25
- | :------------------ | :--------------- | :--------------------------- | :-------------------------------------------------------------- | :----------------------------------- |
26
- | **Google Gemini** | `GEMINI_API_KEY` | `gemini-3.1-flash-image` | `https://generativelanguage.googleapis.com/v1beta/interactions` | Google 原生 Interactions 协议 |
27
- | **OpenAI / 中转站** | `OPENAI_API_KEY` | `gpt-image-2` | `https://api.openai.com/v1` | 标准 OpenAI `/v1/images/generations` |
28
- | **字节 Seedream** | `ARK_API_KEY` | `doubao-seedream-5-0-260128` | `https://ark.cn-beijing.volces.com/api/v3` | 火山方舟豆包文生图标准网关 |
48
+ **`dsh-image-gen` 是专为 DeepSeek Harness (DSH) 打造的开源图像生成插件。**
49
+
50
+ DeepSeek Harness 已经可以让 Agent 调用不同工具完成任务,本项目为它补上了原生的**多模态生图能力**:
51
+
52
+ ```mermaid
53
+ graph LR
54
+ A[用户 Prompt] --> B[DeepSeek Harness Agent]
55
+ B --> C[generate_image 工具]
56
+ C --> D[Gemini / OpenAI / Seedream]
57
+ D --> E[图片数据]
58
+ E --> F[当前 Conversation 对话流]
59
+ ```
29
60
 
30
61
  ---
31
62
 
32
- ## 🚀 安装与使用
63
+ ## 🚀 快速安装与使用
33
64
 
34
65
  ### 1. 安装插件
35
66
 
36
- 在你的 DeepSeek Harness 工作区中安装本插件(以默认 `web` profile 为例):
67
+ 在你的 DeepSeek Harness 项目根目录下运行:
37
68
 
38
69
  ```bash
39
- # 方式 A:npm 安装
70
+ # 推荐方式:通过 pnpm 一键安装并注册插件
71
+ pnpm dsh plugin --profile web add dsh-image-gen
72
+
73
+ # 若已将 dsh 安装为系统全局命令:
40
74
  dsh plugin --profile web add dsh-image-gen
75
+ ```
76
+
77
+ <details>
78
+ <summary><b>🛠️ 其他安装方式(Git 仓库直装 / 本地调试)</b></summary>
41
79
 
42
- # 方式 B:本地开发引入
43
- dsh plugin --profile web add /path/to/dsh-image-gen
80
+ ```bash
81
+ # 方式 B:从 GitHub 仓库直接安装最新代码
82
+ pnpm dsh plugin --profile web add git+https://github.com/shanliuling/dsh-image-gen.git
83
+
84
+ # 方式 C:本地克隆源码开发安装
85
+ git clone https://github.com/shanliuling/dsh-image-gen.git
86
+ pnpm dsh plugin --profile web add ./dsh-image-gen
44
87
  ```
45
88
 
46
- ### 2. 在 Web 界面配置
89
+ </details>
90
+
91
+ ### 2. 配置 API Key
92
+
93
+ 打开 DSH Web 页面(默认 `http://localhost:3080`):
94
+
95
+ 1. 进入 **Settings → Plugins → Image generation**。
96
+ 2. 选择 Provider,填写 API Key,点击 **保存** 即可。
47
97
 
48
- 1. 打开 DSH Web 页面(默认 `http://localhost:3080`)。
49
- 2. 进入 **设置 (Settings) → 插件 (Plugins) → 图像生成 (Image generation)**。
50
- 3. 选择厂商,填入对应的 API Key,确认或自定义接口地址与模型,点击 **保存**。
98
+ <div align="center">
99
+ <img src="docs/assets/settings-preview.png" alt="设置面板预览" width="720" />
100
+ </div>
51
101
 
52
- ### 3. 在对话中触发生图
102
+ ### 3. 开始对话生图
53
103
 
54
- 新建对话,直接向大模型输入绘图提示词即可:
104
+ 现在直接在聊天框输入:
105
+
106
+ ```text
107
+ 生成一张极简主义的现代建筑客厅插画。
108
+ ```
109
+
110
+ 当前 Agent 就会自动调用 `generate_image` 工具并在对话流中返回图片。
111
+
112
+ ---
55
113
 
56
- > _"生成一只牛来的图片"_ 或 _"帮我画一张在雨夜霓虹街头的赛博朋克猫咪"_
114
+ ## ✨ 主要能力
57
115
 
58
- 模型将自动调用 `generate_image` 工具生成图片,并在对话中渲染出精美卡片。
116
+ - 💬 **对话中直接生图**:不需要切换到其他网站,也不需要手动复制 Prompt,直接告诉 Agent 你想画什么即可。
117
+ - 🎨 **多 Provider 支持**:目前支持 Google Gemini、OpenAI Images、OpenAI Compatible API 以及 ByteDance Seedream / Volcengine Ark。Provider、模型和 Endpoint 都可以在设置界面中自由修改。
118
+ - 🔑 **BYOK (自带 Key)**:插件使用你自己的 API Key。API Key 通过 DeepSeek Harness 的 `credentials` 服务管理,采用写保护隔离,不需要写进项目源码或配置文件,前端不存明文。
119
+ - 🖼️ **图片跟随会话保存**:生成结果会接入 DeepSeek Harness 的 Attachment / Conversation 体系,重新打开历史会话后,仍然可以看到之前生成的图片。
120
+ - ⚙️ **原生设置界面**:Provider、API Key、模型和 Endpoint 都可以直接在 DSH Web 设置中修改,不需要手动编辑配置文件。
59
121
 
60
122
  ---
61
123
 
62
- ## 🛠️ 本地开发与构建
124
+ ## 📦 支持的 Provider
125
+
126
+ | Provider | 默认模型 | 默认 Endpoint / Base URL |
127
+ | :--- | :--- | :--- |
128
+ | **Google Gemini** | `gemini-3.1-flash-image` | `https://generativelanguage.googleapis.com/v1beta/interactions` |
129
+ | **OpenAI Images** | `gpt-image-2` | `https://api.openai.com/v1` |
130
+ | **OpenAI Compatible** | 自定义 | 自定义 Base URL |
131
+ | **ByteDance Seedream / 火山方舟** | `doubao-seedream-5-0-260128` | `https://ark.cn-beijing.volces.com/api/v3` |
132
+
133
+ ---
134
+
135
+ ## 🛠️ 本地开发 (Development)
63
136
 
64
137
  ```bash
65
- # 安装依赖
66
- pnpm install
138
+ # 克隆仓库
139
+ git clone https://github.com/shanliuling/dsh-image-gen.git
140
+ cd dsh-image-gen
67
141
 
68
- # 类型检查
142
+ # 安装依赖与构建
143
+ pnpm install
69
144
  pnpm run typecheck
70
-
71
- # 运行单元测试
72
145
  pnpm run test
73
-
74
- # 编译 Node 端与浏览器端产物
75
146
  pnpm run build
76
147
 
77
- # 预打包检查
148
+ # 检查 npm 打包内容
78
149
  pnpm run pack:check
79
150
  ```
80
151
 
81
152
  ---
82
153
 
83
- ## 📄 开源协议
154
+ ## 📄 开源协议 (License)
155
+
156
+ 本项目基于 [MIT License](LICENSE) 开源。
84
157
 
85
- [MIT](LICENSE)
158
+ 如果这个插件对你有用,欢迎点一个 ⭐️ **Star** 支持!
package/lib/client.js CHANGED
@@ -61,10 +61,11 @@ window.__ModuleLoader__.load({
61
61
  style.remove();
62
62
  };
63
63
  }, "dsh-image-gen: styles");
64
- ctx.slots.inject("settings.plugin.item", () => ctx.slots.register({
64
+ const register = ctx.slots.register.bind(ctx.slots);
65
+ ctx.slots.inject("settings.plugin.item", () => register({
65
66
  name: "settings.plugin.item",
66
- id: "dsh-image-gen",
67
- order: 30,
67
+ key: IMAGE_GENERATION_NAMESPACE,
68
+ id: IMAGE_GENERATION_NAMESPACE,
68
69
  inject: () => ({
69
70
  scope,
70
71
  credentials: api.credentials
package/lib/client.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","names":["useState","_jsxs","_jsx"],"sources":["types/shared.js","types/client/index.js"],"sourcesContent":["/** Values shared by the Host and browser Bundle faces. */\n/** Browser route used by the generated-image card. */\nexport const IMAGE_ROUTE = '/plugins/dsh-image-gen/image';\n/** Namespace persisted through DSH Settings. */\nexport const IMAGE_GENERATION_NAMESPACE = 'image-generation';\n/** Supported providers. */\nexport const IMAGE_PROVIDERS = ['google', 'openai', 'seedream'];\n/** Default endpoints and base URLs. */\nexport const DEFAULT_GOOGLE_ENDPOINT = 'https://generativelanguage.googleapis.com/v1beta/interactions';\nexport const DEFAULT_OPENAI_BASE_URL = 'https://api.openai.com/v1';\nexport const DEFAULT_SEEDREAM_BASE_URL = 'https://ark.cn-beijing.volces.com/api/v3';\n/** Default model names. */\nexport const DEFAULT_GOOGLE_MODEL = 'gemini-3.1-flash-image';\nexport const DEFAULT_OPENAI_MODEL = 'gpt-image-2';\nexport const DEFAULT_SEEDREAM_MODEL = 'doubao-seedream-5-0-260128';\nexport const DEFAULT_MODELS = {\n google: DEFAULT_GOOGLE_MODEL,\n openai: DEFAULT_OPENAI_MODEL,\n seedream: DEFAULT_SEEDREAM_MODEL,\n};\nexport const DEFAULT_BASE_URLS = {\n google: DEFAULT_GOOGLE_ENDPOINT,\n openai: DEFAULT_OPENAI_BASE_URL,\n seedream: DEFAULT_SEEDREAM_BASE_URL,\n};\n//# sourceMappingURL=shared.js.map","import { jsx as _jsx, jsxs as _jsxs } from \"react/jsx-runtime\";\n/** Web settings and generated-image cards contributed by the Bundle. */\nimport { useEffect, useState } from 'react';\nimport { DEFAULT_BASE_URLS, DEFAULT_MODELS, IMAGE_GENERATION_NAMESPACE, IMAGE_ROUTE, } from '../shared.js';\nconst KEY_REF = { google: 'GEMINI_API_KEY', openai: 'OPENAI_API_KEY', seedream: 'ARK_API_KEY' };\nconst PROVIDER_LABEL = { google: 'Google Gemini', openai: 'OpenAI / 中转站', seedream: '字节 Seedream' };\nconst STYLE = `\n.dsh-ig-card{list-style:none;border:1px solid var(--border-color,#e5e7eb);border-radius:14px;background:var(--surface-color,#fff);overflow:hidden}.dsh-ig-head{width:100%;padding:18px 20px;border:0;background:transparent;text-align:left;cursor:pointer;display:flex;justify-content:space-between;gap:16px;color:inherit}.dsh-ig-title{display:block;font-size:16px;font-weight:650}.dsh-ig-desc{display:block;margin-top:5px;color:#7b818b;font-size:14px}.dsh-ig-body{padding:0 20px 20px;border-top:1px solid var(--border-color,#eee)}.dsh-ig-field{display:grid;gap:7px;margin-top:18px}.dsh-ig-label{font-size:14px;font-weight:600}.dsh-ig-input{box-sizing:border-box;width:100%;padding:10px 12px;border:1px solid #d7dbe0;border-radius:9px;background:transparent;color:inherit}.dsh-ig-input-group{display:flex;gap:8px;align-items:center}.dsh-ig-btn-reset{padding:9px 14px;border:1px solid #d7dbe0;border-radius:9px;background:var(--surface-color,#f9fafb);color:inherit;font-size:13px;cursor:pointer;white-space:nowrap;transition:background .15s}.dsh-ig-btn-reset:hover{background:#edf0f3}.dsh-ig-hint,.dsh-ig-status{margin:0;color:#7b818b;font-size:12px}.dsh-ig-actions{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:16px}.dsh-ig-save{border:0;border-radius:9px;padding:9px 16px;background:#4c78ff;color:#fff;cursor:pointer}.dsh-ig-save:disabled{opacity:.55;cursor:default}.dsh-ig-result{display:grid;gap:10px;max-width:520px}.dsh-ig-result-title{font-size:14px;font-weight:600}.dsh-ig-image{display:block;max-width:100%;max-height:520px;border-radius:14px;background:#f2f3f5}.dsh-ig-error{color:#d33;font-size:13px}.dsh-ig-loading{color:#7b818b;font-size:13px}`;\n/** Required browser services. */\nexport const inject = ['slots', 'connection', 'remote', 'settingsScope'];\n/** Mount the settings card and generated-image card. */\nexport function apply(ctx) {\n const { api } = ctx.get('connection');\n const scope = ctx.settingsScope.bind({ namespace: IMAGE_GENERATION_NAMESPACE });\n ctx.effect(() => {\n const style = document.createElement('style');\n style.dataset.plugin = 'dsh-image-gen';\n style.textContent = STYLE;\n document.head.appendChild(style);\n return () => { style.remove(); };\n }, 'dsh-image-gen: styles');\n ctx.slots.inject('settings.plugin.item', () => ctx.slots.register({ name: 'settings.plugin.item', id: 'dsh-image-gen', order: 30, inject: () => ({ scope, credentials: api.credentials }) }, ImageGenerationSettingsCard));\n ctx.slots.inject('tool.call.toolview', () => ctx.slots.register({ name: 'tool.call.toolview', key: 'generate_image' }, GeneratedImageCard));\n}\n/** Edit provider settings and its write-only API credential. */\nexport function ImageGenerationSettingsCard(props) {\n const [open, setOpen] = useState(false);\n const [snapshot, setSnapshot] = useState(() => props.scope.getSnapshot());\n const [provider, setProvider] = useState('google');\n const [model, setModel] = useState('');\n const [baseURL, setBaseURL] = useState('');\n const [key, setKey] = useState('');\n const [configured, setConfigured] = useState();\n const [saving, setSaving] = useState(false);\n const [message, setMessage] = useState('');\n useEffect(() => props.scope.subscribe(() => { setSnapshot(props.scope.getSnapshot()); }), [props.scope]);\n useEffect(() => {\n const value = snapshot.value;\n const next = value?.provider ?? 'google';\n setProvider(next);\n setModel(modelOf(next, value));\n setBaseURL(baseURLOf(next, value));\n }, [snapshot]);\n useEffect(() => {\n let active = true;\n void props.credentials.describe({ refs: [KEY_REF[provider]] }).then(response => {\n if (active)\n setConfigured(response.result.ok ? response.result.value.credentials[KEY_REF[provider]]?.configured ?? false : undefined);\n }).catch(() => { if (active)\n setConfigured(undefined); });\n return () => { active = false; };\n }, [props.credentials, provider]);\n const save = async (event) => {\n event.preventDefault();\n setSaving(true);\n setMessage('');\n try {\n await props.scope.set('provider', provider);\n await props.scope.set(provider === 'google' ? 'googleModel' : provider === 'openai' ? 'openaiModel' : 'seedreamModel', model);\n await props.scope.set(provider === 'google' ? 'googleEndpoint' : provider === 'openai' ? 'openaiBaseURL' : 'seedreamBaseURL', baseURL);\n if (key.trim().length > 0) {\n const response = await props.credentials.set({ ref: KEY_REF[provider], value: key.trim() });\n if (!response.result.ok)\n throw new Error(response.result.error.message);\n setKey('');\n setConfigured(true);\n }\n setMessage('已保存');\n }\n catch (cause) {\n setMessage(cause instanceof Error ? cause.message : String(cause));\n }\n finally {\n setSaving(false);\n }\n };\n const keyStatus = configured === undefined ? '正在检查 API Key…' : configured ? '已配置 API Key' : '尚未配置 API Key';\n return _jsxs(\"li\", { className: \"dsh-ig-card\", children: [_jsxs(\"button\", { type: \"button\", className: \"dsh-ig-head\", \"aria-expanded\": open, onClick: () => { setOpen(value => !value); }, children: [_jsxs(\"span\", { children: [_jsx(\"span\", { className: \"dsh-ig-title\", children: \"\\u56FE\\u50CF\\u751F\\u6210\" }), _jsx(\"span\", { className: \"dsh-ig-desc\", children: \"\\u9009\\u62E9\\u5382\\u5546\\u5E76\\u914D\\u7F6E\\u751F\\u56FE\\u6A21\\u578B\\u3002\" })] }), _jsx(\"span\", { \"aria-hidden\": \"true\", children: open ? '⌃' : '⌄' })] }), open ? _jsxs(\"form\", { className: \"dsh-ig-body\", onSubmit: (event) => { void save(event); }, children: [_jsxs(\"label\", { className: \"dsh-ig-field\", children: [_jsx(\"span\", { className: \"dsh-ig-label\", children: \"Provider\" }), _jsxs(\"select\", { className: \"dsh-ig-input\", value: provider, onChange: event => { const next = event.target.value; setProvider(next); setModel(modelOf(next, snapshot.value)); setBaseURL(baseURLOf(next, snapshot.value)); setKey(''); }, children: [_jsx(\"option\", { value: \"google\", children: \"Google Gemini\" }), _jsx(\"option\", { value: \"openai\", children: \"OpenAI / \\u4E2D\\u8F6C\\u7AD9\" }), _jsx(\"option\", { value: \"seedream\", children: \"\\u5B57\\u8282 Seedream\" })] }), _jsx(\"span\", { className: \"dsh-ig-hint\", children: PROVIDER_LABEL[provider] })] }), _jsxs(\"label\", { className: \"dsh-ig-field\", children: [_jsxs(\"span\", { className: \"dsh-ig-label\", children: [PROVIDER_LABEL[provider], \" API Key\"] }), _jsx(\"input\", { className: \"dsh-ig-input\", type: \"password\", autoComplete: \"off\", value: key, onChange: event => { setKey(event.target.value); }, placeholder: configured ? '留空即可保留已配置的 Key' : '' }), _jsxs(\"span\", { className: \"dsh-ig-hint\", children: [\"\\u5B89\\u5168\\u4FDD\\u5B58\\u4E3A \", KEY_REF[provider], \"\\uFF1B\\u9875\\u9762\\u4E0D\\u4F1A\\u8BFB\\u56DE\\u660E\\u6587\\u3002\"] })] }), _jsxs(\"label\", { className: \"dsh-ig-field\", children: [_jsx(\"span\", { className: \"dsh-ig-label\", children: \"\\u63A5\\u53E3\\u5730\\u5740\" }), _jsxs(\"div\", { className: \"dsh-ig-input-group\", children: [_jsx(\"input\", { className: \"dsh-ig-input\", type: \"url\", value: baseURL, onChange: event => { setBaseURL(event.target.value); }, required: true }), _jsx(\"button\", { type: \"button\", className: \"dsh-ig-btn-reset\", title: \"\\u91CD\\u7F6E\\u4E3A\\u9ED8\\u8BA4\\u5B98\\u65B9\\u5730\\u5740\", onClick: () => { setBaseURL(DEFAULT_BASE_URLS[provider]); }, children: \"\\u91CD\\u7F6E\" })] }), _jsx(\"span\", { className: \"dsh-ig-hint\", children: provider === 'google' ? 'Google 官方地址或反代端点(全路径)。' : provider === 'openai' ? '中转站请填其 OpenAI 兼容的 /v1 地址。' : '火山方舟兼容的 /api/v3 地址。' })] }), _jsxs(\"label\", { className: \"dsh-ig-field\", children: [_jsx(\"span\", { className: \"dsh-ig-label\", children: \"\\u6A21\\u578B\" }), _jsx(\"input\", { className: \"dsh-ig-input\", value: model, onChange: event => { setModel(event.target.value); }, required: true })] }), _jsxs(\"div\", { className: \"dsh-ig-actions\", children: [_jsx(\"p\", { className: \"dsh-ig-status\", role: \"status\", children: message || keyStatus }), _jsx(\"button\", { className: \"dsh-ig-save\", type: \"submit\", disabled: saving || !snapshot.writable, children: saving ? '保存中…' : '保存' })] })] }) : null] });\n}\n/** Render the durable attachment referenced by a completed image tool call. */\nexport function GeneratedImageCard(props) {\n const attachment = imageRef(props.block);\n const [url, setUrl] = useState();\n const [error, setError] = useState();\n useEffect(() => {\n if (attachment === undefined)\n return;\n const controller = new AbortController();\n let objectUrl;\n void fetch(IMAGE_ROUTE, { method: 'POST', signal: controller.signal, headers: { 'content-type': 'application/json' }, body: JSON.stringify({ attachment }) }).then(async (response) => { if (!response.ok)\n throw new Error(`图片读取失败 (${String(response.status)})`); const blob = await response.blob(); if (controller.signal.aborted)\n return; objectUrl = URL.createObjectURL(blob); setUrl(objectUrl); }).catch(cause => { if (!controller.signal.aborted)\n setError(cause instanceof Error ? cause.message : String(cause)); });\n return () => { controller.abort(); if (objectUrl !== undefined)\n URL.revokeObjectURL(objectUrl); };\n }, [attachment?.attachmentId]);\n if (attachment === undefined)\n return _jsx(\"div\", { className: \"dsh-ig-loading\", children: \"\\u6B63\\u5728\\u751F\\u6210\\u56FE\\u7247\\u2026\" });\n return _jsxs(\"section\", { className: \"dsh-ig-result\", \"aria-label\": \"Generated image\", children: [_jsx(\"div\", { className: \"dsh-ig-result-title\", children: \"Generated image\" }), error !== undefined ? _jsx(\"div\", { className: \"dsh-ig-error\", children: error }) : null, url === undefined && error === undefined ? _jsx(\"div\", { className: \"dsh-ig-loading\", children: \"\\u6B63\\u5728\\u52A0\\u8F7D\\u56FE\\u7247\\u2026\" }) : null, url !== undefined ? _jsx(\"img\", { className: \"dsh-ig-image\", src: url, alt: attachment.name ?? 'Generated image' }) : null] });\n}\nfunction modelOf(provider, value) {\n const stored = provider === 'google' ? value?.googleModel : provider === 'openai' ? value?.openaiModel : value?.seedreamModel;\n return typeof stored === 'string' && stored.length > 0 ? stored : DEFAULT_MODELS[provider];\n}\nfunction baseURLOf(provider, value) {\n const stored = provider === 'google' ? value?.googleEndpoint : provider === 'openai' ? value?.openaiBaseURL : value?.seedreamBaseURL;\n return typeof stored === 'string' && stored.length > 0 ? stored : DEFAULT_BASE_URLS[provider];\n}\nfunction imageRef(block) { if (!('kind' in block) || block.resultView?.card !== 'generic')\n return undefined; const image = block.resultView.content?.find(item => item.type === 'image'); return image?.type === 'image' ? image.attachment : undefined; }\n//# sourceMappingURL=index.js.map"],"mappings":"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"}
1
+ {"version":3,"file":"client.js","names":["useState","_jsxs","_jsx"],"sources":["types/shared.js","types/client/index.js"],"sourcesContent":["/** Values shared by the Host and browser Bundle faces. */\n/** Browser route used by the generated-image card. */\nexport const IMAGE_ROUTE = '/plugins/dsh-image-gen/image';\n/** Namespace persisted through DSH Settings. */\nexport const IMAGE_GENERATION_NAMESPACE = 'image-generation';\n/** Supported providers. */\nexport const IMAGE_PROVIDERS = ['google', 'openai', 'seedream'];\n/** Default endpoints and base URLs. */\nexport const DEFAULT_GOOGLE_ENDPOINT = 'https://generativelanguage.googleapis.com/v1beta/interactions';\nexport const DEFAULT_OPENAI_BASE_URL = 'https://api.openai.com/v1';\nexport const DEFAULT_SEEDREAM_BASE_URL = 'https://ark.cn-beijing.volces.com/api/v3';\n/** Default model names. */\nexport const DEFAULT_GOOGLE_MODEL = 'gemini-3.1-flash-image';\nexport const DEFAULT_OPENAI_MODEL = 'gpt-image-2';\nexport const DEFAULT_SEEDREAM_MODEL = 'doubao-seedream-5-0-260128';\nexport const DEFAULT_MODELS = {\n google: DEFAULT_GOOGLE_MODEL,\n openai: DEFAULT_OPENAI_MODEL,\n seedream: DEFAULT_SEEDREAM_MODEL,\n};\nexport const DEFAULT_BASE_URLS = {\n google: DEFAULT_GOOGLE_ENDPOINT,\n openai: DEFAULT_OPENAI_BASE_URL,\n seedream: DEFAULT_SEEDREAM_BASE_URL,\n};\n//# sourceMappingURL=shared.js.map","import { jsx as _jsx, jsxs as _jsxs } from \"react/jsx-runtime\";\n/** Web settings and generated-image cards contributed by the Bundle. */\nimport { useEffect, useState } from 'react';\nimport { DEFAULT_BASE_URLS, DEFAULT_MODELS, IMAGE_GENERATION_NAMESPACE, IMAGE_ROUTE, } from '../shared.js';\nconst KEY_REF = { google: 'GEMINI_API_KEY', openai: 'OPENAI_API_KEY', seedream: 'ARK_API_KEY' };\nconst PROVIDER_LABEL = { google: 'Google Gemini', openai: 'OpenAI / 中转站', seedream: '字节 Seedream' };\nconst STYLE = `\n.dsh-ig-card{list-style:none;border:1px solid var(--border-color,#e5e7eb);border-radius:14px;background:var(--surface-color,#fff);overflow:hidden}.dsh-ig-head{width:100%;padding:18px 20px;border:0;background:transparent;text-align:left;cursor:pointer;display:flex;justify-content:space-between;gap:16px;color:inherit}.dsh-ig-title{display:block;font-size:16px;font-weight:650}.dsh-ig-desc{display:block;margin-top:5px;color:#7b818b;font-size:14px}.dsh-ig-body{padding:0 20px 20px;border-top:1px solid var(--border-color,#eee)}.dsh-ig-field{display:grid;gap:7px;margin-top:18px}.dsh-ig-label{font-size:14px;font-weight:600}.dsh-ig-input{box-sizing:border-box;width:100%;padding:10px 12px;border:1px solid #d7dbe0;border-radius:9px;background:transparent;color:inherit}.dsh-ig-input-group{display:flex;gap:8px;align-items:center}.dsh-ig-btn-reset{padding:9px 14px;border:1px solid #d7dbe0;border-radius:9px;background:var(--surface-color,#f9fafb);color:inherit;font-size:13px;cursor:pointer;white-space:nowrap;transition:background .15s}.dsh-ig-btn-reset:hover{background:#edf0f3}.dsh-ig-hint,.dsh-ig-status{margin:0;color:#7b818b;font-size:12px}.dsh-ig-actions{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:16px}.dsh-ig-save{border:0;border-radius:9px;padding:9px 16px;background:#4c78ff;color:#fff;cursor:pointer}.dsh-ig-save:disabled{opacity:.55;cursor:default}.dsh-ig-result{display:grid;gap:10px;max-width:520px}.dsh-ig-result-title{font-size:14px;font-weight:600}.dsh-ig-image{display:block;max-width:100%;max-height:520px;border-radius:14px;background:#f2f3f5}.dsh-ig-error{color:#d33;font-size:13px}.dsh-ig-loading{color:#7b818b;font-size:13px}`;\n/** Required browser services. */\nexport const inject = ['slots', 'connection', 'remote', 'settingsScope'];\n/** Mount the settings card and generated-image card. */\nexport function apply(ctx) {\n const { api } = ctx.get('connection');\n const scope = ctx.settingsScope.bind({ namespace: IMAGE_GENERATION_NAMESPACE });\n ctx.effect(() => {\n const style = document.createElement('style');\n style.dataset.plugin = 'dsh-image-gen';\n style.textContent = STYLE;\n document.head.appendChild(style);\n return () => { style.remove(); };\n }, 'dsh-image-gen: styles');\n const register = ctx.slots.register.bind(ctx.slots);\n ctx.slots.inject('settings.plugin.item', () => register({\n name: 'settings.plugin.item',\n key: IMAGE_GENERATION_NAMESPACE,\n id: IMAGE_GENERATION_NAMESPACE,\n inject: () => ({ scope, credentials: api.credentials }),\n }, ImageGenerationSettingsCard));\n ctx.slots.inject('tool.call.toolview', () => ctx.slots.register({ name: 'tool.call.toolview', key: 'generate_image' }, GeneratedImageCard));\n}\n/** Edit provider settings and its write-only API credential. */\nexport function ImageGenerationSettingsCard(props) {\n const [open, setOpen] = useState(false);\n const [snapshot, setSnapshot] = useState(() => props.scope.getSnapshot());\n const [provider, setProvider] = useState('google');\n const [model, setModel] = useState('');\n const [baseURL, setBaseURL] = useState('');\n const [key, setKey] = useState('');\n const [configured, setConfigured] = useState();\n const [saving, setSaving] = useState(false);\n const [message, setMessage] = useState('');\n useEffect(() => props.scope.subscribe(() => { setSnapshot(props.scope.getSnapshot()); }), [props.scope]);\n useEffect(() => {\n const value = snapshot.value;\n const next = value?.provider ?? 'google';\n setProvider(next);\n setModel(modelOf(next, value));\n setBaseURL(baseURLOf(next, value));\n }, [snapshot]);\n useEffect(() => {\n let active = true;\n void props.credentials.describe({ refs: [KEY_REF[provider]] }).then(response => {\n if (active)\n setConfigured(response.result.ok ? response.result.value.credentials[KEY_REF[provider]]?.configured ?? false : undefined);\n }).catch(() => { if (active)\n setConfigured(undefined); });\n return () => { active = false; };\n }, [props.credentials, provider]);\n const save = async (event) => {\n event.preventDefault();\n setSaving(true);\n setMessage('');\n try {\n await props.scope.set('provider', provider);\n await props.scope.set(provider === 'google' ? 'googleModel' : provider === 'openai' ? 'openaiModel' : 'seedreamModel', model);\n await props.scope.set(provider === 'google' ? 'googleEndpoint' : provider === 'openai' ? 'openaiBaseURL' : 'seedreamBaseURL', baseURL);\n if (key.trim().length > 0) {\n const response = await props.credentials.set({ ref: KEY_REF[provider], value: key.trim() });\n if (!response.result.ok)\n throw new Error(response.result.error.message);\n setKey('');\n setConfigured(true);\n }\n setMessage('已保存');\n }\n catch (cause) {\n setMessage(cause instanceof Error ? cause.message : String(cause));\n }\n finally {\n setSaving(false);\n }\n };\n const keyStatus = configured === undefined ? '正在检查 API Key…' : configured ? '已配置 API Key' : '尚未配置 API Key';\n return _jsxs(\"li\", { className: \"dsh-ig-card\", children: [_jsxs(\"button\", { type: \"button\", className: \"dsh-ig-head\", \"aria-expanded\": open, onClick: () => { setOpen(value => !value); }, children: [_jsxs(\"span\", { children: [_jsx(\"span\", { className: \"dsh-ig-title\", children: \"\\u56FE\\u50CF\\u751F\\u6210\" }), _jsx(\"span\", { className: \"dsh-ig-desc\", children: \"\\u9009\\u62E9\\u5382\\u5546\\u5E76\\u914D\\u7F6E\\u751F\\u56FE\\u6A21\\u578B\\u3002\" })] }), _jsx(\"span\", { \"aria-hidden\": \"true\", children: open ? '⌃' : '⌄' })] }), open ? _jsxs(\"form\", { className: \"dsh-ig-body\", onSubmit: (event) => { void save(event); }, children: [_jsxs(\"label\", { className: \"dsh-ig-field\", children: [_jsx(\"span\", { className: \"dsh-ig-label\", children: \"Provider\" }), _jsxs(\"select\", { className: \"dsh-ig-input\", value: provider, onChange: event => { const next = event.target.value; setProvider(next); setModel(modelOf(next, snapshot.value)); setBaseURL(baseURLOf(next, snapshot.value)); setKey(''); }, children: [_jsx(\"option\", { value: \"google\", children: \"Google Gemini\" }), _jsx(\"option\", { value: \"openai\", children: \"OpenAI / \\u4E2D\\u8F6C\\u7AD9\" }), _jsx(\"option\", { value: \"seedream\", children: \"\\u5B57\\u8282 Seedream\" })] }), _jsx(\"span\", { className: \"dsh-ig-hint\", children: PROVIDER_LABEL[provider] })] }), _jsxs(\"label\", { className: \"dsh-ig-field\", children: [_jsxs(\"span\", { className: \"dsh-ig-label\", children: [PROVIDER_LABEL[provider], \" API Key\"] }), _jsx(\"input\", { className: \"dsh-ig-input\", type: \"password\", autoComplete: \"off\", value: key, onChange: event => { setKey(event.target.value); }, placeholder: configured ? '留空即可保留已配置的 Key' : '' }), _jsxs(\"span\", { className: \"dsh-ig-hint\", children: [\"\\u5B89\\u5168\\u4FDD\\u5B58\\u4E3A \", KEY_REF[provider], \"\\uFF1B\\u9875\\u9762\\u4E0D\\u4F1A\\u8BFB\\u56DE\\u660E\\u6587\\u3002\"] })] }), _jsxs(\"label\", { className: \"dsh-ig-field\", children: [_jsx(\"span\", { className: \"dsh-ig-label\", children: \"\\u63A5\\u53E3\\u5730\\u5740\" }), _jsxs(\"div\", { className: \"dsh-ig-input-group\", children: [_jsx(\"input\", { className: \"dsh-ig-input\", type: \"url\", value: baseURL, onChange: event => { setBaseURL(event.target.value); }, required: true }), _jsx(\"button\", { type: \"button\", className: \"dsh-ig-btn-reset\", title: \"\\u91CD\\u7F6E\\u4E3A\\u9ED8\\u8BA4\\u5B98\\u65B9\\u5730\\u5740\", onClick: () => { setBaseURL(DEFAULT_BASE_URLS[provider]); }, children: \"\\u91CD\\u7F6E\" })] }), _jsx(\"span\", { className: \"dsh-ig-hint\", children: provider === 'google' ? 'Google 官方地址或反代端点(全路径)。' : provider === 'openai' ? '中转站请填其 OpenAI 兼容的 /v1 地址。' : '火山方舟兼容的 /api/v3 地址。' })] }), _jsxs(\"label\", { className: \"dsh-ig-field\", children: [_jsx(\"span\", { className: \"dsh-ig-label\", children: \"\\u6A21\\u578B\" }), _jsx(\"input\", { className: \"dsh-ig-input\", value: model, onChange: event => { setModel(event.target.value); }, required: true })] }), _jsxs(\"div\", { className: \"dsh-ig-actions\", children: [_jsx(\"p\", { className: \"dsh-ig-status\", role: \"status\", children: message || keyStatus }), _jsx(\"button\", { className: \"dsh-ig-save\", type: \"submit\", disabled: saving || !snapshot.writable, children: saving ? '保存中…' : '保存' })] })] }) : null] });\n}\n/** Render the durable attachment referenced by a completed image tool call. */\nexport function GeneratedImageCard(props) {\n const attachment = imageRef(props.block);\n const [url, setUrl] = useState();\n const [error, setError] = useState();\n useEffect(() => {\n if (attachment === undefined)\n return;\n const controller = new AbortController();\n let objectUrl;\n void fetch(IMAGE_ROUTE, { method: 'POST', signal: controller.signal, headers: { 'content-type': 'application/json' }, body: JSON.stringify({ attachment }) }).then(async (response) => { if (!response.ok)\n throw new Error(`图片读取失败 (${String(response.status)})`); const blob = await response.blob(); if (controller.signal.aborted)\n return; objectUrl = URL.createObjectURL(blob); setUrl(objectUrl); }).catch(cause => { if (!controller.signal.aborted)\n setError(cause instanceof Error ? cause.message : String(cause)); });\n return () => { controller.abort(); if (objectUrl !== undefined)\n URL.revokeObjectURL(objectUrl); };\n }, [attachment?.attachmentId]);\n if (attachment === undefined)\n return _jsx(\"div\", { className: \"dsh-ig-loading\", children: \"\\u6B63\\u5728\\u751F\\u6210\\u56FE\\u7247\\u2026\" });\n return _jsxs(\"section\", { className: \"dsh-ig-result\", \"aria-label\": \"Generated image\", children: [_jsx(\"div\", { className: \"dsh-ig-result-title\", children: \"Generated image\" }), error !== undefined ? _jsx(\"div\", { className: \"dsh-ig-error\", children: error }) : null, url === undefined && error === undefined ? _jsx(\"div\", { className: \"dsh-ig-loading\", children: \"\\u6B63\\u5728\\u52A0\\u8F7D\\u56FE\\u7247\\u2026\" }) : null, url !== undefined ? _jsx(\"img\", { className: \"dsh-ig-image\", src: url, alt: attachment.name ?? 'Generated image' }) : null] });\n}\nfunction modelOf(provider, value) {\n const stored = provider === 'google' ? value?.googleModel : provider === 'openai' ? value?.openaiModel : value?.seedreamModel;\n return typeof stored === 'string' && stored.length > 0 ? stored : DEFAULT_MODELS[provider];\n}\nfunction baseURLOf(provider, value) {\n const stored = provider === 'google' ? value?.googleEndpoint : provider === 'openai' ? value?.openaiBaseURL : value?.seedreamBaseURL;\n return typeof stored === 'string' && stored.length > 0 ? stored : DEFAULT_BASE_URLS[provider];\n}\nfunction imageRef(block) { if (!('kind' in block) || block.resultView?.card !== 'generic')\n return undefined; const image = block.resultView.content?.find(item => item.type === 'image'); return image?.type === 'image' ? image.attachment : undefined; }\n//# sourceMappingURL=index.js.map"],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "dsh-image-gen",
3
- "version": "0.1.0",
4
- "description": "Installable multi-provider image generation bundle for DeepSeek Harness",
3
+ "version": "0.1.1",
4
+ "description": "Bring ChatGPT-like image generation to DeepSeek Harness — Gemini, OpenAI, Seedream & more.",
5
5
  "type": "module",
6
6
  "author": "shanliuling",
7
7
  "repository": {
@@ -34,6 +34,7 @@
34
34
  "cordis.patch.yml",
35
35
  "README.md",
36
36
  "README.zh-CN.md",
37
+ "README.en.md",
37
38
  "LICENSE"
38
39
  ],
39
40
  "dsh": {
@@ -57,12 +58,20 @@
57
58
  },
58
59
  "license": "MIT",
59
60
  "keywords": [
61
+ "deepseek",
60
62
  "deepseek-harness",
61
63
  "dsh",
64
+ "dsh-plugin",
65
+ "ai-agent",
66
+ "image-generation",
67
+ "ai-image-generation",
68
+ "multimodal",
62
69
  "gemini",
63
70
  "openai",
71
+ "openai-compatible",
64
72
  "seedream",
65
- "image-generation",
73
+ "volcengine",
74
+ "byok",
66
75
  "cordis"
67
76
  ],
68
77
  "peerDependencies": {