@dickpy/dsh-imagegen 1.5.7 → 1.5.8
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 +5 -4
- package/lib/client.js +36358 -845
- package/lib/client.js.map +1 -1
- package/lib/index.js +3 -3
- package/package.json +82 -81
- package/src/canvas-store.ts +376 -375
- package/src/client/CanvasWorkspace.tsx +417 -77
- package/src/client/canvas-workspace.module.css +157 -33
- package/src/client/locales.ts +21 -12
- package/src/protocol.ts +580 -580
package/src/protocol.ts
CHANGED
|
@@ -1,580 +1,580 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Wire contract shared by the host and client halves of dsh-imagegen: the
|
|
3
|
-
* settings namespace, the route paths, and the generate payload/result shapes.
|
|
4
|
-
* Pure types + constants 鈥?safe for the client bundle to inline.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
/** Settings namespace this plugin owns (host settings seam + bridge). */
|
|
8
|
-
export const IMAGEGEN_SETTINGS_NAMESPACE = 'dsh-imagegen'
|
|
9
|
-
|
|
10
|
-
/** Published package version shared by the host updater and the client UI. */
|
|
11
|
-
export const PLUGIN_VERSION = '1.5.
|
|
12
|
-
|
|
13
|
-
/** Same-origin route family (loopback-only, mirroring the dsh-ssh fence). */
|
|
14
|
-
export const SETTINGS_API = {
|
|
15
|
-
describe: '/api/dsh-imagegen/settings/describe',
|
|
16
|
-
mutate: '/api/dsh-imagegen/settings/mutate',
|
|
17
|
-
} as const
|
|
18
|
-
|
|
19
|
-
/** The image-generation proxy route. */
|
|
20
|
-
export const GENERATE_API = '/api/dsh-imagegen/generate'
|
|
21
|
-
|
|
22
|
-
/** Host-mediated OpenAI-compatible prompt enhancement endpoints. */
|
|
23
|
-
export const PROMPT_ENHANCE_API = {
|
|
24
|
-
models: '/api/dsh-imagegen/prompt-enhance/models',
|
|
25
|
-
enhance: '/api/dsh-imagegen/prompt-enhance',
|
|
26
|
-
} as const
|
|
27
|
-
|
|
28
|
-
/** Host-mediated candidate discovery for the configured image API. */
|
|
29
|
-
export const IMAGE_MODEL_API = {
|
|
30
|
-
models: '/api/dsh-imagegen/image-models',
|
|
31
|
-
} as const
|
|
32
|
-
|
|
33
|
-
/** Host-served built-in provider catalog (channels the user can instantiate). */
|
|
34
|
-
export const PRESETS_API = '/api/dsh-imagegen/presets' as const
|
|
35
|
-
|
|
36
|
-
/** Loopback-only image reader for Agent tool-result previews. */
|
|
37
|
-
export const AGENT_IMAGE_API = '/api/dsh-imagegen/agent-image' as const
|
|
38
|
-
|
|
39
|
-
/** Store the current composer image for the direct edit_image command. */
|
|
40
|
-
export const CONVERSATION_IMAGE_API = '/api/dsh-imagegen/conversation-image' as const
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Host-computed per-channel usage counters (generation-count badges in the
|
|
44
|
-
* settings card): entries are tallied from the persisted history and gallery
|
|
45
|
-
* by channel + model alias.
|
|
46
|
-
*/
|
|
47
|
-
export const USAGE_API = '/api/dsh-imagegen/usage' as const
|
|
48
|
-
|
|
49
|
-
/** Host-resident generation queue endpoints. */
|
|
50
|
-
export const TASK_API = {
|
|
51
|
-
submit: '/api/dsh-imagegen/tasks/submit',
|
|
52
|
-
list: '/api/dsh-imagegen/tasks/list',
|
|
53
|
-
cancel: '/api/dsh-imagegen/tasks/cancel',
|
|
54
|
-
retry: '/api/dsh-imagegen/tasks/retry',
|
|
55
|
-
} as const
|
|
56
|
-
|
|
57
|
-
/** Reveal the host data directory (saved images) in the OS file manager. */
|
|
58
|
-
export const DATA_FOLDER_API = '/api/dsh-imagegen/data-folder/open' as const
|
|
59
|
-
|
|
60
|
-
/** Probe the configured S3-compatible object storage. */
|
|
61
|
-
export const STORAGE_API = {
|
|
62
|
-
test: '/api/dsh-imagegen/storage/test',
|
|
63
|
-
} as const
|
|
64
|
-
|
|
65
|
-
/** Host-mediated GitHub Release update routes. */
|
|
66
|
-
export const UPDATE_API = {
|
|
67
|
-
check: '/api/dsh-imagegen/update/check',
|
|
68
|
-
apply: '/api/dsh-imagegen/update/apply',
|
|
69
|
-
} as const
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Same-origin route family for the host-persisted generation history. Images
|
|
73
|
-
* live as files under ~/.dsh/dsh-imagegen/images/ and are served back through
|
|
74
|
-
* the `image` prefix route, so list responses carry metadata only (never
|
|
75
|
-
* base64) and the browser loads thumbnails/previews lazily.
|
|
76
|
-
*/
|
|
77
|
-
export const HISTORY_API = {
|
|
78
|
-
list: '/api/dsh-imagegen/history/list',
|
|
79
|
-
append: '/api/dsh-imagegen/history/append',
|
|
80
|
-
remove: '/api/dsh-imagegen/history/remove',
|
|
81
|
-
clear: '/api/dsh-imagegen/history/clear',
|
|
82
|
-
image: '/api/dsh-imagegen/history/image',
|
|
83
|
-
} as const
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Same-origin route family for the user-curated gallery (favorites). Entries
|
|
87
|
-
* reuse the history wire shape and persist under ~/.dsh/dsh-imagegen/gallery/;
|
|
88
|
-
* unlike history there is no size cap 鈥?the user adds images on purpose.
|
|
89
|
-
*/
|
|
90
|
-
export const GALLERY_API = {
|
|
91
|
-
list: '/api/dsh-imagegen/gallery/list',
|
|
92
|
-
append: '/api/dsh-imagegen/gallery/append',
|
|
93
|
-
remove: '/api/dsh-imagegen/gallery/remove',
|
|
94
|
-
clear: '/api/dsh-imagegen/gallery/clear',
|
|
95
|
-
tags: '/api/dsh-imagegen/gallery/tags',
|
|
96
|
-
image: '/api/dsh-imagegen/gallery/image',
|
|
97
|
-
} as const
|
|
98
|
-
|
|
99
|
-
/** Host-persisted infinite canvas projects and their content-addressed assets. */
|
|
100
|
-
export const CANVAS_API = {
|
|
101
|
-
list: '/api/dsh-imagegen/canvas/list',
|
|
102
|
-
create: '/api/dsh-imagegen/canvas/create',
|
|
103
|
-
read: '/api/dsh-imagegen/canvas/read',
|
|
104
|
-
save: '/api/dsh-imagegen/canvas/save',
|
|
105
|
-
remove: '/api/dsh-imagegen/canvas/remove',
|
|
106
|
-
assetUpload: '/api/dsh-imagegen/canvas/asset/upload',
|
|
107
|
-
assetImport: '/api/dsh-imagegen/canvas/asset/import',
|
|
108
|
-
asset: '/api/dsh-imagegen/canvas/asset',
|
|
109
|
-
} as const
|
|
110
|
-
|
|
111
|
-
/** Maximum number of history entries retained host-side (oldest evicted). */
|
|
112
|
-
export const HISTORY_MAX = 50
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Same-origin route family for the prompt-template libraries. The library is
|
|
116
|
-
* multi-source: every request names a source id from {@link TEMPLATE_SOURCES},
|
|
117
|
-
* each source keeps an independent snapshot/image cache host-side, and
|
|
118
|
-
* reference images are proxied through the source-scoped `image` prefix route
|
|
119
|
-
* (`…/image/<sourceId>/<file>`) and cached on disk so repeated views never hit
|
|
120
|
-
* the network again.
|
|
121
|
-
*/
|
|
122
|
-
export const TEMPLATES_API = {
|
|
123
|
-
list: '/api/dsh-imagegen/templates/list',
|
|
124
|
-
refresh: '/api/dsh-imagegen/templates/refresh',
|
|
125
|
-
sample: '/api/dsh-imagegen/templates/sample',
|
|
126
|
-
image: '/api/dsh-imagegen/templates/image',
|
|
127
|
-
} as const
|
|
128
|
-
|
|
129
|
-
/** Same-origin route family for the user's saved (favorited) templates. */
|
|
130
|
-
export const TEMPLATE_FAVORITES_API = {
|
|
131
|
-
list: '/api/dsh-imagegen/templates/favorites/list',
|
|
132
|
-
add: '/api/dsh-imagegen/templates/favorites/add',
|
|
133
|
-
remove: '/api/dsh-imagegen/templates/favorites/remove',
|
|
134
|
-
} as const
|
|
135
|
-
|
|
136
|
-
/** One prompt-template library source (a tab in the library overlay). */
|
|
137
|
-
export interface TemplateSourceMeta {
|
|
138
|
-
/** Stable source id: snapshot dir name, image-cache dir, and request key. */
|
|
139
|
-
id: string
|
|
140
|
-
/** Tab label shown in the library overlay. */
|
|
141
|
-
label: string
|
|
142
|
-
/** Source homepage linked in the overlay footer. */
|
|
143
|
-
homepage: string
|
|
144
|
-
/** One-line description of the source (tab tooltip). */
|
|
145
|
-
description: string
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* The template-library source registry. Each entry is fully independent (own
|
|
150
|
-
* upstream JSON, own image pool, own refresh state) and renders as its own
|
|
151
|
-
* tab; adding a source later means appending an entry here plus a host-side
|
|
152
|
-
* fetch definition in templates-store.ts and an optional bundled snapshot.
|
|
153
|
-
*/
|
|
154
|
-
export const TEMPLATE_SOURCES: TemplateSourceMeta[] = [
|
|
155
|
-
{
|
|
156
|
-
id: 'vibeui',
|
|
157
|
-
label: '精选案例库',
|
|
158
|
-
homepage: 'https://vibeui.top/',
|
|
159
|
-
description: 'awesome-gpt-image-2 精选提示词案例(vibeui.top 镜像)',
|
|
160
|
-
},
|
|
161
|
-
{
|
|
162
|
-
id: 'canghe',
|
|
163
|
-
label: '沧河案例库',
|
|
164
|
-
homepage: 'https://gpt-image2.canghe.ai/',
|
|
165
|
-
description: 'GPT-Image2 Prompt Gallery(gpt-image2.canghe.ai,定期更新)',
|
|
166
|
-
},
|
|
167
|
-
]
|
|
168
|
-
|
|
169
|
-
/** Default source id when a request does not name one (legacy clients). */
|
|
170
|
-
export const DEFAULT_TEMPLATE_SOURCE_ID = TEMPLATE_SOURCES[0]!.id
|
|
171
|
-
|
|
172
|
-
/** True when the id names a registered template source. */
|
|
173
|
-
export function isTemplateSourceId(id: string): boolean {
|
|
174
|
-
return TEMPLATE_SOURCES.some(source => source.id === id)
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/** One prompt-library case as the browser consumes it. */
|
|
178
|
-
export interface TemplateCase {
|
|
179
|
-
/** Upstream case number (stable across refreshes). */
|
|
180
|
-
id: number
|
|
181
|
-
/** Short case title. */
|
|
182
|
-
title: string
|
|
183
|
-
/** Full reusable prompt text. */
|
|
184
|
-
prompt: string
|
|
185
|
-
/** English category name (grouping key). */
|
|
186
|
-
category: string
|
|
187
|
-
/** Chinese category display name. */
|
|
188
|
-
categoryZh: string
|
|
189
|
-
/** Style tags. */
|
|
190
|
-
styles: string[]
|
|
191
|
-
/** Scene tags. */
|
|
192
|
-
scenes: string[]
|
|
193
|
-
/** Original author handle, e.g. @vista8. */
|
|
194
|
-
sourceLabel: string
|
|
195
|
-
/** Original author link. */
|
|
196
|
-
sourceUrl: string
|
|
197
|
-
/** awesome-gpt-image-2 repo anchor link. */
|
|
198
|
-
githubUrl: string
|
|
199
|
-
/** Reference-image file name served through the image route ('' when none). */
|
|
200
|
-
image: string
|
|
201
|
-
/** Whether the source gallery featured the case. */
|
|
202
|
-
featured: boolean
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
/** Template-library list payload (one source). */
|
|
206
|
-
export interface TemplateListResult {
|
|
207
|
-
/** The source this list belongs to. */
|
|
208
|
-
sourceId: string
|
|
209
|
-
cases: TemplateCase[]
|
|
210
|
-
total: number
|
|
211
|
-
/** Where the served list came from. */
|
|
212
|
-
origin: 'bundled' | 'refreshed'
|
|
213
|
-
/** Upstream repository the library mirrors. */
|
|
214
|
-
repository: string
|
|
215
|
-
/** ISO time of the last successful refresh / bundle snapshot. */
|
|
216
|
-
fetchedAt: string
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
/** Template-library refresh outcome (one source). */
|
|
220
|
-
export interface TemplateRefreshResult {
|
|
221
|
-
sourceId: string
|
|
222
|
-
total: number
|
|
223
|
-
fetchedAt: string
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
/** One random inspiration pick served to the studio's empty state. */
|
|
227
|
-
export interface TemplateSample {
|
|
228
|
-
/** Source the case came from (drives the image proxy URL). */
|
|
229
|
-
sourceId: string
|
|
230
|
-
/** The sampled case (full prompt is handed to the form on use). */
|
|
231
|
-
case: TemplateCase
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
/** One favorited template as persisted host-side and served to the browser. */
|
|
235
|
-
export interface TemplateFavorite {
|
|
236
|
-
/** Stable key: `${sourceId}:${caseId}`. */
|
|
237
|
-
key: string
|
|
238
|
-
/** Source the case came from. */
|
|
239
|
-
sourceId: string
|
|
240
|
-
/** ISO time the favorite was saved. */
|
|
241
|
-
savedAt: string
|
|
242
|
-
/** Full case snapshot, so favorites survive upstream list churn. */
|
|
243
|
-
case: TemplateCase
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
/** Generation modes. */
|
|
247
|
-
export type GenerateMode = 'text' | 'edit'
|
|
248
|
-
|
|
249
|
-
/** Origin information carried by a generation started from the canvas. */
|
|
250
|
-
export interface CanvasTaskMeta {
|
|
251
|
-
canvasId: string
|
|
252
|
-
sourceNodeId?: string
|
|
253
|
-
/** Legacy v1 annotation workflow; kept so old history entries still parse. */
|
|
254
|
-
annotationNodeId?: string
|
|
255
|
-
parentNodeId?: string
|
|
256
|
-
placement?: 'right' | 'below'
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
/** One image asset referenced by a canvas node. */
|
|
260
|
-
export interface CanvasAssetRef {
|
|
261
|
-
assetId: string
|
|
262
|
-
url: string
|
|
263
|
-
mime: string
|
|
264
|
-
bytes: number
|
|
265
|
-
width: number
|
|
266
|
-
height: number
|
|
267
|
-
origin: 'upload' | 'history' | 'gallery' | 'generated'
|
|
268
|
-
originId?: string
|
|
269
|
-
entryId?: string
|
|
270
|
-
imageIndex?: number
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
export type CanvasNodeType = 'image' | 'text' | 'config'
|
|
274
|
-
|
|
275
|
-
export interface CanvasViewport {
|
|
276
|
-
x: number
|
|
277
|
-
y: number
|
|
278
|
-
/** Zoom factor. */
|
|
279
|
-
k: number
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
/** Free-form per-node state, mirroring the node-graph canvas model. */
|
|
283
|
-
export interface CanvasNodeMetadata {
|
|
284
|
-
/** Image nodes: the rendered asset. */
|
|
285
|
-
asset?: CanvasAssetRef
|
|
286
|
-
status?: 'idle' | 'generating' | 'success' | 'error'
|
|
287
|
-
error?: string
|
|
288
|
-
/** Config/image nodes: generation settings. */
|
|
289
|
-
prompt?: string
|
|
290
|
-
model?: string
|
|
291
|
-
size?: string
|
|
292
|
-
quality?: string
|
|
293
|
-
/** Config nodes: how many images to generate (1-4). */
|
|
294
|
-
count?: number
|
|
295
|
-
/** Config nodes: generation mode (image) or plain writing (text). */
|
|
296
|
-
mode?: 'image' | 'text'
|
|
297
|
-
taskId?: string
|
|
298
|
-
sourceNodeId?: string
|
|
299
|
-
/** Text nodes. */
|
|
300
|
-
text?: string
|
|
301
|
-
fontSize?: number
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
export interface CanvasNode {
|
|
305
|
-
id: string
|
|
306
|
-
type: CanvasNodeType
|
|
307
|
-
title: string
|
|
308
|
-
x: number
|
|
309
|
-
y: number
|
|
310
|
-
width: number
|
|
311
|
-
height: number
|
|
312
|
-
metadata?: CanvasNodeMetadata
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
export interface CanvasConnection {
|
|
316
|
-
id: string
|
|
317
|
-
fromNodeId: string
|
|
318
|
-
toNodeId: string
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
export interface CanvasDocument {
|
|
322
|
-
version: 2
|
|
323
|
-
id: string
|
|
324
|
-
title: string
|
|
325
|
-
revision: number
|
|
326
|
-
viewport: CanvasViewport
|
|
327
|
-
background: 'dots' | 'lines' | 'diagonal' | 'checker' | 'blank' | 'image'
|
|
328
|
-
/** Custom background image URL (a canvas asset) when background is 'image'. */
|
|
329
|
-
backgroundImage?: string
|
|
330
|
-
nodes: CanvasNode[]
|
|
331
|
-
connections: CanvasConnection[]
|
|
332
|
-
createdAt: number
|
|
333
|
-
updatedAt: number
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
export interface CanvasSummary {
|
|
337
|
-
id: string
|
|
338
|
-
title: string
|
|
339
|
-
revision: number
|
|
340
|
-
nodeCount: number
|
|
341
|
-
createdAt: number
|
|
342
|
-
updatedAt: number
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
/** Metadata shared by the ecommerce product-set workflow. */
|
|
346
|
-
export interface EcommerceTaskMeta {
|
|
347
|
-
workflow?: 'ecommerce'
|
|
348
|
-
projectId?: string
|
|
349
|
-
projectName?: string
|
|
350
|
-
slotKey?: string
|
|
351
|
-
slotLabel?: string
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
/** Role an uploaded product asset plays in the ecommerce workflow. 'none' is
|
|
355
|
-
* only used as a slot selection meaning "generate without a reference". */
|
|
356
|
-
export type EcommerceRefRole = 'none' | 'product' | 'packaging' | 'detail' | 'style'
|
|
357
|
-
|
|
358
|
-
/** One planned image slot in a product set. */
|
|
359
|
-
export interface ProductSetSlot {
|
|
360
|
-
key: string
|
|
361
|
-
label: string
|
|
362
|
-
description: string
|
|
363
|
-
count: number
|
|
364
|
-
enabled: boolean
|
|
365
|
-
/** Which uploaded asset role this slot uses as its edit reference. */
|
|
366
|
-
refRole?: EcommerceRefRole
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
/** A browser-local ecommerce product-set draft. */
|
|
370
|
-
export interface ProductSetDraft {
|
|
371
|
-
projectId: string
|
|
372
|
-
projectName: string
|
|
373
|
-
category: string
|
|
374
|
-
platform: string
|
|
375
|
-
language: string
|
|
376
|
-
/** Custom copy language when language is 'custom'. */
|
|
377
|
-
customLanguage?: string
|
|
378
|
-
size: string
|
|
379
|
-
productName: string
|
|
380
|
-
sellingPoints: string
|
|
381
|
-
protectedFeatures: string
|
|
382
|
-
styleHint: string
|
|
383
|
-
slots: ProductSetSlot[]
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
/** A client → host generate request (what the panel collects). */
|
|
387
|
-
export interface GenerateRequest extends EcommerceTaskMeta {
|
|
388
|
-
/** text-to-image (images/generations) or image-to-image (images/edits). */
|
|
389
|
-
mode: GenerateMode
|
|
390
|
-
/**
|
|
391
|
-
* User-facing model name (an alias from the channel's model catalog). The
|
|
392
|
-
* host maps it onto the configured channel and fills `upstream` with the
|
|
393
|
-
* real id before the engine sees it.
|
|
394
|
-
*/
|
|
395
|
-
model: string
|
|
396
|
-
/** The prompt. Upstream providers may impose their own length limits. */
|
|
397
|
-
prompt: string
|
|
398
|
-
/** Canvas size as an aspect ratio: 'auto' or e.g. '1:1' / '16:9' / '21:9'.
|
|
399
|
-
* The host maps it onto each model's own vocabulary (aspect_ratio for Grok
|
|
400
|
-
* and Nano Banana, resolution-tier size for Seedream, the closest pixel size for
|
|
401
|
-
* OpenAI-compatible endpoints). */
|
|
402
|
-
size: string
|
|
403
|
-
/** Clarity tier: 'auto' | '1k' | '2k' | '4k'. The host maps it onto the
|
|
404
|
-
* model's own vocabulary (resolution for Grok, image_size for Nano Banana,
|
|
405
|
-
* and size for Seedream,
|
|
406
|
-
* Nano Banana, quality for OpenAI). */
|
|
407
|
-
quality: string
|
|
408
|
-
/** Number of images, 1-4. */
|
|
409
|
-
n: number
|
|
410
|
-
/**
|
|
411
|
-
* Passthrough detail parameter: '' (omit), 'standard', or 'high'. Some
|
|
412
|
-
* gpt-image-2 gateways expose it; official OpenAI endpoints reject unknown
|
|
413
|
-
* parameters, so the UI defaults to '' (omit).
|
|
414
|
-
*/
|
|
415
|
-
detail: string
|
|
416
|
-
/** Reference image as a data URL (edit mode only). */
|
|
417
|
-
image?: string
|
|
418
|
-
/** Additional reference images as data URLs (edit mode only). The first
|
|
419
|
-
* image stays in `image`; providers that accept several references get them
|
|
420
|
-
* all, single-reference providers see `image` alone. */
|
|
421
|
-
images?: string[]
|
|
422
|
-
/** Original reference-image name, retained in the history entry. */
|
|
423
|
-
refName?: string
|
|
424
|
-
/** Channel this request targets (the host falls back to the default when
|
|
425
|
-
* absent, and re-routes by model alias when the alias lives elsewhere). */
|
|
426
|
-
channelId?: string
|
|
427
|
-
/** Channel display name snapshot, kept on the history entry (host-filled). */
|
|
428
|
-
channel?: string
|
|
429
|
-
/** Upstream model id actually sent to the gateway (host-filled from the
|
|
430
|
-
* alias mapping; defaults to `model` when absent). */
|
|
431
|
-
upstream?: string
|
|
432
|
-
/** Stable client-created id shared by the tasks in one comparison run. */
|
|
433
|
-
comparisonId?: string
|
|
434
|
-
/** All model aliases selected for one comparison run. */
|
|
435
|
-
comparisonModels?: string[]
|
|
436
|
-
/** Optional canvas lineage metadata. */
|
|
437
|
-
canvas?: CanvasTaskMeta
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
/** One generated image, normalized host-side to base64 so the browser never
|
|
441
|
-
* has to fetch the upstream (no CORS, no key exposure). */
|
|
442
|
-
export interface GeneratedImage {
|
|
443
|
-
/** Raw base64 payload (no data: prefix). */
|
|
444
|
-
b64: string
|
|
445
|
-
/** MIME type of the payload, e.g. image/png. */
|
|
446
|
-
mime: string
|
|
447
|
-
/** Upstream revised prompt, when provided. */
|
|
448
|
-
revisedPrompt?: string
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
/** Successful generate outcome. */
|
|
452
|
-
export interface GenerateResult {
|
|
453
|
-
images: GeneratedImage[]
|
|
454
|
-
/** Updated host-persisted history, when returned by the generate route. */
|
|
455
|
-
history?: HistoryEntry[]
|
|
456
|
-
/** Persistence failure after images were successfully generated. */
|
|
457
|
-
historyError?: string
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
/**
|
|
461
|
-
* One model mapping in a channel's catalog: the display alias the user, the
|
|
462
|
-
* panel, and the Agent see, and the upstream model id actually sent to the
|
|
463
|
-
* gateway. The alias defaults to the upstream id but can be renamed freely.
|
|
464
|
-
*/
|
|
465
|
-
export interface ModelMapping {
|
|
466
|
-
/** User-facing model name (defaults to the upstream id). */
|
|
467
|
-
alias: string
|
|
468
|
-
/** Upstream model id sent to the gateway. */
|
|
469
|
-
id: string
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
/**
|
|
473
|
-
* One configured image channel (provider). Secrets never live here — the API
|
|
474
|
-
* key is stored at `channelSecrets.<channelId>` in the settings document so
|
|
475
|
-
* whole-array writes can never clobber keys the user did not re-enter.
|
|
476
|
-
*/
|
|
477
|
-
export interface ChannelConfig {
|
|
478
|
-
/** Stable channel id (the channelSecrets dict is keyed by it). */
|
|
479
|
-
id: string
|
|
480
|
-
/** Preset provider id this channel was created from ('' = custom). */
|
|
481
|
-
preset: string
|
|
482
|
-
/** Display name shown in the list, the panel, and Agent guidance. */
|
|
483
|
-
name: string
|
|
484
|
-
/** OpenAI-compatible base URL. */
|
|
485
|
-
apiUrl: string
|
|
486
|
-
/** The channel's model catalog (alias → upstream id). */
|
|
487
|
-
models: ModelMapping[]
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
/** One built-in provider as the settings card consumes it. */
|
|
491
|
-
export interface PresetProviderView {
|
|
492
|
-
id: string
|
|
493
|
-
name: string
|
|
494
|
-
apiUrl: string
|
|
495
|
-
hint: string
|
|
496
|
-
models: ModelMapping[]
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
export type GenerationTaskStatus = 'queued' | 'running' | 'completed' | 'failed' | 'cancelled'
|
|
500
|
-
|
|
501
|
-
export interface GenerationTask extends EcommerceTaskMeta {
|
|
502
|
-
id: string
|
|
503
|
-
request: GenerateRequest
|
|
504
|
-
status: GenerationTaskStatus
|
|
505
|
-
createdAt: number
|
|
506
|
-
startedAt?: number
|
|
507
|
-
finishedAt?: number
|
|
508
|
-
result?: GenerateResult
|
|
509
|
-
error?: string
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
/** GitHub Release update information shown by the client. */
|
|
513
|
-
export interface UpdateInfo {
|
|
514
|
-
currentVersion: string
|
|
515
|
-
latestVersion: string
|
|
516
|
-
updateAvailable: boolean
|
|
517
|
-
releaseUrl: string
|
|
518
|
-
publishedAt?: string
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
/** One history image reference as the browser consumes it (a served URL). */
|
|
522
|
-
export interface HistoryImageRef {
|
|
523
|
-
/** Same-origin URL: `${HISTORY_API.image}/<file>`. */
|
|
524
|
-
url: string
|
|
525
|
-
/** MIME type, e.g. image/png. */
|
|
526
|
-
mime: string
|
|
527
|
-
/** Upstream revised prompt, when provided. */
|
|
528
|
-
revisedPrompt?: string
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
/** A saved generation as the browser consumes it (metadata + served images). */
|
|
532
|
-
export interface HistoryEntry extends EcommerceTaskMeta {
|
|
533
|
-
id: string
|
|
534
|
-
createdAt: number
|
|
535
|
-
mode: GenerateMode
|
|
536
|
-
model: string
|
|
537
|
-
prompt: string
|
|
538
|
-
size: string
|
|
539
|
-
quality: string
|
|
540
|
-
detail: string
|
|
541
|
-
n: number
|
|
542
|
-
images: HistoryImageRef[]
|
|
543
|
-
/** Reference-image filename (edit mode), kept for display only. */
|
|
544
|
-
refName?: string
|
|
545
|
-
/** User-managed gallery labels (unused by history entries). */
|
|
546
|
-
tags?: string[]
|
|
547
|
-
/** Channel id snapshot (usage counters key by it for new entries). */
|
|
548
|
-
channelId?: string
|
|
549
|
-
/** Channel display name snapshot (survives channel deletion). */
|
|
550
|
-
channel?: string
|
|
551
|
-
/** Stable id shared by the history entries in one comparison run. */
|
|
552
|
-
comparisonId?: string
|
|
553
|
-
/** Model aliases included in the comparison run. */
|
|
554
|
-
comparisonModels?: string[]
|
|
555
|
-
canvas?: CanvasTaskMeta
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
/** A history entry the client submits for persistence (images still carry base64). */
|
|
559
|
-
export interface HistoryEntryInput extends EcommerceTaskMeta {
|
|
560
|
-
id: string
|
|
561
|
-
createdAt: number
|
|
562
|
-
mode: GenerateMode
|
|
563
|
-
model: string
|
|
564
|
-
prompt: string
|
|
565
|
-
size: string
|
|
566
|
-
quality: string
|
|
567
|
-
detail: string
|
|
568
|
-
n: number
|
|
569
|
-
images: GeneratedImage[]
|
|
570
|
-
refName?: string
|
|
571
|
-
/** Channel id snapshot, tallied by the usage endpoint. */
|
|
572
|
-
channelId?: string
|
|
573
|
-
/** Channel display name snapshot (survives channel deletion). */
|
|
574
|
-
channel?: string
|
|
575
|
-
/** Stable id shared by the history entries in one comparison run. */
|
|
576
|
-
comparisonId?: string
|
|
577
|
-
/** Model aliases included in the comparison run. */
|
|
578
|
-
comparisonModels?: string[]
|
|
579
|
-
canvas?: CanvasTaskMeta
|
|
580
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Wire contract shared by the host and client halves of dsh-imagegen: the
|
|
3
|
+
* settings namespace, the route paths, and the generate payload/result shapes.
|
|
4
|
+
* Pure types + constants 鈥?safe for the client bundle to inline.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/** Settings namespace this plugin owns (host settings seam + bridge). */
|
|
8
|
+
export const IMAGEGEN_SETTINGS_NAMESPACE = 'dsh-imagegen'
|
|
9
|
+
|
|
10
|
+
/** Published package version shared by the host updater and the client UI. */
|
|
11
|
+
export const PLUGIN_VERSION = '1.5.8'
|
|
12
|
+
|
|
13
|
+
/** Same-origin route family (loopback-only, mirroring the dsh-ssh fence). */
|
|
14
|
+
export const SETTINGS_API = {
|
|
15
|
+
describe: '/api/dsh-imagegen/settings/describe',
|
|
16
|
+
mutate: '/api/dsh-imagegen/settings/mutate',
|
|
17
|
+
} as const
|
|
18
|
+
|
|
19
|
+
/** The image-generation proxy route. */
|
|
20
|
+
export const GENERATE_API = '/api/dsh-imagegen/generate'
|
|
21
|
+
|
|
22
|
+
/** Host-mediated OpenAI-compatible prompt enhancement endpoints. */
|
|
23
|
+
export const PROMPT_ENHANCE_API = {
|
|
24
|
+
models: '/api/dsh-imagegen/prompt-enhance/models',
|
|
25
|
+
enhance: '/api/dsh-imagegen/prompt-enhance',
|
|
26
|
+
} as const
|
|
27
|
+
|
|
28
|
+
/** Host-mediated candidate discovery for the configured image API. */
|
|
29
|
+
export const IMAGE_MODEL_API = {
|
|
30
|
+
models: '/api/dsh-imagegen/image-models',
|
|
31
|
+
} as const
|
|
32
|
+
|
|
33
|
+
/** Host-served built-in provider catalog (channels the user can instantiate). */
|
|
34
|
+
export const PRESETS_API = '/api/dsh-imagegen/presets' as const
|
|
35
|
+
|
|
36
|
+
/** Loopback-only image reader for Agent tool-result previews. */
|
|
37
|
+
export const AGENT_IMAGE_API = '/api/dsh-imagegen/agent-image' as const
|
|
38
|
+
|
|
39
|
+
/** Store the current composer image for the direct edit_image command. */
|
|
40
|
+
export const CONVERSATION_IMAGE_API = '/api/dsh-imagegen/conversation-image' as const
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Host-computed per-channel usage counters (generation-count badges in the
|
|
44
|
+
* settings card): entries are tallied from the persisted history and gallery
|
|
45
|
+
* by channel + model alias.
|
|
46
|
+
*/
|
|
47
|
+
export const USAGE_API = '/api/dsh-imagegen/usage' as const
|
|
48
|
+
|
|
49
|
+
/** Host-resident generation queue endpoints. */
|
|
50
|
+
export const TASK_API = {
|
|
51
|
+
submit: '/api/dsh-imagegen/tasks/submit',
|
|
52
|
+
list: '/api/dsh-imagegen/tasks/list',
|
|
53
|
+
cancel: '/api/dsh-imagegen/tasks/cancel',
|
|
54
|
+
retry: '/api/dsh-imagegen/tasks/retry',
|
|
55
|
+
} as const
|
|
56
|
+
|
|
57
|
+
/** Reveal the host data directory (saved images) in the OS file manager. */
|
|
58
|
+
export const DATA_FOLDER_API = '/api/dsh-imagegen/data-folder/open' as const
|
|
59
|
+
|
|
60
|
+
/** Probe the configured S3-compatible object storage. */
|
|
61
|
+
export const STORAGE_API = {
|
|
62
|
+
test: '/api/dsh-imagegen/storage/test',
|
|
63
|
+
} as const
|
|
64
|
+
|
|
65
|
+
/** Host-mediated GitHub Release update routes. */
|
|
66
|
+
export const UPDATE_API = {
|
|
67
|
+
check: '/api/dsh-imagegen/update/check',
|
|
68
|
+
apply: '/api/dsh-imagegen/update/apply',
|
|
69
|
+
} as const
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Same-origin route family for the host-persisted generation history. Images
|
|
73
|
+
* live as files under ~/.dsh/dsh-imagegen/images/ and are served back through
|
|
74
|
+
* the `image` prefix route, so list responses carry metadata only (never
|
|
75
|
+
* base64) and the browser loads thumbnails/previews lazily.
|
|
76
|
+
*/
|
|
77
|
+
export const HISTORY_API = {
|
|
78
|
+
list: '/api/dsh-imagegen/history/list',
|
|
79
|
+
append: '/api/dsh-imagegen/history/append',
|
|
80
|
+
remove: '/api/dsh-imagegen/history/remove',
|
|
81
|
+
clear: '/api/dsh-imagegen/history/clear',
|
|
82
|
+
image: '/api/dsh-imagegen/history/image',
|
|
83
|
+
} as const
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Same-origin route family for the user-curated gallery (favorites). Entries
|
|
87
|
+
* reuse the history wire shape and persist under ~/.dsh/dsh-imagegen/gallery/;
|
|
88
|
+
* unlike history there is no size cap 鈥?the user adds images on purpose.
|
|
89
|
+
*/
|
|
90
|
+
export const GALLERY_API = {
|
|
91
|
+
list: '/api/dsh-imagegen/gallery/list',
|
|
92
|
+
append: '/api/dsh-imagegen/gallery/append',
|
|
93
|
+
remove: '/api/dsh-imagegen/gallery/remove',
|
|
94
|
+
clear: '/api/dsh-imagegen/gallery/clear',
|
|
95
|
+
tags: '/api/dsh-imagegen/gallery/tags',
|
|
96
|
+
image: '/api/dsh-imagegen/gallery/image',
|
|
97
|
+
} as const
|
|
98
|
+
|
|
99
|
+
/** Host-persisted infinite canvas projects and their content-addressed assets. */
|
|
100
|
+
export const CANVAS_API = {
|
|
101
|
+
list: '/api/dsh-imagegen/canvas/list',
|
|
102
|
+
create: '/api/dsh-imagegen/canvas/create',
|
|
103
|
+
read: '/api/dsh-imagegen/canvas/read',
|
|
104
|
+
save: '/api/dsh-imagegen/canvas/save',
|
|
105
|
+
remove: '/api/dsh-imagegen/canvas/remove',
|
|
106
|
+
assetUpload: '/api/dsh-imagegen/canvas/asset/upload',
|
|
107
|
+
assetImport: '/api/dsh-imagegen/canvas/asset/import',
|
|
108
|
+
asset: '/api/dsh-imagegen/canvas/asset',
|
|
109
|
+
} as const
|
|
110
|
+
|
|
111
|
+
/** Maximum number of history entries retained host-side (oldest evicted). */
|
|
112
|
+
export const HISTORY_MAX = 50
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Same-origin route family for the prompt-template libraries. The library is
|
|
116
|
+
* multi-source: every request names a source id from {@link TEMPLATE_SOURCES},
|
|
117
|
+
* each source keeps an independent snapshot/image cache host-side, and
|
|
118
|
+
* reference images are proxied through the source-scoped `image` prefix route
|
|
119
|
+
* (`…/image/<sourceId>/<file>`) and cached on disk so repeated views never hit
|
|
120
|
+
* the network again.
|
|
121
|
+
*/
|
|
122
|
+
export const TEMPLATES_API = {
|
|
123
|
+
list: '/api/dsh-imagegen/templates/list',
|
|
124
|
+
refresh: '/api/dsh-imagegen/templates/refresh',
|
|
125
|
+
sample: '/api/dsh-imagegen/templates/sample',
|
|
126
|
+
image: '/api/dsh-imagegen/templates/image',
|
|
127
|
+
} as const
|
|
128
|
+
|
|
129
|
+
/** Same-origin route family for the user's saved (favorited) templates. */
|
|
130
|
+
export const TEMPLATE_FAVORITES_API = {
|
|
131
|
+
list: '/api/dsh-imagegen/templates/favorites/list',
|
|
132
|
+
add: '/api/dsh-imagegen/templates/favorites/add',
|
|
133
|
+
remove: '/api/dsh-imagegen/templates/favorites/remove',
|
|
134
|
+
} as const
|
|
135
|
+
|
|
136
|
+
/** One prompt-template library source (a tab in the library overlay). */
|
|
137
|
+
export interface TemplateSourceMeta {
|
|
138
|
+
/** Stable source id: snapshot dir name, image-cache dir, and request key. */
|
|
139
|
+
id: string
|
|
140
|
+
/** Tab label shown in the library overlay. */
|
|
141
|
+
label: string
|
|
142
|
+
/** Source homepage linked in the overlay footer. */
|
|
143
|
+
homepage: string
|
|
144
|
+
/** One-line description of the source (tab tooltip). */
|
|
145
|
+
description: string
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* The template-library source registry. Each entry is fully independent (own
|
|
150
|
+
* upstream JSON, own image pool, own refresh state) and renders as its own
|
|
151
|
+
* tab; adding a source later means appending an entry here plus a host-side
|
|
152
|
+
* fetch definition in templates-store.ts and an optional bundled snapshot.
|
|
153
|
+
*/
|
|
154
|
+
export const TEMPLATE_SOURCES: TemplateSourceMeta[] = [
|
|
155
|
+
{
|
|
156
|
+
id: 'vibeui',
|
|
157
|
+
label: '精选案例库',
|
|
158
|
+
homepage: 'https://vibeui.top/',
|
|
159
|
+
description: 'awesome-gpt-image-2 精选提示词案例(vibeui.top 镜像)',
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
id: 'canghe',
|
|
163
|
+
label: '沧河案例库',
|
|
164
|
+
homepage: 'https://gpt-image2.canghe.ai/',
|
|
165
|
+
description: 'GPT-Image2 Prompt Gallery(gpt-image2.canghe.ai,定期更新)',
|
|
166
|
+
},
|
|
167
|
+
]
|
|
168
|
+
|
|
169
|
+
/** Default source id when a request does not name one (legacy clients). */
|
|
170
|
+
export const DEFAULT_TEMPLATE_SOURCE_ID = TEMPLATE_SOURCES[0]!.id
|
|
171
|
+
|
|
172
|
+
/** True when the id names a registered template source. */
|
|
173
|
+
export function isTemplateSourceId(id: string): boolean {
|
|
174
|
+
return TEMPLATE_SOURCES.some(source => source.id === id)
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/** One prompt-library case as the browser consumes it. */
|
|
178
|
+
export interface TemplateCase {
|
|
179
|
+
/** Upstream case number (stable across refreshes). */
|
|
180
|
+
id: number
|
|
181
|
+
/** Short case title. */
|
|
182
|
+
title: string
|
|
183
|
+
/** Full reusable prompt text. */
|
|
184
|
+
prompt: string
|
|
185
|
+
/** English category name (grouping key). */
|
|
186
|
+
category: string
|
|
187
|
+
/** Chinese category display name. */
|
|
188
|
+
categoryZh: string
|
|
189
|
+
/** Style tags. */
|
|
190
|
+
styles: string[]
|
|
191
|
+
/** Scene tags. */
|
|
192
|
+
scenes: string[]
|
|
193
|
+
/** Original author handle, e.g. @vista8. */
|
|
194
|
+
sourceLabel: string
|
|
195
|
+
/** Original author link. */
|
|
196
|
+
sourceUrl: string
|
|
197
|
+
/** awesome-gpt-image-2 repo anchor link. */
|
|
198
|
+
githubUrl: string
|
|
199
|
+
/** Reference-image file name served through the image route ('' when none). */
|
|
200
|
+
image: string
|
|
201
|
+
/** Whether the source gallery featured the case. */
|
|
202
|
+
featured: boolean
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/** Template-library list payload (one source). */
|
|
206
|
+
export interface TemplateListResult {
|
|
207
|
+
/** The source this list belongs to. */
|
|
208
|
+
sourceId: string
|
|
209
|
+
cases: TemplateCase[]
|
|
210
|
+
total: number
|
|
211
|
+
/** Where the served list came from. */
|
|
212
|
+
origin: 'bundled' | 'refreshed'
|
|
213
|
+
/** Upstream repository the library mirrors. */
|
|
214
|
+
repository: string
|
|
215
|
+
/** ISO time of the last successful refresh / bundle snapshot. */
|
|
216
|
+
fetchedAt: string
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/** Template-library refresh outcome (one source). */
|
|
220
|
+
export interface TemplateRefreshResult {
|
|
221
|
+
sourceId: string
|
|
222
|
+
total: number
|
|
223
|
+
fetchedAt: string
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/** One random inspiration pick served to the studio's empty state. */
|
|
227
|
+
export interface TemplateSample {
|
|
228
|
+
/** Source the case came from (drives the image proxy URL). */
|
|
229
|
+
sourceId: string
|
|
230
|
+
/** The sampled case (full prompt is handed to the form on use). */
|
|
231
|
+
case: TemplateCase
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/** One favorited template as persisted host-side and served to the browser. */
|
|
235
|
+
export interface TemplateFavorite {
|
|
236
|
+
/** Stable key: `${sourceId}:${caseId}`. */
|
|
237
|
+
key: string
|
|
238
|
+
/** Source the case came from. */
|
|
239
|
+
sourceId: string
|
|
240
|
+
/** ISO time the favorite was saved. */
|
|
241
|
+
savedAt: string
|
|
242
|
+
/** Full case snapshot, so favorites survive upstream list churn. */
|
|
243
|
+
case: TemplateCase
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/** Generation modes. */
|
|
247
|
+
export type GenerateMode = 'text' | 'edit'
|
|
248
|
+
|
|
249
|
+
/** Origin information carried by a generation started from the canvas. */
|
|
250
|
+
export interface CanvasTaskMeta {
|
|
251
|
+
canvasId: string
|
|
252
|
+
sourceNodeId?: string
|
|
253
|
+
/** Legacy v1 annotation workflow; kept so old history entries still parse. */
|
|
254
|
+
annotationNodeId?: string
|
|
255
|
+
parentNodeId?: string
|
|
256
|
+
placement?: 'right' | 'below'
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/** One image asset referenced by a canvas node. */
|
|
260
|
+
export interface CanvasAssetRef {
|
|
261
|
+
assetId: string
|
|
262
|
+
url: string
|
|
263
|
+
mime: string
|
|
264
|
+
bytes: number
|
|
265
|
+
width: number
|
|
266
|
+
height: number
|
|
267
|
+
origin: 'upload' | 'history' | 'gallery' | 'generated'
|
|
268
|
+
originId?: string
|
|
269
|
+
entryId?: string
|
|
270
|
+
imageIndex?: number
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export type CanvasNodeType = 'image' | 'text' | 'config'
|
|
274
|
+
|
|
275
|
+
export interface CanvasViewport {
|
|
276
|
+
x: number
|
|
277
|
+
y: number
|
|
278
|
+
/** Zoom factor. */
|
|
279
|
+
k: number
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/** Free-form per-node state, mirroring the node-graph canvas model. */
|
|
283
|
+
export interface CanvasNodeMetadata {
|
|
284
|
+
/** Image nodes: the rendered asset. */
|
|
285
|
+
asset?: CanvasAssetRef
|
|
286
|
+
status?: 'idle' | 'generating' | 'success' | 'error'
|
|
287
|
+
error?: string
|
|
288
|
+
/** Config/image nodes: generation settings. */
|
|
289
|
+
prompt?: string
|
|
290
|
+
model?: string
|
|
291
|
+
size?: string
|
|
292
|
+
quality?: string
|
|
293
|
+
/** Config nodes: how many images to generate (1-4). */
|
|
294
|
+
count?: number
|
|
295
|
+
/** Config nodes: generation mode (image) or plain writing (text). */
|
|
296
|
+
mode?: 'image' | 'text'
|
|
297
|
+
taskId?: string
|
|
298
|
+
sourceNodeId?: string
|
|
299
|
+
/** Text nodes. */
|
|
300
|
+
text?: string
|
|
301
|
+
fontSize?: number
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
export interface CanvasNode {
|
|
305
|
+
id: string
|
|
306
|
+
type: CanvasNodeType
|
|
307
|
+
title: string
|
|
308
|
+
x: number
|
|
309
|
+
y: number
|
|
310
|
+
width: number
|
|
311
|
+
height: number
|
|
312
|
+
metadata?: CanvasNodeMetadata
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
export interface CanvasConnection {
|
|
316
|
+
id: string
|
|
317
|
+
fromNodeId: string
|
|
318
|
+
toNodeId: string
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
export interface CanvasDocument {
|
|
322
|
+
version: 2
|
|
323
|
+
id: string
|
|
324
|
+
title: string
|
|
325
|
+
revision: number
|
|
326
|
+
viewport: CanvasViewport
|
|
327
|
+
background: 'dots' | 'lines' | 'diagonal' | 'checker' | 'blank' | 'image' | 'flow' | 'aurora'
|
|
328
|
+
/** Custom background image URL (a canvas asset) when background is 'image'. */
|
|
329
|
+
backgroundImage?: string
|
|
330
|
+
nodes: CanvasNode[]
|
|
331
|
+
connections: CanvasConnection[]
|
|
332
|
+
createdAt: number
|
|
333
|
+
updatedAt: number
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
export interface CanvasSummary {
|
|
337
|
+
id: string
|
|
338
|
+
title: string
|
|
339
|
+
revision: number
|
|
340
|
+
nodeCount: number
|
|
341
|
+
createdAt: number
|
|
342
|
+
updatedAt: number
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/** Metadata shared by the ecommerce product-set workflow. */
|
|
346
|
+
export interface EcommerceTaskMeta {
|
|
347
|
+
workflow?: 'ecommerce'
|
|
348
|
+
projectId?: string
|
|
349
|
+
projectName?: string
|
|
350
|
+
slotKey?: string
|
|
351
|
+
slotLabel?: string
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/** Role an uploaded product asset plays in the ecommerce workflow. 'none' is
|
|
355
|
+
* only used as a slot selection meaning "generate without a reference". */
|
|
356
|
+
export type EcommerceRefRole = 'none' | 'product' | 'packaging' | 'detail' | 'style'
|
|
357
|
+
|
|
358
|
+
/** One planned image slot in a product set. */
|
|
359
|
+
export interface ProductSetSlot {
|
|
360
|
+
key: string
|
|
361
|
+
label: string
|
|
362
|
+
description: string
|
|
363
|
+
count: number
|
|
364
|
+
enabled: boolean
|
|
365
|
+
/** Which uploaded asset role this slot uses as its edit reference. */
|
|
366
|
+
refRole?: EcommerceRefRole
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/** A browser-local ecommerce product-set draft. */
|
|
370
|
+
export interface ProductSetDraft {
|
|
371
|
+
projectId: string
|
|
372
|
+
projectName: string
|
|
373
|
+
category: string
|
|
374
|
+
platform: string
|
|
375
|
+
language: string
|
|
376
|
+
/** Custom copy language when language is 'custom'. */
|
|
377
|
+
customLanguage?: string
|
|
378
|
+
size: string
|
|
379
|
+
productName: string
|
|
380
|
+
sellingPoints: string
|
|
381
|
+
protectedFeatures: string
|
|
382
|
+
styleHint: string
|
|
383
|
+
slots: ProductSetSlot[]
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/** A client → host generate request (what the panel collects). */
|
|
387
|
+
export interface GenerateRequest extends EcommerceTaskMeta {
|
|
388
|
+
/** text-to-image (images/generations) or image-to-image (images/edits). */
|
|
389
|
+
mode: GenerateMode
|
|
390
|
+
/**
|
|
391
|
+
* User-facing model name (an alias from the channel's model catalog). The
|
|
392
|
+
* host maps it onto the configured channel and fills `upstream` with the
|
|
393
|
+
* real id before the engine sees it.
|
|
394
|
+
*/
|
|
395
|
+
model: string
|
|
396
|
+
/** The prompt. Upstream providers may impose their own length limits. */
|
|
397
|
+
prompt: string
|
|
398
|
+
/** Canvas size as an aspect ratio: 'auto' or e.g. '1:1' / '16:9' / '21:9'.
|
|
399
|
+
* The host maps it onto each model's own vocabulary (aspect_ratio for Grok
|
|
400
|
+
* and Nano Banana, resolution-tier size for Seedream, the closest pixel size for
|
|
401
|
+
* OpenAI-compatible endpoints). */
|
|
402
|
+
size: string
|
|
403
|
+
/** Clarity tier: 'auto' | '1k' | '2k' | '4k'. The host maps it onto the
|
|
404
|
+
* model's own vocabulary (resolution for Grok, image_size for Nano Banana,
|
|
405
|
+
* and size for Seedream,
|
|
406
|
+
* Nano Banana, quality for OpenAI). */
|
|
407
|
+
quality: string
|
|
408
|
+
/** Number of images, 1-4. */
|
|
409
|
+
n: number
|
|
410
|
+
/**
|
|
411
|
+
* Passthrough detail parameter: '' (omit), 'standard', or 'high'. Some
|
|
412
|
+
* gpt-image-2 gateways expose it; official OpenAI endpoints reject unknown
|
|
413
|
+
* parameters, so the UI defaults to '' (omit).
|
|
414
|
+
*/
|
|
415
|
+
detail: string
|
|
416
|
+
/** Reference image as a data URL (edit mode only). */
|
|
417
|
+
image?: string
|
|
418
|
+
/** Additional reference images as data URLs (edit mode only). The first
|
|
419
|
+
* image stays in `image`; providers that accept several references get them
|
|
420
|
+
* all, single-reference providers see `image` alone. */
|
|
421
|
+
images?: string[]
|
|
422
|
+
/** Original reference-image name, retained in the history entry. */
|
|
423
|
+
refName?: string
|
|
424
|
+
/** Channel this request targets (the host falls back to the default when
|
|
425
|
+
* absent, and re-routes by model alias when the alias lives elsewhere). */
|
|
426
|
+
channelId?: string
|
|
427
|
+
/** Channel display name snapshot, kept on the history entry (host-filled). */
|
|
428
|
+
channel?: string
|
|
429
|
+
/** Upstream model id actually sent to the gateway (host-filled from the
|
|
430
|
+
* alias mapping; defaults to `model` when absent). */
|
|
431
|
+
upstream?: string
|
|
432
|
+
/** Stable client-created id shared by the tasks in one comparison run. */
|
|
433
|
+
comparisonId?: string
|
|
434
|
+
/** All model aliases selected for one comparison run. */
|
|
435
|
+
comparisonModels?: string[]
|
|
436
|
+
/** Optional canvas lineage metadata. */
|
|
437
|
+
canvas?: CanvasTaskMeta
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/** One generated image, normalized host-side to base64 so the browser never
|
|
441
|
+
* has to fetch the upstream (no CORS, no key exposure). */
|
|
442
|
+
export interface GeneratedImage {
|
|
443
|
+
/** Raw base64 payload (no data: prefix). */
|
|
444
|
+
b64: string
|
|
445
|
+
/** MIME type of the payload, e.g. image/png. */
|
|
446
|
+
mime: string
|
|
447
|
+
/** Upstream revised prompt, when provided. */
|
|
448
|
+
revisedPrompt?: string
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/** Successful generate outcome. */
|
|
452
|
+
export interface GenerateResult {
|
|
453
|
+
images: GeneratedImage[]
|
|
454
|
+
/** Updated host-persisted history, when returned by the generate route. */
|
|
455
|
+
history?: HistoryEntry[]
|
|
456
|
+
/** Persistence failure after images were successfully generated. */
|
|
457
|
+
historyError?: string
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
/**
|
|
461
|
+
* One model mapping in a channel's catalog: the display alias the user, the
|
|
462
|
+
* panel, and the Agent see, and the upstream model id actually sent to the
|
|
463
|
+
* gateway. The alias defaults to the upstream id but can be renamed freely.
|
|
464
|
+
*/
|
|
465
|
+
export interface ModelMapping {
|
|
466
|
+
/** User-facing model name (defaults to the upstream id). */
|
|
467
|
+
alias: string
|
|
468
|
+
/** Upstream model id sent to the gateway. */
|
|
469
|
+
id: string
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
/**
|
|
473
|
+
* One configured image channel (provider). Secrets never live here — the API
|
|
474
|
+
* key is stored at `channelSecrets.<channelId>` in the settings document so
|
|
475
|
+
* whole-array writes can never clobber keys the user did not re-enter.
|
|
476
|
+
*/
|
|
477
|
+
export interface ChannelConfig {
|
|
478
|
+
/** Stable channel id (the channelSecrets dict is keyed by it). */
|
|
479
|
+
id: string
|
|
480
|
+
/** Preset provider id this channel was created from ('' = custom). */
|
|
481
|
+
preset: string
|
|
482
|
+
/** Display name shown in the list, the panel, and Agent guidance. */
|
|
483
|
+
name: string
|
|
484
|
+
/** OpenAI-compatible base URL. */
|
|
485
|
+
apiUrl: string
|
|
486
|
+
/** The channel's model catalog (alias → upstream id). */
|
|
487
|
+
models: ModelMapping[]
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/** One built-in provider as the settings card consumes it. */
|
|
491
|
+
export interface PresetProviderView {
|
|
492
|
+
id: string
|
|
493
|
+
name: string
|
|
494
|
+
apiUrl: string
|
|
495
|
+
hint: string
|
|
496
|
+
models: ModelMapping[]
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
export type GenerationTaskStatus = 'queued' | 'running' | 'completed' | 'failed' | 'cancelled'
|
|
500
|
+
|
|
501
|
+
export interface GenerationTask extends EcommerceTaskMeta {
|
|
502
|
+
id: string
|
|
503
|
+
request: GenerateRequest
|
|
504
|
+
status: GenerationTaskStatus
|
|
505
|
+
createdAt: number
|
|
506
|
+
startedAt?: number
|
|
507
|
+
finishedAt?: number
|
|
508
|
+
result?: GenerateResult
|
|
509
|
+
error?: string
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
/** GitHub Release update information shown by the client. */
|
|
513
|
+
export interface UpdateInfo {
|
|
514
|
+
currentVersion: string
|
|
515
|
+
latestVersion: string
|
|
516
|
+
updateAvailable: boolean
|
|
517
|
+
releaseUrl: string
|
|
518
|
+
publishedAt?: string
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
/** One history image reference as the browser consumes it (a served URL). */
|
|
522
|
+
export interface HistoryImageRef {
|
|
523
|
+
/** Same-origin URL: `${HISTORY_API.image}/<file>`. */
|
|
524
|
+
url: string
|
|
525
|
+
/** MIME type, e.g. image/png. */
|
|
526
|
+
mime: string
|
|
527
|
+
/** Upstream revised prompt, when provided. */
|
|
528
|
+
revisedPrompt?: string
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
/** A saved generation as the browser consumes it (metadata + served images). */
|
|
532
|
+
export interface HistoryEntry extends EcommerceTaskMeta {
|
|
533
|
+
id: string
|
|
534
|
+
createdAt: number
|
|
535
|
+
mode: GenerateMode
|
|
536
|
+
model: string
|
|
537
|
+
prompt: string
|
|
538
|
+
size: string
|
|
539
|
+
quality: string
|
|
540
|
+
detail: string
|
|
541
|
+
n: number
|
|
542
|
+
images: HistoryImageRef[]
|
|
543
|
+
/** Reference-image filename (edit mode), kept for display only. */
|
|
544
|
+
refName?: string
|
|
545
|
+
/** User-managed gallery labels (unused by history entries). */
|
|
546
|
+
tags?: string[]
|
|
547
|
+
/** Channel id snapshot (usage counters key by it for new entries). */
|
|
548
|
+
channelId?: string
|
|
549
|
+
/** Channel display name snapshot (survives channel deletion). */
|
|
550
|
+
channel?: string
|
|
551
|
+
/** Stable id shared by the history entries in one comparison run. */
|
|
552
|
+
comparisonId?: string
|
|
553
|
+
/** Model aliases included in the comparison run. */
|
|
554
|
+
comparisonModels?: string[]
|
|
555
|
+
canvas?: CanvasTaskMeta
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
/** A history entry the client submits for persistence (images still carry base64). */
|
|
559
|
+
export interface HistoryEntryInput extends EcommerceTaskMeta {
|
|
560
|
+
id: string
|
|
561
|
+
createdAt: number
|
|
562
|
+
mode: GenerateMode
|
|
563
|
+
model: string
|
|
564
|
+
prompt: string
|
|
565
|
+
size: string
|
|
566
|
+
quality: string
|
|
567
|
+
detail: string
|
|
568
|
+
n: number
|
|
569
|
+
images: GeneratedImage[]
|
|
570
|
+
refName?: string
|
|
571
|
+
/** Channel id snapshot, tallied by the usage endpoint. */
|
|
572
|
+
channelId?: string
|
|
573
|
+
/** Channel display name snapshot (survives channel deletion). */
|
|
574
|
+
channel?: string
|
|
575
|
+
/** Stable id shared by the history entries in one comparison run. */
|
|
576
|
+
comparisonId?: string
|
|
577
|
+
/** Model aliases included in the comparison run. */
|
|
578
|
+
comparisonModels?: string[]
|
|
579
|
+
canvas?: CanvasTaskMeta
|
|
580
|
+
}
|