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 +158 -0
- package/README.md +115 -42
- package/README.zh-CN.md +114 -41
- package/lib/client.js +4 -3
- package/lib/client.js.map +1 -1
- package/package.json +12 -3
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
|
+
[](https://www.npmjs.com/package/dsh-image-gen)
|
|
12
|
+
[](https://github.com/deepseek-ai)
|
|
13
|
+
[](https://www.npmjs.com/package/dsh-image-gen)
|
|
14
|
+
[](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
|
-
|
|
1
|
+
<div align="center">
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
# 🎨 dsh-image-gen
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
### DeepSeek Harness (DSH) 原生生图插件
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
**让 DeepSeek Harness 像 ChatGPT 一样,在对话里直接生成图片。**
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
支持 Google Gemini、OpenAI Images、OpenAI Compatible API、字节 Seedream / 火山方舟。
|
|
10
|
+
|
|
11
|
+
[](https://www.npmjs.com/package/dsh-image-gen)
|
|
12
|
+
[](https://github.com/deepseek-ai)
|
|
13
|
+
[](https://www.npmjs.com/package/dsh-image-gen)
|
|
14
|
+
[](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
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
30
|
+
<p align="center">安装完成后,在 DSH 设置中填入自己的 API Key,就可以直接对 Agent 说:</p>
|
|
31
|
+
|
|
32
|
+
```text
|
|
33
|
+
帮我画一张雨夜霓虹街头的赛博朋克猫咪。
|
|
34
|
+
```
|
|
17
35
|
|
|
18
|
-
|
|
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
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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
|
-
### 1.
|
|
65
|
+
### 1. 安装插件
|
|
35
66
|
|
|
36
|
-
|
|
67
|
+
在你的 DeepSeek Harness 项目根目录下运行:
|
|
37
68
|
|
|
38
69
|
```bash
|
|
39
|
-
#
|
|
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
|
-
|
|
43
|
-
|
|
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
|
-
|
|
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
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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
|
-
|
|
55
|
-
> *"Generate a realistic picture of a Holstein cow in a green meadow with wildflowers under golden sunlight."*
|
|
104
|
+
现在直接在聊天框输入:
|
|
56
105
|
|
|
57
|
-
|
|
106
|
+
```text
|
|
107
|
+
生成一张极简主义的现代建筑客厅插画。
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
当前 Agent 就会自动调用 `generate_image` 工具并在对话流中返回图片。
|
|
58
111
|
|
|
59
112
|
---
|
|
60
113
|
|
|
61
|
-
##
|
|
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
|
-
#
|
|
65
|
-
|
|
138
|
+
# 克隆仓库
|
|
139
|
+
git clone https://github.com/shanliuling/dsh-image-gen.git
|
|
140
|
+
cd dsh-image-gen
|
|
66
141
|
|
|
67
|
-
#
|
|
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
|
-
#
|
|
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
|
-
|
|
1
|
+
<div align="center">
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
# 🎨 dsh-image-gen
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
### DeepSeek Harness (DSH) 原生生图插件
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
**让 DeepSeek Harness 像 ChatGPT 一样,在对话里直接生成图片。**
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
支持 Google Gemini、OpenAI Images、OpenAI Compatible API、字节 Seedream / 火山方舟。
|
|
10
|
+
|
|
11
|
+
[](https://www.npmjs.com/package/dsh-image-gen)
|
|
12
|
+
[](https://github.com/deepseek-ai)
|
|
13
|
+
[](https://www.npmjs.com/package/dsh-image-gen)
|
|
14
|
+
[](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
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
30
|
+
<p align="center">安装完成后,在 DSH 设置中填入自己的 API Key,就可以直接对 Agent 说:</p>
|
|
31
|
+
|
|
32
|
+
```text
|
|
33
|
+
帮我画一张雨夜霓虹街头的赛博朋克猫咪。
|
|
34
|
+
```
|
|
17
35
|
|
|
18
|
-
|
|
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
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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
|
|
67
|
+
在你的 DeepSeek Harness 项目根目录下运行:
|
|
37
68
|
|
|
38
69
|
```bash
|
|
39
|
-
#
|
|
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
|
-
|
|
43
|
-
|
|
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
|
-
|
|
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
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
64
|
+
const register = ctx.slots.register.bind(ctx.slots);
|
|
65
|
+
ctx.slots.inject("settings.plugin.item", () => register({
|
|
65
66
|
name: "settings.plugin.item",
|
|
66
|
-
|
|
67
|
-
|
|
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":";;;;;;;;;;;EAEA,MAAa,cAAc;;EAE3B,MAAa,6BAA6B;;EAI1C,MAAa,0BAA0B;EACvC,MAAa,0BAA0B;EACvC,MAAa,4BAA4B;EAKzC,MAAa,iBAAiB;GAC1B,QAAQ;GACR,QAAQ;GACR,UAAU;EACd;EACA,MAAa,oBAAoB;GAC7B,QAAQ;GACR,QAAQ;GACR,UAAU;EACd;;;;ECpBA,MAAM,UAAU;GAAE,QAAQ;GAAkB,QAAQ;GAAkB,UAAU;EAAc;EAC9F,MAAM,iBAAiB;GAAE,QAAQ;GAAiB,QAAQ;GAAgB,UAAU;EAAc;EAClG,MAAM,QAAQ;;;EAGd,MAAa,SAAS;GAAC;GAAS;GAAc;GAAU;EAAe;;EAEvE,SAAgB,MAAM,KAAK;GACvB,MAAM,EAAE,QAAQ,IAAI,IAAI,YAAY;GACpC,MAAM,QAAQ,IAAI,cAAc,KAAK,EAAE,WAAW,2BAA2B,CAAC;GAC9E,IAAI,aAAa;IACb,MAAM,QAAQ,SAAS,cAAc,OAAO;IAC5C,MAAM,QAAQ,SAAS;IACvB,MAAM,cAAc;IACpB,SAAS,KAAK,YAAY,KAAK;IAC/B,aAAa;KAAE,MAAM,OAAO;IAAG;GACnC,GAAG,uBAAuB;GAC1B,MAAM,WAAW,IAAI,MAAM,SAAS,KAAK,IAAI,KAAK;GAClD,IAAI,MAAM,OAAO,8BAA8B,SAAS;IACpD,MAAM;IACN,KAAK;IACL,IAAI;IACJ,eAAe;KAAE;KAAO,aAAa,IAAI;IAAY;GACzD,GAAG,2BAA2B,CAAC;GAC/B,IAAI,MAAM,OAAO,4BAA4B,IAAI,MAAM,SAAS;IAAE,MAAM;IAAsB,KAAK;GAAiB,GAAG,kBAAkB,CAAC;EAC9I;;EAEA,SAAgB,4BAA4B,OAAO;GAC/C,MAAM,CAAC,MAAM,YAAA,GAAWA,MAAAA,SAAAA,CAAS,KAAK;GACtC,MAAM,CAAC,UAAU,gBAAA,GAAeA,MAAAA,SAAAA,OAAe,MAAM,MAAM,YAAY,CAAC;GACxE,MAAM,CAAC,UAAU,gBAAA,GAAeA,MAAAA,SAAAA,CAAS,QAAQ;GACjD,MAAM,CAAC,OAAO,aAAA,GAAYA,MAAAA,SAAAA,CAAS,EAAE;GACrC,MAAM,CAAC,SAAS,eAAA,GAAcA,MAAAA,SAAAA,CAAS,EAAE;GACzC,MAAM,CAAC,KAAK,WAAA,GAAUA,MAAAA,SAAAA,CAAS,EAAE;GACjC,MAAM,CAAC,YAAY,kBAAA,GAAiBA,MAAAA,SAAAA,CAAS;GAC7C,MAAM,CAAC,QAAQ,cAAA,GAAaA,MAAAA,SAAAA,CAAS,KAAK;GAC1C,MAAM,CAAC,SAAS,eAAA,GAAcA,MAAAA,SAAAA,CAAS,EAAE;GACzC,CAAA,GAAA,MAAA,UAAA,OAAgB,MAAM,MAAM,gBAAgB;IAAE,YAAY,MAAM,MAAM,YAAY,CAAC;GAAG,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC;GACvG,CAAA,GAAA,MAAA,UAAA,OAAgB;IACZ,MAAM,QAAQ,SAAS;IACvB,MAAM,OAAO,OAAO,YAAY;IAChC,YAAY,IAAI;IAChB,SAAS,QAAQ,MAAM,KAAK,CAAC;IAC7B,WAAW,UAAU,MAAM,KAAK,CAAC;GACrC,GAAG,CAAC,QAAQ,CAAC;GACb,CAAA,GAAA,MAAA,UAAA,OAAgB;IACZ,IAAI,SAAS;IACb,MAAW,YAAY,SAAS,EAAE,MAAM,CAAC,QAAQ,SAAS,EAAE,CAAC,CAAC,CAAC,MAAK,aAAY;KAC5E,IAAI,QACA,cAAc,SAAS,OAAO,KAAK,SAAS,OAAO,MAAM,YAAY,QAAQ,UAAU,EAAE,cAAc,QAAQ,KAAA,CAAS;IAChI,CAAC,CAAC,CAAC,YAAY;KAAE,IAAI,QACjB,cAAc,KAAA,CAAS;IAAG,CAAC;IAC/B,aAAa;KAAE,SAAS;IAAO;GACnC,GAAG,CAAC,MAAM,aAAa,QAAQ,CAAC;GAChC,MAAM,OAAO,OAAO,UAAU;IAC1B,MAAM,eAAe;IACrB,UAAU,IAAI;IACd,WAAW,EAAE;IACb,IAAI;KACA,MAAM,MAAM,MAAM,IAAI,YAAY,QAAQ;KAC1C,MAAM,MAAM,MAAM,IAAI,aAAa,WAAW,gBAAgB,aAAa,WAAW,gBAAgB,iBAAiB,KAAK;KAC5H,MAAM,MAAM,MAAM,IAAI,aAAa,WAAW,mBAAmB,aAAa,WAAW,kBAAkB,mBAAmB,OAAO;KACrI,IAAI,IAAI,KAAK,CAAC,CAAC,SAAS,GAAG;MACvB,MAAM,WAAW,MAAM,MAAM,YAAY,IAAI;OAAE,KAAK,QAAQ;OAAW,OAAO,IAAI,KAAK;MAAE,CAAC;MAC1F,IAAI,CAAC,SAAS,OAAO,IACjB,MAAM,IAAI,MAAM,SAAS,OAAO,MAAM,OAAO;MACjD,OAAO,EAAE;MACT,cAAc,IAAI;KACtB;KACA,WAAW,KAAK;IACpB,SACO,OAAO;KACV,WAAW,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;IACrE,UACQ;KACJ,UAAU,KAAK;IACnB;GACJ;GACA,MAAM,YAAY,eAAe,KAAA,IAAY,kBAAkB,aAAa,gBAAgB;GAC5F,QAAA,GAAOC,kBAAAA,KAAAA,CAAM,MAAM;IAAE,WAAW;IAAe,UAAU,EAAA,GAACA,kBAAAA,KAAAA,CAAM,UAAU;KAAE,MAAM;KAAU,WAAW;KAAe,iBAAiB;KAAM,eAAe;MAAE,SAAQ,UAAS,CAAC,KAAK;KAAG;KAAG,UAAU,EAAA,GAACA,kBAAAA,KAAAA,CAAM,QAAQ,EAAE,UAAU,EAAA,GAACC,kBAAAA,IAAAA,CAAK,QAAQ;MAAE,WAAW;MAAgB,UAAU;KAA2B,CAAC,IAAA,GAAGA,kBAAAA,IAAAA,CAAK,QAAQ;MAAE,WAAW;MAAe,UAAU;KAA2E,CAAC,CAAC,EAAE,CAAC,IAAA,GAAGA,kBAAAA,IAAAA,CAAK,QAAQ;MAAE,eAAe;MAAQ,UAAU,OAAO,MAAM;KAAI,CAAC,CAAC;IAAE,CAAC,GAAG,QAAA,GAAOD,kBAAAA,KAAAA,CAAM,QAAQ;KAAE,WAAW;KAAe,WAAW,UAAU;MAAE,KAAU,KAAK;KAAG;KAAG,UAAU;OAACA,GAAAA,kBAAAA,KAAAA,CAAM,SAAS;OAAE,WAAW;OAAgB,UAAU;SAACC,GAAAA,kBAAAA,IAAAA,CAAK,QAAQ;SAAE,WAAW;SAAgB,UAAU;QAAW,CAAC;SAAGD,GAAAA,kBAAAA,KAAAA,CAAM,UAAU;SAAE,WAAW;SAAgB,OAAO;SAAU,WAAU,UAAS;UAAE,MAAM,OAAO,MAAM,OAAO;UAAO,YAAY,IAAI;UAAG,SAAS,QAAQ,MAAM,SAAS,KAAK,CAAC;UAAG,WAAW,UAAU,MAAM,SAAS,KAAK,CAAC;UAAG,OAAO,EAAE;SAAG;SAAG,UAAU;WAACC,GAAAA,kBAAAA,IAAAA,CAAK,UAAU;WAAE,OAAO;WAAU,UAAU;UAAgB,CAAC;WAAGA,GAAAA,kBAAAA,IAAAA,CAAK,UAAU;WAAE,OAAO;WAAU,UAAU;UAA8B,CAAC;WAAGA,GAAAA,kBAAAA,IAAAA,CAAK,UAAU;WAAE,OAAO;WAAY,UAAU;UAAwB,CAAC;SAAC;QAAE,CAAC;SAAGA,GAAAA,kBAAAA,IAAAA,CAAK,QAAQ;SAAE,WAAW;SAAe,UAAU,eAAe;QAAU,CAAC;OAAC;MAAE,CAAC;OAAGD,GAAAA,kBAAAA,KAAAA,CAAM,SAAS;OAAE,WAAW;OAAgB,UAAU;SAACA,GAAAA,kBAAAA,KAAAA,CAAM,QAAQ;SAAE,WAAW;SAAgB,UAAU,CAAC,eAAe,WAAW,UAAU;QAAE,CAAC;SAAGC,GAAAA,kBAAAA,IAAAA,CAAK,SAAS;SAAE,WAAW;SAAgB,MAAM;SAAY,cAAc;SAAO,OAAO;SAAK,WAAU,UAAS;UAAE,OAAO,MAAM,OAAO,KAAK;SAAG;SAAG,aAAa,aAAa,mBAAmB;QAAG,CAAC;SAAGD,GAAAA,kBAAAA,KAAAA,CAAM,QAAQ;SAAE,WAAW;SAAe,UAAU;UAAC;UAAmC,QAAQ;UAAW;SAA8D;QAAE,CAAC;OAAC;MAAE,CAAC;OAAGA,GAAAA,kBAAAA,KAAAA,CAAM,SAAS;OAAE,WAAW;OAAgB,UAAU;SAACC,GAAAA,kBAAAA,IAAAA,CAAK,QAAQ;SAAE,WAAW;SAAgB,UAAU;QAA2B,CAAC;SAAGD,GAAAA,kBAAAA,KAAAA,CAAM,OAAO;SAAE,WAAW;SAAsB,UAAU,EAAA,GAACC,kBAAAA,IAAAA,CAAK,SAAS;UAAE,WAAW;UAAgB,MAAM;UAAO,OAAO;UAAS,WAAU,UAAS;WAAE,WAAW,MAAM,OAAO,KAAK;UAAG;UAAG,UAAU;SAAK,CAAC,IAAA,GAAGA,kBAAAA,IAAAA,CAAK,UAAU;UAAE,MAAM;UAAU,WAAW;UAAoB,OAAO;UAA0D,eAAe;WAAE,WAAW,kBAAkB,SAAS;UAAG;UAAG,UAAU;SAAe,CAAC,CAAC;QAAE,CAAC;SAAGA,GAAAA,kBAAAA,IAAAA,CAAK,QAAQ;SAAE,WAAW;SAAe,UAAU,aAAa,WAAW,2BAA2B,aAAa,WAAW,8BAA8B;QAAsB,CAAC;OAAC;MAAE,CAAC;OAAGD,GAAAA,kBAAAA,KAAAA,CAAM,SAAS;OAAE,WAAW;OAAgB,UAAU,EAAA,GAACC,kBAAAA,IAAAA,CAAK,QAAQ;QAAE,WAAW;QAAgB,UAAU;OAAe,CAAC,IAAA,GAAGA,kBAAAA,IAAAA,CAAK,SAAS;QAAE,WAAW;QAAgB,OAAO;QAAO,WAAU,UAAS;SAAE,SAAS,MAAM,OAAO,KAAK;QAAG;QAAG,UAAU;OAAK,CAAC,CAAC;MAAE,CAAC;OAAGD,GAAAA,kBAAAA,KAAAA,CAAM,OAAO;OAAE,WAAW;OAAkB,UAAU,EAAA,GAACC,kBAAAA,IAAAA,CAAK,KAAK;QAAE,WAAW;QAAiB,MAAM;QAAU,UAAU,WAAW;OAAU,CAAC,IAAA,GAAGA,kBAAAA,IAAAA,CAAK,UAAU;QAAE,WAAW;QAAe,MAAM;QAAU,UAAU,UAAU,CAAC,SAAS;QAAU,UAAU,SAAS,SAAS;OAAK,CAAC,CAAC;MAAE,CAAC;KAAC;IAAE,CAAC,IAAI,IAAI;GAAE,CAAC;EAC/jG;;EAEA,SAAgB,mBAAmB,OAAO;GACtC,MAAM,aAAa,SAAS,MAAM,KAAK;GACvC,MAAM,CAAC,KAAK,WAAA,GAAUF,MAAAA,SAAAA,CAAS;GAC/B,MAAM,CAAC,OAAO,aAAA,GAAYA,MAAAA,SAAAA,CAAS;GACnC,CAAA,GAAA,MAAA,UAAA,OAAgB;IACZ,IAAI,eAAe,KAAA,GACf;IACJ,MAAM,aAAa,IAAI,gBAAgB;IACvC,IAAI;IACJ,MAAW,aAAa;KAAE,QAAQ;KAAQ,QAAQ,WAAW;KAAQ,SAAS,EAAE,gBAAgB,mBAAmB;KAAG,MAAM,KAAK,UAAU,EAAE,WAAW,CAAC;IAAE,CAAC,CAAC,CAAC,KAAK,OAAO,aAAa;KAAE,IAAI,CAAC,SAAS,IACnM,MAAM,IAAI,MAAM,WAAW,OAAO,SAAS,MAAM,EAAE,EAAE;KAAG,MAAM,OAAO,MAAM,SAAS,KAAK;KAAG,IAAI,WAAW,OAAO,SAClH;KAAQ,YAAY,IAAI,gBAAgB,IAAI;KAAG,OAAO,SAAS;IAAG,CAAC,CAAC,CAAC,OAAM,UAAS;KAAE,IAAI,CAAC,WAAW,OAAO,SAC7G,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;IAAG,CAAC;IACvE,aAAa;KAAE,WAAW,MAAM;KAAG,IAAI,cAAc,KAAA,GACjD,IAAI,gBAAgB,SAAS;IAAG;GACxC,GAAG,CAAC,YAAY,YAAY,CAAC;GAC7B,IAAI,eAAe,KAAA,GACf,QAAA,GAAOE,kBAAAA,IAAAA,CAAK,OAAO;IAAE,WAAW;IAAkB,UAAU;GAA6C,CAAC;GAC9G,QAAA,GAAOD,kBAAAA,KAAAA,CAAM,WAAW;IAAE,WAAW;IAAiB,cAAc;IAAmB,UAAU;MAACC,GAAAA,kBAAAA,IAAAA,CAAK,OAAO;MAAE,WAAW;MAAuB,UAAU;KAAkB,CAAC;KAAG,UAAU,KAAA,KAAA,GAAYA,kBAAAA,IAAAA,CAAK,OAAO;MAAE,WAAW;MAAgB,UAAU;KAAM,CAAC,IAAI;KAAM,QAAQ,KAAA,KAAa,UAAU,KAAA,KAAA,GAAYA,kBAAAA,IAAAA,CAAK,OAAO;MAAE,WAAW;MAAkB,UAAU;KAA6C,CAAC,IAAI;KAAM,QAAQ,KAAA,KAAA,GAAYA,kBAAAA,IAAAA,CAAK,OAAO;MAAE,WAAW;MAAgB,KAAK;MAAK,KAAK,WAAW,QAAQ;KAAkB,CAAC,IAAI;IAAI;GAAE,CAAC;EACriB;EACA,SAAS,QAAQ,UAAU,OAAO;GAC9B,MAAM,SAAS,aAAa,WAAW,OAAO,cAAc,aAAa,WAAW,OAAO,cAAc,OAAO;GAChH,OAAO,OAAO,WAAW,YAAY,OAAO,SAAS,IAAI,SAAS,eAAe;EACrF;EACA,SAAS,UAAU,UAAU,OAAO;GAChC,MAAM,SAAS,aAAa,WAAW,OAAO,iBAAiB,aAAa,WAAW,OAAO,gBAAgB,OAAO;GACrH,OAAO,OAAO,WAAW,YAAY,OAAO,SAAS,IAAI,SAAS,kBAAkB;EACxF;EACA,SAAS,SAAS,OAAO;GAAE,IAAI,EAAE,UAAU,UAAU,MAAM,YAAY,SAAS,WAC5E,OAAO,KAAA;GAAW,MAAM,QAAQ,MAAM,WAAW,SAAS,MAAK,SAAQ,KAAK,SAAS,OAAO;GAAG,OAAO,OAAO,SAAS,UAAU,MAAM,aAAa,KAAA;EAAW"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-image-gen",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "
|
|
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
|
-
"
|
|
73
|
+
"volcengine",
|
|
74
|
+
"byok",
|
|
66
75
|
"cordis"
|
|
67
76
|
],
|
|
68
77
|
"peerDependencies": {
|