@dickpy/dsh-imagegen 1.4.0 → 1.5.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.
Files changed (54) hide show
  1. package/LICENSE +201 -201
  2. package/README.md +270 -124
  3. package/cordis.patch.yml +8 -8
  4. package/docs/images/ecommerce-mode.png +0 -0
  5. package/docs/images/image-generation-studio-three-column.png +0 -0
  6. package/docs/images/imagegen-overview.png +0 -0
  7. package/docs/videos/agent-chat-edit.gif +0 -0
  8. package/docs/videos/agent-chat-edit.mp4 +0 -0
  9. package/lib/client.js +1873 -431
  10. package/lib/client.js.map +1 -1
  11. package/lib/index.js +355 -116
  12. package/package.json +77 -70
  13. package/src/agent-image-tools.ts +447 -418
  14. package/src/client/ImageGenPanel.tsx +1243 -348
  15. package/src/client/SettingsCard.tsx +936 -936
  16. package/src/client/TemplateLibrary.tsx +336 -336
  17. package/src/client/api.ts +203 -193
  18. package/src/client/channels-form.ts +263 -263
  19. package/src/client/controller.ts +46 -46
  20. package/src/client/conversation-sync.ts +14 -14
  21. package/src/client/css-modules.d.ts +5 -5
  22. package/src/client/helpers.ts +33 -33
  23. package/src/client/image-toolview.module.css +73 -73
  24. package/src/client/image-toolview.tsx +34 -28
  25. package/src/client/index.ts +25 -24
  26. package/src/client/locales.ts +156 -28
  27. package/src/client/mount.tsx +117 -117
  28. package/src/client/panel.module.css +1243 -455
  29. package/src/client/settings-card.module.css +1023 -1023
  30. package/src/client/settings-form.ts +337 -336
  31. package/src/client/settings-scope.ts +302 -298
  32. package/src/client/sidebar-entry.ts +190 -190
  33. package/src/client/templates.module.css +453 -453
  34. package/src/edit-image-command.ts +110 -0
  35. package/src/engine.ts +520 -520
  36. package/src/gallery-store.ts +306 -286
  37. package/src/generation-runtime.ts +84 -79
  38. package/src/history-store.ts +270 -250
  39. package/src/image-format.ts +11 -11
  40. package/src/image-models.ts +19 -19
  41. package/src/index.ts +337 -318
  42. package/src/model-catalog.ts +115 -115
  43. package/src/presets.ts +71 -71
  44. package/src/prompt-enhancer.ts +137 -137
  45. package/src/protocol.ts +380 -338
  46. package/src/routes.ts +966 -916
  47. package/src/settings-compat.ts +60 -0
  48. package/src/task-queue.ts +113 -113
  49. package/src/templates/cases.json +10196 -10196
  50. package/src/templates-store.ts +278 -278
  51. package/src/updater.ts +117 -117
  52. package/docs/images/agent-chat-edit.png +0 -0
  53. package/docs/images/agent-chat-generate.png +0 -0
  54. package/docs/images/agent-chat-poster-workflow.png +0 -0
