@dickpy/dsh-imagegen 1.2.2 → 1.2.3
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.md +14 -2
- package/docs/images/community-qq.png +0 -0
- package/lib/client.js +222 -215
- package/lib/client.js.map +1 -1
- package/lib/index.js +60 -4
- package/package.json +2 -2
- package/src/client/ImageGenPanel.tsx +1 -1
- package/src/client/locales.ts +2 -2
- package/src/engine.ts +86 -1
- package/src/image-models.ts +1 -1
- package/src/index.ts +1 -1
- package/src/protocol.ts +6 -4
package/lib/index.js
CHANGED
|
@@ -16,7 +16,7 @@ import { defineTool } from "@deepseek-ai/dsh-tools";
|
|
|
16
16
|
/** Settings namespace this plugin owns (host settings seam + bridge). */
|
|
17
17
|
const IMAGEGEN_SETTINGS_NAMESPACE = "dsh-imagegen";
|
|
18
18
|
/** Published package version shared by the host updater and the client UI. */
|
|
19
|
-
const PLUGIN_VERSION = "1.2.
|
|
19
|
+
const PLUGIN_VERSION = "1.2.3";
|
|
20
20
|
/** Same-origin route family (loopback-only, mirroring the dsh-ssh fence). */
|
|
21
21
|
const SETTINGS_API = {
|
|
22
22
|
describe: "/api/dsh-imagegen/settings/describe",
|
|
@@ -140,7 +140,14 @@ async function enhancePrompt(config, prompt) {
|
|
|
140
140
|
* `/models` exposes candidates only: the configured list is the explicit
|
|
141
141
|
* allow-list because OpenAI-compatible gateways rarely advertise modalities.
|
|
142
142
|
*/
|
|
143
|
-
const DEFAULT_IMAGE_MODELS = [
|
|
143
|
+
const DEFAULT_IMAGE_MODELS = [
|
|
144
|
+
"gpt-image-2",
|
|
145
|
+
"grok-imagine-image",
|
|
146
|
+
"nanobanana2",
|
|
147
|
+
"nanobanana2-lite",
|
|
148
|
+
"nanobanana-pro",
|
|
149
|
+
"seedream-5.0-pro"
|
|
150
|
+
];
|
|
144
151
|
/** Normalize user-entered model identifiers and retain a usable legacy default. */
|
|
145
152
|
function normalizeImageModels(value) {
|
|
146
153
|
const candidates = Array.isArray(value) ? value : [];
|
|
@@ -183,6 +190,24 @@ const DALLE3_SIZES = /* @__PURE__ */ new Set([
|
|
|
183
190
|
function isGrokImagine(model) {
|
|
184
191
|
return /^grok-imagine(?:-|$)/.test(model);
|
|
185
192
|
}
|
|
193
|
+
/** Whether the model belongs to the Google Nano Banana family (nanobanana2 /
|
|
194
|
+
* nanobanana2-lite / nanobanana-pro, plus the official Gemini image IDs the
|
|
195
|
+
* gateways expose). OpenAI-compatible gateways serve these with their own
|
|
196
|
+
* aspect_ratio / image_size vocabulary instead of the OpenAI size/quality
|
|
197
|
+
* passthrough. */
|
|
198
|
+
function isNanoBanana(model) {
|
|
199
|
+
if (/^nanobanana/i.test(model)) return true;
|
|
200
|
+
return model === "gemini-3-pro-image" || model === "gemini-3-pro-image-preview" || model === "gemini-3.1-flash-image" || model === "gemini-3.1-flash-image-preview" || model === "gemini-3.1-flash-lite-image" || model === "gemini-2.5-flash-image";
|
|
201
|
+
}
|
|
202
|
+
/** Whether the model belongs to the ByteDance Seedream family (seedream-5.0-pro,
|
|
203
|
+
* seedream-5.0, seedream-4.x, doubao-seedream-…). OpenAI-compatible gateways
|
|
204
|
+
* serve Seedream through a unified generate-and-edit architecture:
|
|
205
|
+
* generation AND editing both go to /images/generations, reference images are
|
|
206
|
+
* a JSON URL / data-URL array, and the clarity tier is `resolution` while
|
|
207
|
+
* `size` carries the aspect ratio (or exact pixels). */
|
|
208
|
+
function isSeedream(model) {
|
|
209
|
+
return /^(?:doubao-)?seedream/i.test(model);
|
|
210
|
+
}
|
|
186
211
|
/** The panel's aspect ratios mapped to the closest OpenAI pixel size
|
|
187
212
|
* (gpt-image-2 / generic OpenAI-compatible endpoints). */
|
|
188
213
|
const OPENAI_SIZE_BY_RATIO = {
|
|
@@ -273,6 +298,18 @@ function effectiveParams(request) {
|
|
|
273
298
|
...request.quality !== "" && request.quality !== "auto" ? { resolution: request.quality === "4k" ? "2k" : request.quality } : {},
|
|
274
299
|
response_format: "b64_json"
|
|
275
300
|
};
|
|
301
|
+
if (isNanoBanana(model)) return {
|
|
302
|
+
model,
|
|
303
|
+
...request.size !== "" && request.size !== "auto" ? { aspect_ratio: request.size } : {},
|
|
304
|
+
...request.quality !== "" && request.quality !== "auto" ? { image_size: request.quality.toUpperCase() } : {},
|
|
305
|
+
response_format: "b64_json"
|
|
306
|
+
};
|
|
307
|
+
if (isSeedream(model)) return {
|
|
308
|
+
model,
|
|
309
|
+
...request.size !== "" && request.size !== "auto" ? { size: request.size } : {},
|
|
310
|
+
...request.quality !== "" && request.quality !== "auto" ? { resolution: request.quality === "4k" ? "2K" : request.quality.toUpperCase() } : {},
|
|
311
|
+
response_format: "b64_json"
|
|
312
|
+
};
|
|
276
313
|
return {
|
|
277
314
|
model,
|
|
278
315
|
...request.size !== "" && request.size !== "auto" && OPENAI_SIZE_BY_RATIO[request.size] !== void 0 ? { size: OPENAI_SIZE_BY_RATIO[request.size] } : {},
|
|
@@ -358,6 +395,24 @@ async function requestOneImage(baseUrl, upstream, request, params, signal) {
|
|
|
358
395
|
...params.aspect_ratio !== void 0 ? { aspect_ratio: params.aspect_ratio } : {},
|
|
359
396
|
response_format: "b64_json"
|
|
360
397
|
});
|
|
398
|
+
} else if (isNanoBanana(params.model)) {
|
|
399
|
+
const form = new FormData();
|
|
400
|
+
form.append("image", new Blob([bytes], { type: parsed.mime }), `reference.${extensionOf$2(parsed.mime)}`);
|
|
401
|
+
form.append("prompt", request.prompt);
|
|
402
|
+
form.append("model", params.model);
|
|
403
|
+
if (params.aspect_ratio !== void 0) form.append("aspect_ratio", params.aspect_ratio);
|
|
404
|
+
if (params.image_size !== void 0) form.append("image_size", params.image_size);
|
|
405
|
+
body = form;
|
|
406
|
+
} else if (isSeedream(params.model)) {
|
|
407
|
+
headers["content-type"] = "application/json";
|
|
408
|
+
body = JSON.stringify({
|
|
409
|
+
model: params.model,
|
|
410
|
+
prompt: request.prompt,
|
|
411
|
+
image: [request.image],
|
|
412
|
+
...params.size !== void 0 ? { size: params.size } : {},
|
|
413
|
+
...params.resolution !== void 0 ? { resolution: params.resolution } : {},
|
|
414
|
+
response_format: "b64_json"
|
|
415
|
+
});
|
|
361
416
|
} else {
|
|
362
417
|
const form = new FormData();
|
|
363
418
|
form.append("image", new Blob([bytes], { type: parsed.mime }), `reference.${extensionOf$2(parsed.mime)}`);
|
|
@@ -378,7 +433,8 @@ async function requestOneImage(baseUrl, upstream, request, params, signal) {
|
|
|
378
433
|
const budget = requestSignal(signal, UPSTREAM_TIMEOUT_MS);
|
|
379
434
|
let response;
|
|
380
435
|
try {
|
|
381
|
-
|
|
436
|
+
const endpoint = request.mode === "edit" && !isSeedream(params.model) ? "/images/edits" : "/images/generations";
|
|
437
|
+
response = await fetch(`${baseUrl}${endpoint}`, {
|
|
382
438
|
method: "POST",
|
|
383
439
|
headers,
|
|
384
440
|
body,
|
|
@@ -2623,7 +2679,7 @@ const DEFAULT_ALLOW_AGENT_IMAGE_GENERATION = true;
|
|
|
2623
2679
|
/** Order of the announcement section within the tool-guidance band. */
|
|
2624
2680
|
const SECTION_ORDER = 150;
|
|
2625
2681
|
/** Model-facing announcement: plugin presence, capabilities, and limits. */
|
|
2626
|
-
const IMAGEGEN_GUIDANCE = "本机已安装 dsh-imagegen 插件(DSH AI 生图):侧边栏「AI 生图」入口。能力:对接 OpenAI 兼容图像生成 API,模型由用户在「设置 → 插件 → AI 生图」中检测或手动配置的生图模型列表决定;支持文生图(/images/generations)与图生图(/images/edits,上传参考图,grok-imagine 模型按官方 JSON image_url
|
|
2682
|
+
const IMAGEGEN_GUIDANCE = "本机已安装 dsh-imagegen 插件(DSH AI 生图):侧边栏「AI 生图」入口。能力:对接 OpenAI 兼容图像生成 API,模型由用户在「设置 → 插件 → AI 生图」中检测或手动配置的生图模型列表决定;支持文生图(/images/generations)与图生图(/images/edits,上传参考图,grok-imagine 模型按官方 JSON image_url 协议发送,nanobanana 系列按 aspect_ratio / image_size 参数协议发送;seedream 系列统一走 /images/generations,参考图以 JSON image 数组发送)。API 地址与密钥在 GUI 设置中配置,密钥仅存于本机设置文档;生成请求由本地宿主代理转发,结果以 base64 返回面板,可预览与下载。模型只能使用已配置的生图模型;模型出现在 /models 中不等于其网关原生支持生图协议,遇到 Qwen、Gemini 等非 OpenAI 生图协议时应如实说明上游兼容性。可一键把满意的图片加入「画廊」。内置「提示词模板库」(面板提示词框左下角「模板库」按钮):打包 awesome-gpt-image-2 的数百条提示词案例,可搜索、筛选与复用。Agent 可直接调用 `generate_image` 提交文生图,也可用 `edit_image` 图生图;默认保持工具调用等待直到任务完成,完成图片直接作为工具结果附件返回,不会额外伪造用户消息。若明确需要后台执行,可传 `wait_for_completion: false`,之后再用 `get_image_generation_task` 查询;不要反复轮询。限制:生成消耗上游 API 额度;图片内容由上游模型生成,可能不符合预期或包含不适宜内容;api_key 以明文存储在设置文档中;参考图会发送至所配置的 API 服务;模板库在线刷新与参考图首次加载需要访问 vibeui.top。用户提到「生图 / 绘画 / 生成图片 / 文生图 / 图生图 / 画廊 / 提示词模板」时即指本插件,请据此协作。";
|
|
2627
2683
|
/** Add the live allow-list so an Agent can honor a user's model choice. */
|
|
2628
2684
|
function guidanceFor(imageModels) {
|
|
2629
2685
|
return `${IMAGEGEN_GUIDANCE} 当前允许调用的生图模型:${imageModels.join("、")}。用户指定其中某个模型时,工具参数 model 必须使用该精确名称;未指定时使用列表中的第一个。`;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dickpy/dsh-imagegen",
|
|
3
|
-
"description": "AI 鐢熷浘 (image generation) plugin for the dsh web GUI: text-to-image and image-to-image through a configurable OpenAI-compatible endpoint (gpt-image-2 / grok-imagine-image / dall-e-3, with native xAI Grok Imagine request shaping), with a settings card for api_url / api_key and a sidebar entry opening a split-pane generation studio.",
|
|
4
|
-
"version": "1.2.
|
|
3
|
+
"description": "AI 鐢熷浘 (image generation) plugin for the dsh web GUI: text-to-image and image-to-image through a configurable OpenAI-compatible endpoint (gpt-image-2 / grok-imagine-image / nanobanana series / seedream-5.0-pro / dall-e-3, with native xAI Grok Imagine, Google Nano Banana and ByteDance Seedream request shaping), with a settings card for api_url / api_key and a sidebar entry opening a split-pane generation studio.",
|
|
4
|
+
"version": "1.2.3",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"exports": {
|
|
@@ -1127,7 +1127,7 @@ export function ImageGenPanel(props: {
|
|
|
1127
1127
|
<span className={css.galleryBadge}>{entry.mode === 'edit' ? tt('mode.edit') : tt('mode.text')}</span>
|
|
1128
1128
|
</button>
|
|
1129
1129
|
<div className={css.galleryCardFooter}>
|
|
1130
|
-
<span className={css.galleryAvatar}>{entry.model.startsWith('grok') ? 'G' : 'D'}</span>
|
|
1130
|
+
<span className={css.galleryAvatar}>{entry.model.toLowerCase().startsWith('nanobanana') ? 'N' : entry.model.toLowerCase().startsWith('seedream') ? 'S' : entry.model.startsWith('grok') ? 'G' : 'D'}</span>
|
|
1131
1131
|
<span className={css.galleryCardInfo}>
|
|
1132
1132
|
<strong>{entry.prompt || tt('gallery.untitled')}</strong>
|
|
1133
1133
|
<small>{entry.model} · {normalizeSize(entry.size)} · {formatTime(entry.createdAt)}</small>
|
package/src/client/locales.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
export const zh = {
|
|
6
6
|
'entry.label': 'AI 生图',
|
|
7
|
-
'entry.tooltip': 'AI 生图面板(gpt-image-2 / grok-imagine-image
|
|
7
|
+
'entry.tooltip': 'AI 生图面板(gpt-image-2 / grok-imagine-image / nanobanana / seedream 系列)',
|
|
8
8
|
'panel.title': 'AI 生图',
|
|
9
9
|
'panel.githubTip': '觉得好用或有建议?欢迎来 GitHub 提 issues、点个 star 支持一下!',
|
|
10
10
|
// mode
|
|
@@ -253,7 +253,7 @@ export const zh = {
|
|
|
253
253
|
|
|
254
254
|
export const en: Record<keyof typeof zh, string> = {
|
|
255
255
|
'entry.label': 'AI Image',
|
|
256
|
-
'entry.tooltip': 'AI image generation studio (gpt-image-2 / grok-imagine-image)',
|
|
256
|
+
'entry.tooltip': 'AI image generation studio (gpt-image-2 / grok-imagine-image / nanobanana / seedream family)',
|
|
257
257
|
'panel.title': 'AI Image',
|
|
258
258
|
'panel.githubTip': 'Like it or have suggestions? Head to GitHub to open issues and star us!',
|
|
259
259
|
'mode.text': 'Text to Image',
|
package/src/engine.ts
CHANGED
|
@@ -50,6 +50,31 @@ function isGrokImagine(model: string): boolean {
|
|
|
50
50
|
return /^grok-imagine(?:-|$)/.test(model)
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
/** Whether the model belongs to the Google Nano Banana family (nanobanana2 /
|
|
54
|
+
* nanobanana2-lite / nanobanana-pro, plus the official Gemini image IDs the
|
|
55
|
+
* gateways expose). OpenAI-compatible gateways serve these with their own
|
|
56
|
+
* aspect_ratio / image_size vocabulary instead of the OpenAI size/quality
|
|
57
|
+
* passthrough. */
|
|
58
|
+
function isNanoBanana(model: string): boolean {
|
|
59
|
+
if (/^nanobanana/i.test(model)) return true
|
|
60
|
+
return (
|
|
61
|
+
model === 'gemini-3-pro-image' || model === 'gemini-3-pro-image-preview' ||
|
|
62
|
+
model === 'gemini-3.1-flash-image' || model === 'gemini-3.1-flash-image-preview' ||
|
|
63
|
+
model === 'gemini-3.1-flash-lite-image' ||
|
|
64
|
+
model === 'gemini-2.5-flash-image'
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** Whether the model belongs to the ByteDance Seedream family (seedream-5.0-pro,
|
|
69
|
+
* seedream-5.0, seedream-4.x, doubao-seedream-…). OpenAI-compatible gateways
|
|
70
|
+
* serve Seedream through a unified generate-and-edit architecture:
|
|
71
|
+
* generation AND editing both go to /images/generations, reference images are
|
|
72
|
+
* a JSON URL / data-URL array, and the clarity tier is `resolution` while
|
|
73
|
+
* `size` carries the aspect ratio (or exact pixels). */
|
|
74
|
+
function isSeedream(model: string): boolean {
|
|
75
|
+
return /^(?:doubao-)?seedream/i.test(model)
|
|
76
|
+
}
|
|
77
|
+
|
|
53
78
|
/** The panel's aspect ratios mapped to the closest OpenAI pixel size
|
|
54
79
|
* (gpt-image-2 / generic OpenAI-compatible endpoints). */
|
|
55
80
|
const OPENAI_SIZE_BY_RATIO: Readonly<Record<string, string>> = {
|
|
@@ -136,6 +161,7 @@ function effectiveParams(request: GenerateRequest): {
|
|
|
136
161
|
quality?: string
|
|
137
162
|
detail?: string
|
|
138
163
|
aspect_ratio?: string
|
|
164
|
+
image_size?: string
|
|
139
165
|
resolution?: string
|
|
140
166
|
response_format?: string
|
|
141
167
|
} {
|
|
@@ -163,6 +189,39 @@ function effectiveParams(request: GenerateRequest): {
|
|
|
163
189
|
response_format: 'b64_json',
|
|
164
190
|
}
|
|
165
191
|
}
|
|
192
|
+
// Google Nano Banana: the panel's aspect ratios are sent as-is (the family
|
|
193
|
+
// documents 1:1 … 21:9 natively), the clarity tiers become image_size
|
|
194
|
+
// (1K / 2K / 4K — Gen 1 and 2-Lite are 1K-only upstream, but which gateway
|
|
195
|
+
// rejects higher tiers is its own call), and base64 output keeps any signed
|
|
196
|
+
// result URLs from expiring before the host downloads them.
|
|
197
|
+
if (isNanoBanana(model)) {
|
|
198
|
+
return {
|
|
199
|
+
model,
|
|
200
|
+
...request.size !== '' && request.size !== 'auto'
|
|
201
|
+
? { aspect_ratio: request.size }
|
|
202
|
+
: {},
|
|
203
|
+
...request.quality !== '' && request.quality !== 'auto'
|
|
204
|
+
? { image_size: request.quality.toUpperCase() }
|
|
205
|
+
: {},
|
|
206
|
+
response_format: 'b64_json',
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
// ByteDance Seedream: OpenAI-compatible gateways accept the aspect ratio in
|
|
210
|
+
// `size` directly and the clarity tiers as `resolution` (1K / 2K; the 5.0-pro
|
|
211
|
+
// tier caps at 2K, so 4k falls back to 2K). There is no quality/detail knob,
|
|
212
|
+
// and edits reuse /images/generations with an image array (see below).
|
|
213
|
+
if (isSeedream(model)) {
|
|
214
|
+
return {
|
|
215
|
+
model,
|
|
216
|
+
...request.size !== '' && request.size !== 'auto'
|
|
217
|
+
? { size: request.size }
|
|
218
|
+
: {},
|
|
219
|
+
...request.quality !== '' && request.quality !== 'auto'
|
|
220
|
+
? { resolution: request.quality === '4k' ? '2K' : request.quality.toUpperCase() }
|
|
221
|
+
: {},
|
|
222
|
+
response_format: 'b64_json',
|
|
223
|
+
}
|
|
224
|
+
}
|
|
166
225
|
// OpenAI-compatible endpoints: nearest pixel size, clarity tiers mapped to
|
|
167
226
|
// the quality levels (1k→low / 2k→medium / 4k→high), detail passthrough.
|
|
168
227
|
return {
|
|
@@ -268,6 +327,28 @@ async function requestOneImage(
|
|
|
268
327
|
...params.aspect_ratio !== undefined ? { aspect_ratio: params.aspect_ratio } : {},
|
|
269
328
|
response_format: 'b64_json',
|
|
270
329
|
})
|
|
330
|
+
} else if (isNanoBanana(params.model)) {
|
|
331
|
+
// Nano Banana OpenAI-compatible gateways accept the standard multipart
|
|
332
|
+
// edit upload, with the family's own aspect_ratio / image_size knobs.
|
|
333
|
+
const form = new FormData()
|
|
334
|
+
form.append('image', new Blob([bytes], { type: parsed.mime }), `reference.${extensionOf(parsed.mime)}`)
|
|
335
|
+
form.append('prompt', request.prompt)
|
|
336
|
+
form.append('model', params.model)
|
|
337
|
+
if (params.aspect_ratio !== undefined) form.append('aspect_ratio', params.aspect_ratio)
|
|
338
|
+
if (params.image_size !== undefined) form.append('image_size', params.image_size)
|
|
339
|
+
body = form
|
|
340
|
+
} else if (isSeedream(params.model)) {
|
|
341
|
+
// Seedream unifies generation and editing on /images/generations; the
|
|
342
|
+
// reference image is a JSON URL / data-URL array, never multipart.
|
|
343
|
+
headers['content-type'] = 'application/json'
|
|
344
|
+
body = JSON.stringify({
|
|
345
|
+
model: params.model,
|
|
346
|
+
prompt: request.prompt,
|
|
347
|
+
image: [request.image],
|
|
348
|
+
...params.size !== undefined ? { size: params.size } : {},
|
|
349
|
+
...params.resolution !== undefined ? { resolution: params.resolution } : {},
|
|
350
|
+
response_format: 'b64_json',
|
|
351
|
+
})
|
|
271
352
|
} else {
|
|
272
353
|
const form = new FormData()
|
|
273
354
|
form.append('image', new Blob([bytes], { type: parsed.mime }), `reference.${extensionOf(parsed.mime)}`)
|
|
@@ -286,7 +367,11 @@ async function requestOneImage(
|
|
|
286
367
|
const budget = requestSignal(signal, UPSTREAM_TIMEOUT_MS)
|
|
287
368
|
let response: Response
|
|
288
369
|
try {
|
|
289
|
-
|
|
370
|
+
// Seedream has no /images/edits endpoint: both modes hit generations.
|
|
371
|
+
const endpoint = request.mode === 'edit' && !isSeedream(params.model)
|
|
372
|
+
? '/images/edits'
|
|
373
|
+
: '/images/generations'
|
|
374
|
+
response = await fetch(`${baseUrl}${endpoint}`, {
|
|
290
375
|
method: 'POST',
|
|
291
376
|
headers,
|
|
292
377
|
body,
|
package/src/image-models.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* allow-list because OpenAI-compatible gateways rarely advertise modalities.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
export const DEFAULT_IMAGE_MODELS = ['gpt-image-2', 'grok-imagine-image'] as const
|
|
7
|
+
export const DEFAULT_IMAGE_MODELS = ['gpt-image-2', 'grok-imagine-image', 'nanobanana2', 'nanobanana2-lite', 'nanobanana-pro', 'seedream-5.0-pro'] as const
|
|
8
8
|
|
|
9
9
|
/** Normalize user-entered model identifiers and retain a usable legacy default. */
|
|
10
10
|
export function normalizeImageModels(value: unknown): string[] {
|
package/src/index.ts
CHANGED
|
@@ -83,7 +83,7 @@ const DEFAULT_ALLOW_AGENT_IMAGE_GENERATION = true
|
|
|
83
83
|
const SECTION_ORDER = 150
|
|
84
84
|
|
|
85
85
|
/** Model-facing announcement: plugin presence, capabilities, and limits. */
|
|
86
|
-
export const IMAGEGEN_GUIDANCE = '本机已安装 dsh-imagegen 插件(DSH AI 生图):侧边栏「AI 生图」入口。能力:对接 OpenAI 兼容图像生成 API,模型由用户在「设置 → 插件 → AI 生图」中检测或手动配置的生图模型列表决定;支持文生图(/images/generations)与图生图(/images/edits,上传参考图,grok-imagine 模型按官方 JSON image_url
|
|
86
|
+
export const IMAGEGEN_GUIDANCE = '本机已安装 dsh-imagegen 插件(DSH AI 生图):侧边栏「AI 生图」入口。能力:对接 OpenAI 兼容图像生成 API,模型由用户在「设置 → 插件 → AI 生图」中检测或手动配置的生图模型列表决定;支持文生图(/images/generations)与图生图(/images/edits,上传参考图,grok-imagine 模型按官方 JSON image_url 协议发送,nanobanana 系列按 aspect_ratio / image_size 参数协议发送;seedream 系列统一走 /images/generations,参考图以 JSON image 数组发送)。API 地址与密钥在 GUI 设置中配置,密钥仅存于本机设置文档;生成请求由本地宿主代理转发,结果以 base64 返回面板,可预览与下载。模型只能使用已配置的生图模型;模型出现在 /models 中不等于其网关原生支持生图协议,遇到 Qwen、Gemini 等非 OpenAI 生图协议时应如实说明上游兼容性。可一键把满意的图片加入「画廊」。内置「提示词模板库」(面板提示词框左下角「模板库」按钮):打包 awesome-gpt-image-2 的数百条提示词案例,可搜索、筛选与复用。Agent 可直接调用 `generate_image` 提交文生图,也可用 `edit_image` 图生图;默认保持工具调用等待直到任务完成,完成图片直接作为工具结果附件返回,不会额外伪造用户消息。若明确需要后台执行,可传 `wait_for_completion: false`,之后再用 `get_image_generation_task` 查询;不要反复轮询。限制:生成消耗上游 API 额度;图片内容由上游模型生成,可能不符合预期或包含不适宜内容;api_key 以明文存储在设置文档中;参考图会发送至所配置的 API 服务;模板库在线刷新与参考图首次加载需要访问 vibeui.top。用户提到「生图 / 绘画 / 生成图片 / 文生图 / 图生图 / 画廊 / 提示词模板」时即指本插件,请据此协作。'
|
|
87
87
|
|
|
88
88
|
/** Add the live allow-list so an Agent can honor a user's model choice. */
|
|
89
89
|
function guidanceFor(imageModels: string[]): string {
|
package/src/protocol.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
export const IMAGEGEN_SETTINGS_NAMESPACE = 'dsh-imagegen'
|
|
9
9
|
|
|
10
10
|
/** Published package version shared by the host updater and the client UI. */
|
|
11
|
-
export const PLUGIN_VERSION = '1.2.
|
|
11
|
+
export const PLUGIN_VERSION = '1.2.3'
|
|
12
12
|
|
|
13
13
|
/** Same-origin route family (loopback-only, mirroring the dsh-ssh fence). */
|
|
14
14
|
export const SETTINGS_API = {
|
|
@@ -145,11 +145,13 @@ export interface GenerateRequest {
|
|
|
145
145
|
/** The prompt. Upstream providers may impose their own length limits. */
|
|
146
146
|
prompt: string
|
|
147
147
|
/** Canvas size as an aspect ratio: 'auto' or e.g. '1:1' / '16:9' / '21:9'.
|
|
148
|
-
* The host maps it onto each model's own vocabulary (aspect_ratio for Grok
|
|
149
|
-
* the closest pixel size for
|
|
148
|
+
* The host maps it onto each model's own vocabulary (aspect_ratio for Grok
|
|
149
|
+
* and Nano Banana, size-aspect for Seedream, the closest pixel size for
|
|
150
|
+
* OpenAI-compatible endpoints). */
|
|
150
151
|
size: string
|
|
151
152
|
/** Clarity tier: 'auto' | '1k' | '2k' | '4k'. The host maps it onto the
|
|
152
|
-
* model's own vocabulary (resolution for Grok,
|
|
153
|
+
* model's own vocabulary (resolution for Grok / Seedream, image_size for
|
|
154
|
+
* Nano Banana, quality for OpenAI). */
|
|
153
155
|
quality: string
|
|
154
156
|
/** Number of images, 1-4. */
|
|
155
157
|
n: number
|