package/src/protocol.ts CHANGED
@@ -1,338 +1,380 @@
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.3.1'
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
- /**
40
- * Host-computed per-channel usage counters (generation-count badges in the
41
- * settings card): entries are tallied from the persisted history and gallery
42
- * by channel + model alias.
43
- */
44
- export const USAGE_API = '/api/dsh-imagegen/usage' as const
45
-
46
- /** Host-resident generation queue endpoints. */
47
- export const TASK_API = {
48
- submit: '/api/dsh-imagegen/tasks/submit',
49
- list: '/api/dsh-imagegen/tasks/list',
50
- cancel: '/api/dsh-imagegen/tasks/cancel',
51
- retry: '/api/dsh-imagegen/tasks/retry',
52
- } as const
53
-
54
- /** Host-mediated GitHub Release update routes. */
55
- export const UPDATE_API = {
56
- check: '/api/dsh-imagegen/update/check',
57
- apply: '/api/dsh-imagegen/update/apply',
58
- } as const
59
-
60
- /**
61
- * Same-origin route family for the host-persisted generation history. Images
62
- * live as files under ~/.dsh/dsh-imagegen/images/ and are served back through
63
- * the `image` prefix route, so list responses carry metadata only (never
64
- * base64) and the browser loads thumbnails/previews lazily.
65
- */
66
- export const HISTORY_API = {
67
- list: '/api/dsh-imagegen/history/list',
68
- append: '/api/dsh-imagegen/history/append',
69
- remove: '/api/dsh-imagegen/history/remove',
70
- clear: '/api/dsh-imagegen/history/clear',
71
- image: '/api/dsh-imagegen/history/image',
72
- } as const
73
-
74
- /**
75
- * Same-origin route family for the user-curated gallery (favorites). Entries
76
- * reuse the history wire shape and persist under ~/.dsh/dsh-imagegen/gallery/;
77
- * unlike history there is no size cap 鈥?the user adds images on purpose.
78
- */
79
- export const GALLERY_API = {
80
- list: '/api/dsh-imagegen/gallery/list',
81
- append: '/api/dsh-imagegen/gallery/append',
82
- remove: '/api/dsh-imagegen/gallery/remove',
83
- clear: '/api/dsh-imagegen/gallery/clear',
84
- tags: '/api/dsh-imagegen/gallery/tags',
85
- image: '/api/dsh-imagegen/gallery/image',
86
- } as const
87
-
88
- /** Maximum number of history entries retained host-side (oldest evicted). */
89
- export const HISTORY_MAX = 50
90
-
91
- /**
92
- * Same-origin route family for the bundled prompt-template library
93
- * (awesome-gpt-image-2 mirror). The case list ships inside the package and is
94
- * served by the host; reference images are proxied through the `image` prefix
95
- * route and cached on disk so repeated views never hit the network again.
96
- */
97
- export const TEMPLATES_API = {
98
- list: '/api/dsh-imagegen/templates/list',
99
- refresh: '/api/dsh-imagegen/templates/refresh',
100
- image: '/api/dsh-imagegen/templates/image',
101
- } as const
102
-
103
- /** One prompt-library case as the browser consumes it. */
104
- export interface TemplateCase {
105
- /** Upstream case number (stable across refreshes). */
106
- id: number
107
- /** Short case title. */
108
- title: string
109
- /** Full reusable prompt text. */
110
- prompt: string
111
- /** English category name (grouping key). */
112
- category: string
113
- /** Chinese category display name. */
114
- categoryZh: string
115
- /** Style tags. */
116
- styles: string[]
117
- /** Scene tags. */
118
- scenes: string[]
119
- /** Original author handle, e.g. @vista8. */
120
- sourceLabel: string
121
- /** Original author link. */
122
- sourceUrl: string
123
- /** awesome-gpt-image-2 repo anchor link. */
124
- githubUrl: string
125
- /** Reference-image file name served through the image route ('' when none). */
126
- image: string
127
- /** Whether the source gallery featured the case. */
128
- featured: boolean
129
- }
130
-
131
- /** Template-library list payload. */
132
- export interface TemplateListResult {
133
- cases: TemplateCase[]
134
- total: number
135
- /** Where the served list came from. */
136
- origin: 'bundled' | 'refreshed'
137
- /** Upstream repository the library mirrors. */
138
- repository: string
139
- /** ISO time of the last successful refresh / bundle snapshot. */
140
- fetchedAt: string
141
- }
142
-
143
- /** Template-library refresh outcome. */
144
- export interface TemplateRefreshResult {
145
- total: number
146
- fetchedAt: string
147
- }
148
-
149
- /** Generation modes. */
150
- export type GenerateMode = 'text' | 'edit'
151
-
152
- /** A client → host generate request (what the panel collects). */
153
- export interface GenerateRequest {
154
- /** text-to-image (images/generations) or image-to-image (images/edits). */
155
- mode: GenerateMode
156
- /**
157
- * User-facing model name (an alias from the channel's model catalog). The
158
- * host maps it onto the configured channel and fills `upstream` with the
159
- * real id before the engine sees it.
160
- */
161
- model: string
162
- /** The prompt. Upstream providers may impose their own length limits. */
163
- prompt: string
164
- /** Canvas size as an aspect ratio: 'auto' or e.g. '1:1' / '16:9' / '21:9'.
165
- * The host maps it onto each model's own vocabulary (aspect_ratio for Grok
166
- * and Nano Banana, resolution-tier size for Seedream, the closest pixel size for
167
- * OpenAI-compatible endpoints). */
168
- size: string
169
- /** Clarity tier: 'auto' | '1k' | '2k' | '4k'. The host maps it onto the
170
- * model's own vocabulary (resolution for Grok, image_size for Nano Banana,
171
- * and size for Seedream,
172
- * Nano Banana, quality for OpenAI). */
173
- quality: string
174
- /** Number of images, 1-4. */
175
- n: number
176
- /**
177
- * Passthrough detail parameter: '' (omit), 'standard', or 'high'. Some
178
- * gpt-image-2 gateways expose it; official OpenAI endpoints reject unknown
179
- * parameters, so the UI defaults to '' (omit).
180
- */
181
- detail: string
182
- /** Reference image as a data URL (edit mode only). */
183
- image?: string
184
- /** Original reference-image name, retained in the history entry. */
185
- refName?: string
186
- /** Channel this request targets (the host falls back to the default when
187
- * absent, and re-routes by model alias when the alias lives elsewhere). */
188
- channelId?: string
189
- /** Channel display name snapshot, kept on the history entry (host-filled). */
190
- channel?: string
191
- /** Upstream model id actually sent to the gateway (host-filled from the
192
- * alias mapping; defaults to `model` when absent). */
193
- upstream?: string
194
- /** Stable client-created id shared by the tasks in one comparison run. */
195
- comparisonId?: string
196
- /** All model aliases selected for one comparison run. */
197
- comparisonModels?: string[]
198
- }
199
-
200
- /** One generated image, normalized host-side to base64 so the browser never
201
- * has to fetch the upstream (no CORS, no key exposure). */
202
- export interface GeneratedImage {
203
- /** Raw base64 payload (no data: prefix). */
204
- b64: string
205
- /** MIME type of the payload, e.g. image/png. */
206
- mime: string
207
- /** Upstream revised prompt, when provided. */
208
- revisedPrompt?: string
209
- }
210
-
211
- /** Successful generate outcome. */
212
- export interface GenerateResult {
213
- images: GeneratedImage[]
214
- /** Updated host-persisted history, when returned by the generate route. */
215
- history?: HistoryEntry[]
216
- /** Persistence failure after images were successfully generated. */
217
- historyError?: string
218
- }
219
-
220
- /**
221
- * One model mapping in a channel's catalog: the display alias the user, the
222
- * panel, and the Agent see, and the upstream model id actually sent to the
223
- * gateway. The alias defaults to the upstream id but can be renamed freely.
224
- */
225
- export interface ModelMapping {
226
- /** User-facing model name (defaults to the upstream id). */
227
- alias: string
228
- /** Upstream model id sent to the gateway. */
229
- id: string
230
- }
231
-
232
- /**
233
- * One configured image channel (provider). Secrets never live here the API
234
- * key is stored at `channelSecrets.<channelId>` in the settings document so
235
- * whole-array writes can never clobber keys the user did not re-enter.
236
- */
237
- export interface ChannelConfig {
238
- /** Stable channel id (the channelSecrets dict is keyed by it). */
239
- id: string
240
- /** Preset provider id this channel was created from ('' = custom). */
241
- preset: string
242
- /** Display name shown in the list, the panel, and Agent guidance. */
243
- name: string
244
- /** OpenAI-compatible base URL. */
245
- apiUrl: string
246
- /** The channel's model catalog (alias → upstream id). */
247
- models: ModelMapping[]
248
- }
249
-
250
- /** One built-in provider as the settings card consumes it. */
251
- export interface PresetProviderView {
252
- id: string
253
- name: string
254
- apiUrl: string
255
- hint: string
256
- models: ModelMapping[]
257
- }
258
-
259
- export type GenerationTaskStatus = 'queued' | 'running' | 'completed' | 'failed' | 'cancelled'
260
-
261
- export interface GenerationTask {
262
- id: string
263
- request: GenerateRequest
264
- status: GenerationTaskStatus
265
- createdAt: number
266
- startedAt?: number
267
- finishedAt?: number
268
- result?: GenerateResult
269
- error?: string
270
- }
271
-
272
- /** GitHub Release update information shown by the client. */
273
- export interface UpdateInfo {
274
- currentVersion: string
275
- latestVersion: string
276
- updateAvailable: boolean
277
- releaseUrl: string
278
- publishedAt?: string
279
- }
280
-
281
- /** One history image reference as the browser consumes it (a served URL). */
282
- export interface HistoryImageRef {
283
- /** Same-origin URL: `${HISTORY_API.image}/<file>`. */
284
- url: string
285
- /** MIME type, e.g. image/png. */
286
- mime: string
287
- /** Upstream revised prompt, when provided. */
288
- revisedPrompt?: string
289
- }
290
-
291
- /** A saved generation as the browser consumes it (metadata + served images). */
292
- export interface HistoryEntry {
293
- id: string
294
- createdAt: number
295
- mode: GenerateMode
296
- model: string
297
- prompt: string
298
- size: string
299
- quality: string
300
- detail: string
301
- n: number
302
- images: HistoryImageRef[]
303
- /** Reference-image filename (edit mode), kept for display only. */
304
- refName?: string
305
- /** User-managed gallery labels (unused by history entries). */
306
- tags?: string[]
307
- /** Channel id snapshot (usage counters key by it for new entries). */
308
- channelId?: string
309
- /** Channel display name snapshot (survives channel deletion). */
310
- channel?: string
311
- /** Stable id shared by the history entries in one comparison run. */
312
- comparisonId?: string
313
- /** Model aliases included in the comparison run. */
314
- comparisonModels?: string[]
315
- }
316
-
317
- /** A history entry the client submits for persistence (images still carry base64). */
318
- export interface HistoryEntryInput {
319
- id: string
320
- createdAt: number
321
- mode: GenerateMode
322
- model: string
323
- prompt: string
324
- size: string
325
- quality: string
326
- detail: string
327
- n: number
328
- images: GeneratedImage[]
329
- refName?: string
330
- /** Channel id snapshot, tallied by the usage endpoint. */
331
- channelId?: string
332
- /** Channel display name snapshot (survives channel deletion). */
333
- channel?: string
334
- /** Stable id shared by the history entries in one comparison run. */
335
- comparisonId?: string
336
- /** Model aliases included in the comparison run. */
337
- comparisonModels?: string[]
338
- }
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.1'
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
+ /** Host-mediated GitHub Release update routes. */
58
+ export const UPDATE_API = {
59
+ check: '/api/dsh-imagegen/update/check',
60
+ apply: '/api/dsh-imagegen/update/apply',
61
+ } as const
62
+
63
+ /**
64
+ * Same-origin route family for the host-persisted generation history. Images
65
+ * live as files under ~/.dsh/dsh-imagegen/images/ and are served back through
66
+ * the `image` prefix route, so list responses carry metadata only (never
67
+ * base64) and the browser loads thumbnails/previews lazily.
68
+ */
69
+ export const HISTORY_API = {
70
+ list: '/api/dsh-imagegen/history/list',
71
+ append: '/api/dsh-imagegen/history/append',
72
+ remove: '/api/dsh-imagegen/history/remove',
73
+ clear: '/api/dsh-imagegen/history/clear',
74
+ image: '/api/dsh-imagegen/history/image',
75
+ } as const
76
+
77
+ /**
78
+ * Same-origin route family for the user-curated gallery (favorites). Entries
79
+ * reuse the history wire shape and persist under ~/.dsh/dsh-imagegen/gallery/;
80
+ * unlike history there is no size cap 鈥?the user adds images on purpose.
81
+ */
82
+ export const GALLERY_API = {
83
+ list: '/api/dsh-imagegen/gallery/list',
84
+ append: '/api/dsh-imagegen/gallery/append',
85
+ remove: '/api/dsh-imagegen/gallery/remove',
86
+ clear: '/api/dsh-imagegen/gallery/clear',
87
+ tags: '/api/dsh-imagegen/gallery/tags',
88
+ image: '/api/dsh-imagegen/gallery/image',
89
+ } as const
90
+
91
+ /** Maximum number of history entries retained host-side (oldest evicted). */
92
+ export const HISTORY_MAX = 50
93
+
94
+ /**
95
+ * Same-origin route family for the bundled prompt-template library
96
+ * (awesome-gpt-image-2 mirror). The case list ships inside the package and is
97
+ * served by the host; reference images are proxied through the `image` prefix
98
+ * route and cached on disk so repeated views never hit the network again.
99
+ */
100
+ export const TEMPLATES_API = {
101
+ list: '/api/dsh-imagegen/templates/list',
102
+ refresh: '/api/dsh-imagegen/templates/refresh',
103
+ image: '/api/dsh-imagegen/templates/image',
104
+ } as const
105
+
106
+ /** One prompt-library case as the browser consumes it. */
107
+ export interface TemplateCase {
108
+ /** Upstream case number (stable across refreshes). */
109
+ id: number
110
+ /** Short case title. */
111
+ title: string
112
+ /** Full reusable prompt text. */
113
+ prompt: string
114
+ /** English category name (grouping key). */
115
+ category: string
116
+ /** Chinese category display name. */
117
+ categoryZh: string
118
+ /** Style tags. */
119
+ styles: string[]
120
+ /** Scene tags. */
121
+ scenes: string[]
122
+ /** Original author handle, e.g. @vista8. */
123
+ sourceLabel: string
124
+ /** Original author link. */
125
+ sourceUrl: string
126
+ /** awesome-gpt-image-2 repo anchor link. */
127
+ githubUrl: string
128
+ /** Reference-image file name served through the image route ('' when none). */
129
+ image: string
130
+ /** Whether the source gallery featured the case. */
131
+ featured: boolean
132
+ }
133
+
134
+ /** Template-library list payload. */
135
+ export interface TemplateListResult {
136
+ cases: TemplateCase[]
137
+ total: number
138
+ /** Where the served list came from. */
139
+ origin: 'bundled' | 'refreshed'
140
+ /** Upstream repository the library mirrors. */
141
+ repository: string
142
+ /** ISO time of the last successful refresh / bundle snapshot. */
143
+ fetchedAt: string
144
+ }
145
+
146
+ /** Template-library refresh outcome. */
147
+ export interface TemplateRefreshResult {
148
+ total: number
149
+ fetchedAt: string
150
+ }
151
+
152
+ /** Generation modes. */
153
+ export type GenerateMode = 'text' | 'edit'
154
+
155
+ /** Metadata shared by the ecommerce product-set workflow. */
156
+ export interface EcommerceTaskMeta {
157
+ workflow?: 'ecommerce'
158
+ projectId?: string
159
+ projectName?: string
160
+ slotKey?: string
161
+ slotLabel?: string
162
+ }
163
+
164
+ /** Role an uploaded product asset plays in the ecommerce workflow. 'none' is
165
+ * only used as a slot selection meaning "generate without a reference". */
166
+ export type EcommerceRefRole = 'none' | 'product' | 'packaging' | 'detail' | 'style'
167
+
168
+ /** One planned image slot in a product set. */
169
+ export interface ProductSetSlot {
170
+ key: string
171
+ label: string
172
+ description: string
173
+ count: number
174
+ enabled: boolean
175
+ /** Which uploaded asset role this slot uses as its edit reference. */
176
+ refRole?: EcommerceRefRole
177
+ }
178
+
179
+ /** A browser-local ecommerce product-set draft. */
180
+ export interface ProductSetDraft {
181
+ projectId: string
182
+ projectName: string
183
+ category: string
184
+ platform: string
185
+ language: string
186
+ size: string
187
+ productName: string
188
+ sellingPoints: string
189
+ protectedFeatures: string
190
+ styleHint: string
191
+ slots: ProductSetSlot[]
192
+ }
193
+
194
+ /** A client host generate request (what the panel collects). */
195
+ export interface GenerateRequest extends EcommerceTaskMeta {
196
+ /** text-to-image (images/generations) or image-to-image (images/edits). */
197
+ mode: GenerateMode
198
+ /**
199
+ * User-facing model name (an alias from the channel's model catalog). The
200
+ * host maps it onto the configured channel and fills `upstream` with the
201
+ * real id before the engine sees it.
202
+ */
203
+ model: string
204
+ /** The prompt. Upstream providers may impose their own length limits. */
205
+ prompt: string
206
+ /** Canvas size as an aspect ratio: 'auto' or e.g. '1:1' / '16:9' / '21:9'.
207
+ * The host maps it onto each model's own vocabulary (aspect_ratio for Grok
208
+ * and Nano Banana, resolution-tier size for Seedream, the closest pixel size for
209
+ * OpenAI-compatible endpoints). */
210
+ size: string
211
+ /** Clarity tier: 'auto' | '1k' | '2k' | '4k'. The host maps it onto the
212
+ * model's own vocabulary (resolution for Grok, image_size for Nano Banana,
213
+ * and size for Seedream,
214
+ * Nano Banana, quality for OpenAI). */
215
+ quality: string
216
+ /** Number of images, 1-4. */
217
+ n: number
218
+ /**
219
+ * Passthrough detail parameter: '' (omit), 'standard', or 'high'. Some
220
+ * gpt-image-2 gateways expose it; official OpenAI endpoints reject unknown
221
+ * parameters, so the UI defaults to '' (omit).
222
+ */
223
+ detail: string
224
+ /** Reference image as a data URL (edit mode only). */
225
+ image?: string
226
+ /** Original reference-image name, retained in the history entry. */
227
+ refName?: string
228
+ /** Channel this request targets (the host falls back to the default when
229
+ * absent, and re-routes by model alias when the alias lives elsewhere). */
230
+ channelId?: string
231
+ /** Channel display name snapshot, kept on the history entry (host-filled). */
232
+ channel?: string
233
+ /** Upstream model id actually sent to the gateway (host-filled from the
234
+ * alias mapping; defaults to `model` when absent). */
235
+ upstream?: string
236
+ /** Stable client-created id shared by the tasks in one comparison run. */
237
+ comparisonId?: string
238
+ /** All model aliases selected for one comparison run. */
239
+ comparisonModels?: string[]
240
+ }
241
+
242
+ /** One generated image, normalized host-side to base64 so the browser never
243
+ * has to fetch the upstream (no CORS, no key exposure). */
244
+ export interface GeneratedImage {
245
+ /** Raw base64 payload (no data: prefix). */
246
+ b64: string
247
+ /** MIME type of the payload, e.g. image/png. */
248
+ mime: string
249
+ /** Upstream revised prompt, when provided. */
250
+ revisedPrompt?: string
251
+ }
252
+
253
+ /** Successful generate outcome. */
254
+ export interface GenerateResult {
255
+ images: GeneratedImage[]
256
+ /** Updated host-persisted history, when returned by the generate route. */
257
+ history?: HistoryEntry[]
258
+ /** Persistence failure after images were successfully generated. */
259
+ historyError?: string
260
+ }
261
+
262
+ /**
263
+ * One model mapping in a channel's catalog: the display alias the user, the
264
+ * panel, and the Agent see, and the upstream model id actually sent to the
265
+ * gateway. The alias defaults to the upstream id but can be renamed freely.
266
+ */
267
+ export interface ModelMapping {
268
+ /** User-facing model name (defaults to the upstream id). */
269
+ alias: string
270
+ /** Upstream model id sent to the gateway. */
271
+ id: string
272
+ }
273
+
274
+ /**
275
+ * One configured image channel (provider). Secrets never live here — the API
276
+ * key is stored at `channelSecrets.<channelId>` in the settings document so
277
+ * whole-array writes can never clobber keys the user did not re-enter.
278
+ */
279
+ export interface ChannelConfig {
280
+ /** Stable channel id (the channelSecrets dict is keyed by it). */
281
+ id: string
282
+ /** Preset provider id this channel was created from ('' = custom). */
283
+ preset: string
284
+ /** Display name shown in the list, the panel, and Agent guidance. */
285
+ name: string
286
+ /** OpenAI-compatible base URL. */
287
+ apiUrl: string
288
+ /** The channel's model catalog (alias → upstream id). */
289
+ models: ModelMapping[]
290
+ }
291
+
292
+ /** One built-in provider as the settings card consumes it. */
293
+ export interface PresetProviderView {
294
+ id: string
295
+ name: string
296
+ apiUrl: string
297
+ hint: string
298
+ models: ModelMapping[]
299
+ }
300
+
301
+ export type GenerationTaskStatus = 'queued' | 'running' | 'completed' | 'failed' | 'cancelled'
302
+
303
+ export interface GenerationTask extends EcommerceTaskMeta {
304
+ id: string
305
+ request: GenerateRequest
306
+ status: GenerationTaskStatus
307
+ createdAt: number
308
+ startedAt?: number
309
+ finishedAt?: number
310
+ result?: GenerateResult
311
+ error?: string
312
+ }
313
+
314
+ /** GitHub Release update information shown by the client. */
315
+ export interface UpdateInfo {
316
+ currentVersion: string
317
+ latestVersion: string
318
+ updateAvailable: boolean
319
+ releaseUrl: string
320
+ publishedAt?: string
321
+ }
322
+
323
+ /** One history image reference as the browser consumes it (a served URL). */
324
+ export interface HistoryImageRef {
325
+ /** Same-origin URL: `${HISTORY_API.image}/<file>`. */
326
+ url: string
327
+ /** MIME type, e.g. image/png. */
328
+ mime: string
329
+ /** Upstream revised prompt, when provided. */
330
+ revisedPrompt?: string
331
+ }
332
+
333
+ /** A saved generation as the browser consumes it (metadata + served images). */
334
+ export interface HistoryEntry extends EcommerceTaskMeta {
335
+ id: string
336
+ createdAt: number
337
+ mode: GenerateMode
338
+ model: string
339
+ prompt: string
340
+ size: string
341
+ quality: string
342
+ detail: string
343
+ n: number
344
+ images: HistoryImageRef[]
345
+ /** Reference-image filename (edit mode), kept for display only. */
346
+ refName?: string
347
+ /** User-managed gallery labels (unused by history entries). */
348
+ tags?: string[]
349
+ /** Channel id snapshot (usage counters key by it for new entries). */
350
+ channelId?: string
351
+ /** Channel display name snapshot (survives channel deletion). */
352
+ channel?: string
353
+ /** Stable id shared by the history entries in one comparison run. */
354
+ comparisonId?: string
355
+ /** Model aliases included in the comparison run. */
356
+ comparisonModels?: string[]
357
+ }
358
+
359
+ /** A history entry the client submits for persistence (images still carry base64). */
360
+ export interface HistoryEntryInput extends EcommerceTaskMeta {
361
+ id: string
362
+ createdAt: number
363
+ mode: GenerateMode
364
+ model: string
365
+ prompt: string
366
+ size: string
367
+ quality: string
368
+ detail: string
369
+ n: number
370
+ images: GeneratedImage[]
371
+ refName?: string
372
+ /** Channel id snapshot, tallied by the usage endpoint. */
373
+ channelId?: string
374
+ /** Channel display name snapshot (survives channel deletion). */
375
+ channel?: string
376
+ /** Stable id shared by the history entries in one comparison run. */
377
+ comparisonId?: string
378
+ /** Model aliases included in the comparison run. */
379
+ comparisonModels?: string[]
380
+ }