@dickpy/dsh-imagegen 1.0.5 → 1.0.6

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 CHANGED
@@ -14,7 +14,13 @@ DeepSeek Harness (DSH) Web GUI 的 AI 生图插件。它通过宿主进程安全
14
14
 
15
15
  三栏工作台将参数、生成结果和历史记录放在同一视图中;生成的图片可预览、下载,并从历史记录恢复参数。
16
16
 
17
- ![AI 生图工作台(v1.0.5 结果画布)](docs/images/image-generation-studio.png)
17
+ **四图结果布局**
18
+
19
+ ![AI 生图工作台四图结果布局](docs/images/image-generation-studio-four.png)
20
+
21
+ **单图结果布局**
22
+
23
+ ![AI 生图工作台单图结果布局](docs/images/image-generation-studio-single.png)
18
24
 
19
25
  ### 独立配置卡片
20
26
 
@@ -42,13 +48,13 @@ DeepSeek Harness (DSH) Web GUI 的 AI 生图插件。它通过宿主进程安全
42
48
  把下面提示词直接粘贴给 **DSH**(或 Codex / 其他 coding agent)执行即可:
43
49
 
44
50
  ```text
45
- 用 dsh plugin --profile web add @dickpy/dsh-imagegen@1.0.5 安装 AI 生图插件(profile 名按实际修改),完成后重启 dsh web。
51
+ 用 dsh plugin --profile web add @dickpy/dsh-imagegen@1.0.6 安装 AI 生图插件(profile 名按实际修改),完成后重启 dsh web。
46
52
  ```
47
53
 
48
54
  ### 方式二:npm 安装(推荐)
49
55
 
50
56
  ```bash
51
- dsh plugin --profile web add @dickpy/dsh-imagegen@1.0.5
57
+ dsh plugin --profile web add @dickpy/dsh-imagegen@1.0.6
52
58
  ```
53
59
 
54
60
  dsh 会自动把插件注册进 profile 的 bundle 清单(无需手动改 cordis.patch.yml),重启 dsh web 即可。
@@ -56,10 +62,10 @@ dsh 会自动把插件注册进 profile 的 bundle 清单(无需手动改 cord
56
62
  ### 方式三:聚合包(tarball)安装
57
63
 
58
64
  从 [GitHub Releases](https://github.com/dickpy/dsh-imagegen/releases) 下载发布产物
59
- (如 `dickpy-dsh-imagegen-1.0.5.tgz`),然后:
65
+ (如 `dickpy-dsh-imagegen-1.0.6.tgz`),然后:
60
66
 
61
67
  ```bash
62
- dsh plugin --profile web add <下载路径>/dickpy-dsh-imagegen-1.0.5.tgz
68
+ dsh plugin --profile web add <下载路径>/dickpy-dsh-imagegen-1.0.6.tgz
63
69
  ```
64
70
 
65
71
  重启 dsh web。
package/lib/client.js CHANGED
@@ -12,7 +12,7 @@ window.__ModuleLoader__.load({
12
12
  let _deepseek_ai_dsh_client_runtime_client = require("@deepseek-ai/dsh-client-runtime/client");
13
13
  //#region src/protocol.ts
14
14
  /** Published package version shared by the host updater and the client UI. */
15
- const PLUGIN_VERSION = "1.0.5";
15
+ const PLUGIN_VERSION = "1.0.6";
16
16
  /** Same-origin route family (loopback-only, mirroring the dsh-ssh fence). */
17
17
  const SETTINGS_API = {
18
18
  describe: "/api/dsh-imagegen/settings/describe",
@@ -409,100 +409,100 @@ window.__ModuleLoader__.load({
409
409
  document.head.appendChild(tag);
410
410
  }
411
411
  var panel_module_css_default = {
412
+ "uploadIcon": "Yvqh9W_uploadIcon",
413
+ "bigSpinner": "Yvqh9W_bigSpinner",
414
+ "hiddenFile": "Yvqh9W_hiddenFile",
415
+ "updateRelease": "Yvqh9W_updateRelease",
416
+ "panelSubtitle": "Yvqh9W_panelSubtitle",
417
+ "historyMain": "Yvqh9W_historyMain",
418
+ "view": "Yvqh9W_view",
419
+ "historyAction": "Yvqh9W_historyAction",
420
+ "entryLabel": "Yvqh9W_entryLabel",
421
+ "historyEmpty": "Yvqh9W_historyEmpty",
422
+ "connectionDot": "Yvqh9W_connectionDot",
423
+ "canvasState": "Yvqh9W_canvasState",
424
+ "uploadBox": "Yvqh9W_uploadBox",
425
+ "canvasStateTitle": "Yvqh9W_canvasStateTitle",
412
426
  "lightboxClose": "Yvqh9W_lightboxClose",
413
- "panelHeading": "Yvqh9W_panelHeading",
414
- "modelSelect": "Yvqh9W_modelSelect",
427
+ "lightboxImage": "Yvqh9W_lightboxImage",
428
+ "download": "Yvqh9W_download",
429
+ "entryIcon": "Yvqh9W_entryIcon",
430
+ "canvas": "Yvqh9W_canvas",
431
+ "panelHeader": "Yvqh9W_panelHeader",
415
432
  "config": "Yvqh9W_config",
433
+ "generateInner": "Yvqh9W_generateInner",
434
+ "grid": "Yvqh9W_grid",
416
435
  "history": "Yvqh9W_history",
417
- "lightboxActions": "Yvqh9W_lightboxActions",
418
- "promptFooter": "Yvqh9W_promptFooter",
419
- "historyMeta": "Yvqh9W_historyMeta",
436
+ "lightboxCopy": "Yvqh9W_lightboxCopy",
420
437
  "historyTitle": "Yvqh9W_historyTitle",
421
- "footer": "Yvqh9W_footer",
422
- "historyEmpty": "Yvqh9W_historyEmpty",
423
- "canvasBody": "Yvqh9W_canvasBody",
424
- "connectionStatus": "Yvqh9W_connectionStatus",
425
- "imageCaption": "Yvqh9W_imageCaption",
438
+ "paramGroup": "Yvqh9W_paramGroup",
439
+ "spinner": "Yvqh9W_spinner",
440
+ "modePill": "Yvqh9W_modePill",
441
+ "canvasError": "Yvqh9W_canvasError",
426
442
  "uploadHint": "Yvqh9W_uploadHint",
427
- "optionPill": "Yvqh9W_optionPill",
428
- "download": "Yvqh9W_download",
429
- "lightboxDownload": "Yvqh9W_lightboxDownload",
430
- "lightboxEdit": "Yvqh9W_lightboxEdit",
431
- "generateButton": "Yvqh9W_generateButton",
432
- "card": "Yvqh9W_card",
433
- "uploadBox": "Yvqh9W_uploadBox",
434
- "lightboxCaptionRow": "Yvqh9W_lightboxCaptionRow",
435
- "optionRow": "Yvqh9W_optionRow",
436
- "canvas": "Yvqh9W_canvas",
443
+ "reference": "Yvqh9W_reference",
444
+ "zoomHint": "Yvqh9W_zoomHint",
445
+ "canvasHistoryTag": "Yvqh9W_canvasHistoryTag",
446
+ "lightboxTool": "Yvqh9W_lightboxTool",
447
+ "promptFooter": "Yvqh9W_promptFooter",
448
+ "lightbox": "Yvqh9W_lightbox",
449
+ "canvasEmptyIcon": "Yvqh9W_canvasEmptyIcon",
450
+ "lightboxZoomLevel": "Yvqh9W_lightboxZoomLevel",
451
+ "modelWrap": "Yvqh9W_modelWrap",
437
452
  "updateText": "Yvqh9W_updateText",
438
- "historyItem": "Yvqh9W_historyItem",
439
- "historyList": "Yvqh9W_historyList",
440
- "panelSubtitle": "Yvqh9W_panelSubtitle",
441
453
  "prompt": "Yvqh9W_prompt",
454
+ "historyHeader": "Yvqh9W_historyHeader",
455
+ "updateBanner": "Yvqh9W_updateBanner",
442
456
  "canvasStateHint": "Yvqh9W_canvasStateHint",
443
- "canvasHistoryTag": "Yvqh9W_canvasHistoryTag",
444
- "spinner": "Yvqh9W_spinner",
445
- "dshImageGenSpin": "Yvqh9W_dshImageGenSpin",
446
- "lightboxNav": "Yvqh9W_lightboxNav",
447
- "configScroll": "Yvqh9W_configScroll",
448
- "lightboxTools": "Yvqh9W_lightboxTools",
449
- "lightboxZoomLevel": "Yvqh9W_lightboxZoomLevel",
450
- "lightboxImage": "Yvqh9W_lightboxImage",
451
- "historyPrompt": "Yvqh9W_historyPrompt",
452
- "panelTitle": "Yvqh9W_panelTitle",
453
457
  "updateActions": "Yvqh9W_updateActions",
454
- "modelLabel": "Yvqh9W_modelLabel",
455
- "historyClear": "Yvqh9W_historyClear",
456
- "canvasStateTitle": "Yvqh9W_canvasStateTitle",
457
- "historyInfo": "Yvqh9W_historyInfo",
458
- "historyMain": "Yvqh9W_historyMain",
459
- "connectionDot": "Yvqh9W_connectionDot",
460
- "grid": "Yvqh9W_grid",
461
- "promptCount": "Yvqh9W_promptCount",
462
- "entryLabel": "Yvqh9W_entryLabel",
463
- "updateRelease": "Yvqh9W_updateRelease",
464
- "canvasState": "Yvqh9W_canvasState",
465
- "lightboxCaption": "Yvqh9W_lightboxCaption",
466
- "paramGroup": "Yvqh9W_paramGroup",
467
- "updateBanner": "Yvqh9W_updateBanner",
468
- "historyThumbPlaceholder": "Yvqh9W_historyThumbPlaceholder",
469
- "canvasError": "Yvqh9W_canvasError",
470
- "panelHeader": "Yvqh9W_panelHeader",
471
- "referenceImage": "Yvqh9W_referenceImage",
472
- "canvasEmptyIcon": "Yvqh9W_canvasEmptyIcon",
473
- "bigSpinner": "Yvqh9W_bigSpinner",
474
- "generateInner": "Yvqh9W_generateInner",
475
- "lightboxFigure": "Yvqh9W_lightboxFigure",
476
458
  "optionGrid": "Yvqh9W_optionGrid",
477
- "lightboxTool": "Yvqh9W_lightboxTool",
478
- "lightboxCopy": "Yvqh9W_lightboxCopy",
479
- "modelWrap": "Yvqh9W_modelWrap",
480
- "lightboxMeta": "Yvqh9W_lightboxMeta",
481
- "paramHint": "Yvqh9W_paramHint",
459
+ "historyPrompt": "Yvqh9W_historyPrompt",
460
+ "promptCount": "Yvqh9W_promptCount",
461
+ "modelSelect": "Yvqh9W_modelSelect",
462
+ "canvasBody": "Yvqh9W_canvasBody",
482
463
  "lightboxScaleFrame": "Yvqh9W_lightboxScaleFrame",
483
- "historyActions": "Yvqh9W_historyActions",
484
- "image": "Yvqh9W_image",
485
- "zoomHint": "Yvqh9W_zoomHint",
486
- "modePill": "Yvqh9W_modePill",
487
- "view": "Yvqh9W_view",
464
+ "lightboxMeta": "Yvqh9W_lightboxMeta",
465
+ "panelHeading": "Yvqh9W_panelHeading",
488
466
  "historyThumb": "Yvqh9W_historyThumb",
489
- "historyHeader": "Yvqh9W_historyHeader",
490
- "imageCard": "Yvqh9W_imageCard",
491
- "lightboxIndex": "Yvqh9W_lightboxIndex",
467
+ "historyInfo": "Yvqh9W_historyInfo",
468
+ "referenceImage": "Yvqh9W_referenceImage",
469
+ "entry": "Yvqh9W_entry",
470
+ "optionPill": "Yvqh9W_optionPill",
471
+ "paramLabel": "Yvqh9W_paramLabel",
472
+ "historyClear": "Yvqh9W_historyClear",
492
473
  "panel": "Yvqh9W_panel",
474
+ "panelTitle": "Yvqh9W_panelTitle",
475
+ "historyThumbPlaceholder": "Yvqh9W_historyThumbPlaceholder",
493
476
  "studio": "Yvqh9W_studio",
477
+ "referenceActions": "Yvqh9W_referenceActions",
478
+ "dshImageGenSpin": "Yvqh9W_dshImageGenSpin",
479
+ "lightboxNav": "Yvqh9W_lightboxNav",
480
+ "imageCaption": "Yvqh9W_imageCaption",
481
+ "lightboxTools": "Yvqh9W_lightboxTools",
482
+ "lightboxDownload": "Yvqh9W_lightboxDownload",
483
+ "imageCard": "Yvqh9W_imageCard",
484
+ "paramHint": "Yvqh9W_paramHint",
485
+ "historyList": "Yvqh9W_historyList",
486
+ "historyItem": "Yvqh9W_historyItem",
487
+ "lightboxIndex": "Yvqh9W_lightboxIndex",
488
+ "lightboxFigure": "Yvqh9W_lightboxFigure",
489
+ "optionRow": "Yvqh9W_optionRow",
490
+ "card": "Yvqh9W_card",
491
+ "footer": "Yvqh9W_footer",
492
+ "generateButton": "Yvqh9W_generateButton",
493
+ "canvasMeta": "Yvqh9W_canvasMeta",
494
494
  "lightboxStage": "Yvqh9W_lightboxStage",
495
495
  "modeRow": "Yvqh9W_modeRow",
496
- "canvasMeta": "Yvqh9W_canvasMeta",
497
- "paramLabel": "Yvqh9W_paramLabel",
498
- "entryIcon": "Yvqh9W_entryIcon",
499
- "entry": "Yvqh9W_entry",
500
- "reference": "Yvqh9W_reference",
501
- "historyAction": "Yvqh9W_historyAction",
502
- "lightbox": "Yvqh9W_lightbox",
503
- "referenceActions": "Yvqh9W_referenceActions",
504
- "hiddenFile": "Yvqh9W_hiddenFile",
505
- "uploadIcon": "Yvqh9W_uploadIcon"
496
+ "configScroll": "Yvqh9W_configScroll",
497
+ "historyMeta": "Yvqh9W_historyMeta",
498
+ "image": "Yvqh9W_image",
499
+ "lightboxCaptionRow": "Yvqh9W_lightboxCaptionRow",
500
+ "lightboxCaption": "Yvqh9W_lightboxCaption",
501
+ "lightboxActions": "Yvqh9W_lightboxActions",
502
+ "lightboxEdit": "Yvqh9W_lightboxEdit",
503
+ "modelLabel": "Yvqh9W_modelLabel",
504
+ "connectionStatus": "Yvqh9W_connectionStatus",
505
+ "historyActions": "Yvqh9W_historyActions"
506
506
  };
507
507
  //#endregion
508
508
  //#region src/client/ImageGenPanel.tsx
@@ -2100,35 +2100,35 @@ window.__ModuleLoader__.load({
2100
2100
  document.head.appendChild(tag);
2101
2101
  }
2102
2102
  var settings_card_module_css_default = {
2103
- "versionRow": "i1cc5G_versionRow",
2104
- "body": "i1cc5G_body",
2105
- "badge": "i1cc5G_badge",
2106
- "footer": "i1cc5G_footer",
2107
- "badges": "i1cc5G_badges",
2108
- "discard": "i1cc5G_discard",
2109
- "readOnly": "i1cc5G_readOnly",
2110
- "reset": "i1cc5G_reset",
2111
- "header": "i1cc5G_header",
2112
2103
  "failed": "i1cc5G_failed",
2113
- "card": "i1cc5G_card",
2114
- "save": "i1cc5G_save",
2115
- "chevron": "i1cc5G_chevron",
2116
- "invalid": "i1cc5G_invalid",
2104
+ "versionValue": "i1cc5G_versionValue",
2105
+ "badges": "i1cc5G_badges",
2117
2106
  "input": "i1cc5G_input",
2107
+ "label": "i1cc5G_label",
2108
+ "head": "i1cc5G_head",
2118
2109
  "field": "i1cc5G_field",
2119
- "hint": "i1cc5G_hint",
2110
+ "headText": "i1cc5G_headText",
2111
+ "discard": "i1cc5G_discard",
2112
+ "pending": "i1cc5G_pending",
2120
2113
  "notExposed": "i1cc5G_notExposed",
2121
- "label": "i1cc5G_label",
2122
- "chevronOpen": "i1cc5G_chevronOpen",
2114
+ "badge": "i1cc5G_badge",
2115
+ "inputInvalid": "i1cc5G_inputInvalid",
2116
+ "versionRow": "i1cc5G_versionRow",
2117
+ "versionLabel": "i1cc5G_versionLabel",
2118
+ "reset": "i1cc5G_reset",
2119
+ "hint": "i1cc5G_hint",
2120
+ "chevron": "i1cc5G_chevron",
2123
2121
  "description": "i1cc5G_description",
2124
- "pending": "i1cc5G_pending",
2122
+ "readOnly": "i1cc5G_readOnly",
2123
+ "footer": "i1cc5G_footer",
2124
+ "body": "i1cc5G_body",
2125
2125
  "select": "i1cc5G_select",
2126
- "name": "i1cc5G_name",
2127
- "versionLabel": "i1cc5G_versionLabel",
2128
- "headText": "i1cc5G_headText",
2129
- "versionValue": "i1cc5G_versionValue",
2130
- "inputInvalid": "i1cc5G_inputInvalid",
2131
- "head": "i1cc5G_head"
2126
+ "save": "i1cc5G_save",
2127
+ "header": "i1cc5G_header",
2128
+ "chevronOpen": "i1cc5G_chevronOpen",
2129
+ "card": "i1cc5G_card",
2130
+ "invalid": "i1cc5G_invalid",
2131
+ "name": "i1cc5G_name"
2132
2132
  };
2133
2133
  //#endregion
2134
2134
  //#region src/client/SettingsCard.tsx
package/lib/client.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","names":["css","Button","Pill","css","css","css"],"sources":["../src/protocol.ts","../src/client/api.ts","../src/client/controller.ts","../src/client/locales.ts","../src/client/helpers.ts","../src/client/ImageGenPanel.tsx","../src/client/mount.tsx","../src/client/sidebar-entry.ts","../src/client/settings-form.ts","../src/client/SettingsCard.tsx","../src/client/settings-scope.ts","../src/client/index.ts"],"sourcesContent":["/**\n * Wire contract shared by the host and client halves of dsh-imagegen: the\n * settings namespace, the route paths, and the generate payload/result shapes.\n * Pure types + constants — safe for the client bundle to inline.\n */\n\n/** Settings namespace this plugin owns (host settings seam + bridge). */\nexport const IMAGEGEN_SETTINGS_NAMESPACE = 'dsh-imagegen'\n\n/** Published package version shared by the host updater and the client UI. */\nexport const PLUGIN_VERSION = '1.0.5'\n\n/** Same-origin route family (loopback-only, mirroring the dsh-ssh fence). */\nexport const SETTINGS_API = {\n describe: '/api/dsh-imagegen/settings/describe',\n mutate: '/api/dsh-imagegen/settings/mutate',\n} as const\n\n/** The image-generation proxy route. */\nexport const GENERATE_API = '/api/dsh-imagegen/generate'\n\n/** Host-mediated GitHub Release update routes. */\nexport const UPDATE_API = {\n check: '/api/dsh-imagegen/update/check',\n apply: '/api/dsh-imagegen/update/apply',\n} as const\n\n/**\n * Same-origin route family for the host-persisted generation history. Images\n * live as files under ~/.dsh/dsh-imagegen/images/ and are served back through\n * the `image` prefix route, so list responses carry metadata only (never\n * base64) and the browser loads thumbnails/previews lazily.\n */\nexport const HISTORY_API = {\n list: '/api/dsh-imagegen/history/list',\n append: '/api/dsh-imagegen/history/append',\n remove: '/api/dsh-imagegen/history/remove',\n clear: '/api/dsh-imagegen/history/clear',\n image: '/api/dsh-imagegen/history/image',\n} as const\n\n/** Maximum number of history entries retained host-side (oldest evicted). */\nexport const HISTORY_MAX = 50\n\n/** Generation modes. */\nexport type GenerateMode = 'text' | 'edit'\n\n/** A client → host generate request (what the panel collects). */\nexport interface GenerateRequest {\n /** text-to-image (images/generations) or image-to-image (images/edits). */\n mode: GenerateMode\n /** Upstream model name, e.g. gpt-image-2. */\n model: string\n /** The prompt (up to 2000 chars in the UI). */\n prompt: string\n /** Canvas size: 'auto' or a pixel size like '1024x1024'. */\n size: string\n /** Quality: 'auto' | 'low' | 'medium' | 'high'. */\n quality: string\n /** Number of images, 1-4. */\n n: number\n /**\n * Passthrough detail parameter: '' (omit), 'standard', or 'high'. Some\n * gpt-image-2 gateways expose it; official OpenAI endpoints reject unknown\n * parameters, so the UI defaults to '' (omit).\n */\n detail: string\n /** Reference image as a data URL (edit mode only). */\n image?: string\n /** Original reference-image name, retained in the history entry. */\n refName?: string\n}\n\n/** One generated image, normalized host-side to base64 so the browser never\n * has to fetch the upstream (no CORS, no key exposure). */\nexport interface GeneratedImage {\n /** Raw base64 payload (no data: prefix). */\n b64: string\n /** MIME type of the payload, e.g. image/png. */\n mime: string\n /** Upstream revised prompt, when provided. */\n revisedPrompt?: string\n}\n\n/** Successful generate outcome. */\nexport interface GenerateResult {\n images: GeneratedImage[]\n /** Updated host-persisted history, when returned by the generate route. */\n history?: HistoryEntry[]\n /** Persistence failure after images were successfully generated. */\n historyError?: string\n}\n\n/** GitHub Release update information shown by the client. */\nexport interface UpdateInfo {\n currentVersion: string\n latestVersion: string\n updateAvailable: boolean\n releaseUrl: string\n publishedAt?: string\n}\n\n/** One history image reference as the browser consumes it (a served URL). */\nexport interface HistoryImageRef {\n /** Same-origin URL: `${HISTORY_API.image}/<file>`. */\n url: string\n /** MIME type, e.g. image/png. */\n mime: string\n /** Upstream revised prompt, when provided. */\n revisedPrompt?: string\n}\n\n/** A saved generation as the browser consumes it (metadata + served images). */\nexport interface HistoryEntry {\n id: string\n createdAt: number\n mode: GenerateMode\n model: string\n prompt: string\n size: string\n quality: string\n detail: string\n n: number\n images: HistoryImageRef[]\n /** Reference-image filename (edit mode), kept for display only. */\n refName?: string\n}\n\n/** A history entry the client submits for persistence (images still carry base64). */\nexport interface HistoryEntryInput {\n id: string\n createdAt: number\n mode: GenerateMode\n model: string\n prompt: string\n size: string\n quality: string\n detail: string\n n: number\n images: GeneratedImage[]\n refName?: string\n}\n","/**\n * Browser-side API client for the /api/dsh-imagegen route family. The only\n * data access path the panel uses — plain fetch, same origin.\n */\n\nimport { GENERATE_API, HISTORY_API, UPDATE_API, type GenerateRequest, type GenerateResult, type HistoryEntry, type UpdateInfo } from '../protocol.ts'\n\n/** Error carrying the route's JSON error message. */\nexport class ImageGenApiError extends Error {\n /** Stable wire code from the host. */\n readonly code: string\n\n constructor(message: string, code = 'generate-failed') {\n super(message)\n this.name = 'ImageGenApiError'\n this.code = code\n }\n}\n\n/** Parse the { ok, ... } envelope or throw an ImageGenApiError. */\nasync function readEnvelope<T>(response: Response): Promise<T> {\n let body: unknown\n try {\n body = await response.json()\n } catch {\n throw new ImageGenApiError(`HTTP ${response.status}: invalid JSON response`)\n }\n if (body === null || typeof body !== 'object') {\n throw new ImageGenApiError(`HTTP ${response.status}: malformed response`)\n }\n const record = body as { ok?: unknown; message?: unknown; code?: unknown }\n if (record.ok !== true) {\n throw new ImageGenApiError(\n typeof record.message === 'string' ? record.message : `HTTP ${response.status}`,\n typeof record.code === 'string' ? record.code : 'generate-failed',\n )\n }\n return body as T\n}\n\n/** The browser half's data entry point. */\nexport class ImageGenApi {\n /** Ask the host to check the latest stable GitHub Release. */\n async updateCheck(): Promise<UpdateInfo> {\n const response = await fetch(UPDATE_API.check, { method: 'POST' })\n const body = await readEnvelope<{ ok: true; update: UpdateInfo }>(response)\n return body.update\n }\n\n /** Ask the host to install a previously discovered Release. */\n async updateApply(version: string): Promise<{ updatedVersion: string; restartRequired: boolean }> {\n const response = await fetch(UPDATE_API.apply, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ version }),\n })\n const body = await readEnvelope<{ ok: true; updatedVersion: string; restartRequired: boolean }>(response)\n return { updatedVersion: body.updatedVersion, restartRequired: body.restartRequired }\n }\n\n /** Forward one generate request to the host proxy. */\n async generate(request: GenerateRequest): Promise<GenerateResult> {\n const response = await fetch(GENERATE_API, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(request),\n })\n const body = await readEnvelope<{ ok: true; images: GenerateResult['images']; history?: HistoryEntry[]; historyError?: string }>(response)\n return {\n images: body.images,\n ...body.history === undefined ? {} : { history: body.history },\n ...body.historyError === undefined ? {} : { historyError: body.historyError },\n }\n }\n\n /** List the host-persisted history (newest first). */\n async historyList(): Promise<HistoryEntry[]> {\n const response = await fetch(HISTORY_API.list, { method: 'POST' })\n const body = await readEnvelope<{ ok: true; entries: HistoryEntry[] }>(response)\n return body.entries\n }\n\n /** Remove one history entry by id. */\n async historyRemove(id: string): Promise<HistoryEntry[]> {\n const response = await fetch(HISTORY_API.remove, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ id }),\n })\n const body = await readEnvelope<{ ok: true; entries: HistoryEntry[] }>(response)\n return body.entries\n }\n\n /** Clear the entire history. */\n async historyClear(): Promise<HistoryEntry[]> {\n const response = await fetch(HISTORY_API.clear, { method: 'POST' })\n const body = await readEnvelope<{ ok: true; entries: HistoryEntry[] }>(response)\n return body.entries\n }\n}\n","/**\n * Image-gen panel controller: the single owner of the panel's open/closed\n * state. Framework-free so the DOM mounts and the React panel share one tiny\n * subscription surface. The state lives only for the browser session.\n */\n\n/** Immutable controller snapshot for UI subscriptions. */\nexport interface ImageGenControllerSnapshot {\n panelOpen: boolean\n}\n\n/** The panel state owner the sidebar entry toggles and the view renders from. */\nexport class ImageGenController {\n private panelOpen = false\n private listeners = new Set<() => void>()\n\n getSnapshot(): ImageGenControllerSnapshot {\n return { panelOpen: this.panelOpen }\n }\n\n subscribe(fn: () => void): () => void {\n this.listeners.add(fn)\n return () => { this.listeners.delete(fn) }\n }\n\n open(): void {\n if (this.panelOpen) return\n this.panelOpen = true\n this.notify()\n }\n\n close(): void {\n if (!this.panelOpen) return\n this.panelOpen = false\n this.notify()\n }\n\n toggle(): void {\n if (this.panelOpen) this.close()\n else this.open()\n }\n\n private notify(): void {\n for (const fn of [...this.listeners]) fn()\n }\n}\n","/**\n * dsh-imagegen surface copy: zh is the key source, en mirrors every key.\n */\n\nexport const zh = {\n 'entry.label': 'AI 生图',\n 'entry.tooltip': 'AI 生图面板(gpt-image-2)',\n 'panel.title': 'AI 生图',\n 'panel.subtitle': 'gpt-image-2 图像生成',\n // mode\n 'mode.text': '文生图',\n 'mode.edit': '图生图',\n // prompt\n 'prompt.placeholder': '描述你想要的画面,例如:一只戴着宇航员头盔的橘猫,在月球上举起望远镜,水彩风格,柔和光线…',\n 'prompt.required': '请输入提示词',\n 'prompt.count': '{count}/2000',\n // parameters\n 'params.size': '尺寸',\n 'params.quality': '清晰度',\n 'params.count': '生成数量',\n 'params.detail': '细节',\n 'size.auto': '自动',\n 'size.square': '1024×1024',\n 'size.landscape': '1536×1024',\n 'size.portrait': '1024×1536',\n 'size.small': '512×512',\n 'size.wide': '1792×1024',\n 'size.tall': '1024×1792',\n 'quality.auto': '自动',\n 'quality.low': '低',\n 'quality.medium': '中',\n 'quality.high': '高',\n 'count.one': '1 张',\n 'count.two': '2 张',\n 'count.three': '3 张',\n 'count.four': '4 张',\n 'detail.auto': '自动',\n 'detail.standard': '标准',\n 'detail.high': '高清',\n 'detail.hint': '透传参数,部分 gpt-image-2 网关支持;官方接口请保持「自动」',\n // footer\n 'model.label': '模型',\n 'generate': '开始生成',\n 'generating': '生成中…',\n // edit reference image\n 'edit.upload': '点击或拖拽上传参考图片',\n 'edit.uploadHint': 'PNG / JPG / WEBP,不超过 10MB',\n 'edit.change': '更换图片',\n 'edit.remove': '移除',\n 'edit.required': '请先上传参考图片',\n // canvas\n 'canvas.emptyTitle': '开始你的创作',\n 'canvas.emptyHint': '在左侧输入提示词并点击「开始生成」,结果将显示在这里',\n 'canvas.error': '生成失败:{error}',\n 'canvas.generating': '正在生成图片…',\n 'canvas.elapsed': '已用时 {seconds}s',\n 'canvas.images': '本次生成 {count} 张',\n 'download': '下载',\n 'revisedPrompt': '优化提示词:{prompt}',\n // history\n 'history.title': '历史记录',\n 'history.empty': '暂无历史记录,生成图片后会保存在这里',\n 'history.clear': '清空',\n 'history.restore': '恢复',\n 'history.delete': '删除',\n 'history.images': '张',\n 'history.viewing': '历史 · {time}',\n // preview\n 'preview.title': '图片预览',\n 'preview.open': '点击预览',\n 'preview.close': '关闭',\n 'preview.prev': '上一张',\n 'preview.next': '下一张',\n 'preview.index': '{index} / {total}',\n 'preview.zoomControls': '图片缩放控制',\n 'preview.zoomIn': '放大',\n 'preview.zoomOut': '缩小',\n 'preview.zoomReset': '重置缩放',\n 'preview.zoomLevel': '{percent}%',\n 'preview.copyPrompt': '复制提示词',\n 'preview.copied': '已复制',\n 'preview.addToEdit': '添加到图生图',\n // config banner\n 'config.missing': '尚未配置 API:请前往「设置 → 插件 → 可配置」为 AI 生图填写 api_url 与 api_key。',\n 'config.configured': '已连接 {url}',\n 'config.disabled': '插件已停用,请在设置中重新启用。',\n 'connection.connected': '已连接',\n 'connection.disconnected': '未连接',\n // plugin update\n 'update.available': '检测到新版本:{version}',\n 'update.install': '在线更新',\n 'update.installing': '更新中…',\n 'update.success': '已更新到 {version},请重启 DSH',\n 'update.failed': '更新失败,请重试',\n 'update.release': '查看 Release',\n // settings card\n 'settings.title': 'AI 生图(dsh-imagegen)',\n 'settings.description': '配置图像生成 API 地址与密钥',\n 'settings.currentVersion': '当前版本',\n 'settings.apiUrl': 'API 地址(api_url)',\n 'settings.apiUrlHint': 'OpenAI 兼容接口基址,如 https://api.openai.com/v1;将自动拼接 /images/generations 与 /images/edits',\n 'settings.apiKey': 'API 密钥(api_key)',\n 'settings.apiKeyHint': 'Bearer 密钥,明文存于本机设置文档;界面只显示是否已设置',\n 'settings.apiKeySet': '已保存密钥;输入新值可更换,点击「清除」可删除',\n 'settings.apiKeyClear': '清除',\n 'settings.announceToAgent': '向 Agent 播报本插件',\n 'settings.announceToAgentHint': '开启后,本插件的存在与能力会写入每个 Agent 的系统提示词',\n 'settings.enabled': '启用插件',\n 'settings.enabledHint': '关闭后生图面板不可用(设置卡片始终可用)',\n 'settings.save': '保存',\n 'settings.saving': '保存中…',\n 'settings.discard': '放弃修改',\n 'settings.unsaved': '有未保存的修改',\n 'settings.saveFailed': '保存失败,请重试',\n 'settings.readOnly': '当前设置文档为只读,无法保存。',\n 'settings.notExposed': '设置命名空间不可用:本部署未提供该插件的设置服务。',\n 'settings.expand': '展开',\n 'settings.collapse': '收起',\n 'settings.inherit': '继承',\n 'settings.on': '开',\n 'settings.off': '关',\n 'settings.overridden': '已覆盖',\n 'settings.reset': '重置',\n 'settings.invalidNumber': '请输入有效数字',\n} as const\n\nexport const en: Record<keyof typeof zh, string> = {\n 'entry.label': 'AI Image',\n 'entry.tooltip': 'AI image generation studio (gpt-image-2)',\n 'panel.title': 'AI Image',\n 'panel.subtitle': 'gpt-image-2 image generation',\n 'mode.text': 'Text to Image',\n 'mode.edit': 'Image to Image',\n 'prompt.placeholder': 'Describe the picture you want, e.g. an orange cat in an astronaut helmet raising a telescope on the moon, watercolor style, soft light…',\n 'prompt.required': 'Enter a prompt first',\n 'prompt.count': '{count}/2000',\n 'params.size': 'Size',\n 'params.quality': 'Quality',\n 'params.count': 'Count',\n 'params.detail': 'Detail',\n 'size.auto': 'Auto',\n 'size.square': '1024×1024',\n 'size.landscape': '1536×1024',\n 'size.portrait': '1024×1536',\n 'size.small': '512×512',\n 'size.wide': '1792×1024',\n 'size.tall': '1024×1792',\n 'quality.auto': 'Auto',\n 'quality.low': 'Low',\n 'quality.medium': 'Medium',\n 'quality.high': 'High',\n 'count.one': '1',\n 'count.two': '2',\n 'count.three': '3',\n 'count.four': '4',\n 'detail.auto': 'Auto',\n 'detail.standard': 'Standard',\n 'detail.high': 'High',\n 'detail.hint': 'Passthrough parameter supported by some gpt-image-2 gateways; keep \"Auto\" for official endpoints',\n 'model.label': 'Model',\n 'generate': 'Generate',\n 'generating': 'Generating…',\n 'edit.upload': 'Click or drag to upload a reference image',\n 'edit.uploadHint': 'PNG / JPG / WEBP, up to 10MB',\n 'edit.change': 'Change image',\n 'edit.remove': 'Remove',\n 'edit.required': 'Upload a reference image first',\n 'canvas.emptyTitle': 'Start creating',\n 'canvas.emptyHint': 'Enter a prompt on the left and click \"Generate\"; results appear here',\n 'canvas.error': 'Generation failed: {error}',\n 'canvas.generating': 'Generating images…',\n 'canvas.elapsed': 'Elapsed {seconds}s',\n 'canvas.images': '{count} image(s) generated',\n 'download': 'Download',\n 'revisedPrompt': 'Refined prompt: {prompt}',\n 'history.title': 'History',\n 'history.empty': 'No history yet — generations will be saved here',\n 'history.clear': 'Clear',\n 'history.restore': 'Restore',\n 'history.delete': 'Delete',\n 'history.images': 'images',\n 'history.viewing': 'History · {time}',\n 'preview.title': 'Image preview',\n 'preview.open': 'Click to preview',\n 'preview.close': 'Close',\n 'preview.prev': 'Previous',\n 'preview.next': 'Next',\n 'preview.index': '{index} / {total}',\n 'preview.zoomControls': 'Image zoom controls',\n 'preview.zoomIn': 'Zoom in',\n 'preview.zoomOut': 'Zoom out',\n 'preview.zoomReset': 'Reset zoom',\n 'preview.zoomLevel': '{percent}%',\n 'preview.copyPrompt': 'Copy prompt',\n 'preview.copied': 'Copied',\n 'preview.addToEdit': 'Add to image to image',\n 'config.missing': 'API not configured: open \"Settings → Plugins → Configurable\" and fill in api_url and api_key for AI Image.',\n 'config.configured': 'Connected to {url}',\n 'config.disabled': 'The plugin is disabled — re-enable it in Settings.',\n 'connection.connected': 'Connected',\n 'connection.disconnected': 'Disconnected',\n 'update.available': 'A new version is available: {version}',\n 'update.install': 'Update online',\n 'update.installing': 'Updating…',\n 'update.success': 'Updated to {version}; restart DSH to load it',\n 'update.failed': 'Update failed; please try again',\n 'update.release': 'View Release',\n 'settings.title': 'AI Image (dsh-imagegen)',\n 'settings.description': 'Configure the image generation API endpoint and key',\n 'settings.currentVersion': 'Current version',\n 'settings.apiUrl': 'API URL (api_url)',\n 'settings.apiUrlHint': 'OpenAI-compatible base URL, e.g. https://api.openai.com/v1; /images/generations and /images/edits are appended',\n 'settings.apiKey': 'API Key (api_key)',\n 'settings.apiKeyHint': 'Bearer key, stored in plaintext in the local settings document; the UI only shows whether it is set',\n 'settings.apiKeySet': 'A key is stored; type a new value to replace it, or click \"Clear\" to remove it',\n 'settings.apiKeyClear': 'Clear',\n 'settings.announceToAgent': 'Announce this plugin to agents',\n 'settings.announceToAgentHint': 'When on, the plugin presence and capabilities are written into every agent system prompt',\n 'settings.enabled': 'Enable plugin',\n 'settings.enabledHint': 'When off, the generation studio is unavailable (this card stays available)',\n 'settings.save': 'Save',\n 'settings.saving': 'Saving…',\n 'settings.discard': 'Discard',\n 'settings.unsaved': 'Unsaved changes',\n 'settings.saveFailed': 'Save failed, please retry',\n 'settings.readOnly': 'The settings document is read-only; saving is disabled.',\n 'settings.notExposed': 'Settings namespace unavailable: this deployment does not serve this plugin\\'s settings.',\n 'settings.expand': 'Expand',\n 'settings.collapse': 'Collapse',\n 'settings.inherit': 'Inherit',\n 'settings.on': 'On',\n 'settings.off': 'Off',\n 'settings.overridden': 'Overridden',\n 'settings.reset': 'Reset',\n 'settings.invalidNumber': 'Enter a valid number',\n}\n\n/** Locale key union. */\nexport type ImageGenKey = keyof typeof zh\n","/**\n * Shared panel helpers: the active-dictionary pick (document-language based,\n * dsh-ssh precedent) bound to the dsh-imagegen interpolator, plus a small\n * error-message extractor. All copy stays in the locale dictionaries.\n */\n\nimport { en, zh, type ImageGenKey } from './locales.ts'\n\n/** Template values accepted by the interpolator. */\nexport type TranslateValues = Record<string, string | number>\n\n/** Active dictionary, picked by the document language at call time. */\nexport function dictionary(): Record<string, string> {\n const lang = typeof document !== 'undefined' ? document.documentElement.lang : 'zh'\n return lang.toLowerCase().startsWith('en') ? { ...en } : { ...zh }\n}\n\n/** Translate a key with optional {name} template params (current language). */\nexport function tt(key: ImageGenKey, values?: TranslateValues): string {\n const text = dictionary()[key] ?? key\n if (values === undefined) return text\n let rendered = text\n for (const [name, value] of Object.entries(values)) {\n rendered = rendered.replaceAll(`{${name}}`, String(value))\n }\n return rendered\n}\n\n/** Human-readable error text from an unknown thrown value. */\nexport function errorMessage(error: unknown): string {\n if (error instanceof Error) return error.message\n return String(error)\n}\n","/**\n * The AI 生图 studio: a three-column layout — left, a card-grouped\n * configuration sidebar (mode tabs, prompt with counter, rounded parameter\n * selectors, model dropdown + generate button); center, the result canvas;\n * right, a persistent generation history column.\n *\n * Controls ride the system UI primitives (@deepseek-ai/dsh-client-ui-primitives,\n * a platform module) so the studio matches the dsh shell look by construction.\n */\n\nimport { useEffect, useRef, useState } from 'react'\nimport { createPortal } from 'react-dom'\nimport { Button, Pill } from '@deepseek-ai/dsh-client-ui-primitives'\nimport type { ImageGenApi } from './api.ts'\nimport { errorMessage, tt } from './helpers.ts'\nimport type { GeneratedImage, GenerateMode, GenerateRequest, HistoryEntry, HistoryImageRef, UpdateInfo } from '../protocol.ts'\nimport type { ImageGenConfig, ImageGenScope } from './settings-scope.ts'\nimport css from './panel.module.css'\n\n/** The model dropdown offers exactly the plugin's namesake model. */\nconst MODELS = ['gpt-image-2'] as const\n\n/** All size options for gpt-image-2. */\nconst SIZES = ['auto', '1024x1024', '1536x1024', '1024x1536', '512x512', '1792x1024', '1024x1792'] as const\n\n/** Size option keys in the locale dictionary. */\nconst SIZE_KEYS: Record<string, 'size.auto' | 'size.square' | 'size.landscape' | 'size.portrait' | 'size.small' | 'size.wide' | 'size.tall'> = {\n auto: 'size.auto',\n '1024x1024': 'size.square',\n '1536x1024': 'size.landscape',\n '1024x1536': 'size.portrait',\n '512x512': 'size.small',\n '1792x1024': 'size.wide',\n '1024x1792': 'size.tall',\n}\n\n/** Quality options. */\nconst QUALITIES = ['auto', 'low', 'medium', 'high'] as const\n\n/** Detail options ('' = omit the passthrough). */\nconst DETAILS = ['', 'standard', 'high'] as const\n\nconst PROMPT_MAX = 2000\nconst REF_IMAGE_MAX_BYTES = 10 * 1024 * 1024\nconst PREVIEW_SCALE_MIN = 0.5\nconst PREVIEW_SCALE_MAX = 3\nconst PREVIEW_SCALE_STEP = 0.25\n\nfunction clampPreviewScale(scale: number): number {\n return Math.min(PREVIEW_SCALE_MAX, Math.max(PREVIEW_SCALE_MIN, scale))\n}\n\n/** Read the current config from the settings scope snapshot. */\nfunction useConfig(scope: ImageGenScope): ImageGenConfig | undefined {\n const [value, setValue] = useState(scope.getSnapshot().value)\n useEffect(() => scope.subscribe(() => { setValue(scope.getSnapshot().value) }), [scope])\n return value\n}\n\n/** Track the redacted api-key presence bit exposed by the settings bridge. */\nfunction useKeySet(scope: ImageGenScope): boolean {\n const [keySet, setKeySet] = useState(scope.getKeySetSnapshot())\n useEffect(() => scope.subscribeKeySet(() => { setKeySet(scope.getKeySetSnapshot()) }), [scope])\n return keySet\n}\n\n/** Tick a seconds counter while `running`. */\nfunction useElapsed(running: boolean, startedAt: number | null): number {\n const [elapsed, setElapsed] = useState(0)\n useEffect(() => {\n if (!running || startedAt === null) return\n const timer = window.setInterval(() => {\n setElapsed(Math.max(1, Math.round((Date.now() - startedAt) / 1000)))\n }, 1000)\n return () => window.clearInterval(timer)\n }, [running, startedAt])\n return elapsed\n}\n\n/** Data URL for a generated image. */\nfunction srcOf(image: GeneratedImage): string {\n return `data:${image.mime};base64,${image.b64}`\n}\n\n/** Fetch persisted history image refs and decode them back to in-memory\n * GeneratedImage[] (base64), so the canvas/preview can reuse the same\n * rendering path as a fresh generation. */\nasync function historyImagesToGenerated(refs: HistoryImageRef[]): Promise<GeneratedImage[]> {\n return Promise.all(refs.map(async ref => {\n const response = await fetch(ref.url)\n if (!response.ok) throw new Error(`HTTP ${response.status}`)\n const blob = await response.blob()\n const dataUrl = await new Promise<string>((resolve, reject) => {\n const reader = new FileReader()\n reader.onload = () => resolve(typeof reader.result === 'string' ? reader.result : '')\n reader.onerror = () => reject(new Error('image read failed'))\n reader.readAsDataURL(blob)\n })\n const comma = dataUrl.indexOf(',')\n return {\n b64: comma >= 0 ? dataUrl.slice(comma + 1) : '',\n mime: ref.mime,\n ...ref.revisedPrompt === undefined ? {} : { revisedPrompt: ref.revisedPrompt },\n }\n }))\n}\n\n/** Compact, locale-independent timestamp for history entries. */\nfunction formatTime(timestamp: number): string {\n const d = new Date(timestamp)\n const pad = (n: number): string => String(n).padStart(2, '0')\n return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`\n}\n\n/** Render the studio. */\nexport function ImageGenPanel(props: {\n api: ImageGenApi\n scope: ImageGenScope\n}) {\n const { api, scope } = props\n const config = useConfig(scope)\n const enabled = config?.enabled ?? true\n const apiUrl = config?.apiUrl ?? ''\n const configured = apiUrl.trim() !== ''\n const keySet = useKeySet(scope)\n const connected = enabled && configured && keySet\n\n const [mode, setMode] = useState<GenerateMode>('text')\n const [prompt, setPrompt] = useState('')\n const [size, setSize] = useState<string>('auto')\n const [quality, setQuality] = useState<string>('auto')\n const [count, setCount] = useState(1)\n const [detail, setDetail] = useState('')\n const [model, setModel] = useState<string>(MODELS[0])\n const [refImage, setRefImage] = useState<{ dataUrl: string; name: string } | null>(null)\n const [images, setImages] = useState<GeneratedImage[]>([])\n const [error, setError] = useState<string | null>(null)\n const [generating, setGenerating] = useState(false)\n const [startedAt, setStartedAt] = useState<number | null>(null)\n const [history, setHistory] = useState<HistoryEntry[]>([])\n const [viewingHistoryId, setViewingHistoryId] = useState<string | null>(null)\n const [preview, setPreview] = useState<{ images: GeneratedImage[]; index: number } | null>(null)\n const [previewScale, setPreviewScale] = useState(1)\n const [promptCopied, setPromptCopied] = useState(false)\n const [update, setUpdate] = useState<UpdateInfo | null>(null)\n const [updating, setUpdating] = useState(false)\n const [updateMessage, setUpdateMessage] = useState<string | null>(null)\n const [updateResult, setUpdateResult] = useState<'success' | 'failed' | null>(null)\n const fileInput = useRef<HTMLInputElement>(null)\n const previewStage = useRef<HTMLDivElement>(null)\n const elapsed = useElapsed(generating, startedAt)\n\n // Load the host-persisted history once on mount (it lives in ~/.dsh on the\n // DSH host, so every browser/device sees the same list).\n useEffect(() => {\n let disposed = false\n api.historyList()\n .then(entries => { if (!disposed) setHistory(entries) })\n .catch(() => { /* history unavailable — leave the list empty */ })\n return () => { disposed = true }\n }, [api])\n\n // Release checks are host-mediated and intentionally best-effort: a GitHub\n // outage must never make the image-generation studio unavailable.\n useEffect(() => {\n let disposed = false\n api.updateCheck()\n .then(info => {\n if (!disposed && info.updateAvailable) setUpdate(info)\n })\n .catch(() => { /* update discovery is optional */ })\n return () => { disposed = true }\n }, [api])\n\n const applyUpdate = async (): Promise<void> => {\n if (update === null || updating) return\n setUpdating(true)\n setUpdateMessage(null)\n setUpdateResult(null)\n try {\n const result = await api.updateApply(update.latestVersion)\n setUpdateMessage(tt('update.success', { version: result.updatedVersion }))\n setUpdateResult('success')\n } catch {\n setUpdateMessage(tt('update.failed'))\n setUpdateResult('failed')\n } finally {\n setUpdating(false)\n }\n }\n\n /** Read an uploaded reference image into a data URL. */\n const acceptFile = (file: File | undefined): void => {\n if (file === undefined) return\n if (!file.type.startsWith('image/')) {\n setError(tt('edit.uploadHint'))\n return\n }\n if (file.size > REF_IMAGE_MAX_BYTES) {\n setError(tt('edit.uploadHint'))\n return\n }\n const reader = new FileReader()\n reader.onload = () => {\n if (typeof reader.result === 'string') setRefImage({ dataUrl: reader.result, name: file.name })\n }\n reader.onerror = () => { setError(tt('edit.uploadHint')) }\n reader.readAsDataURL(file)\n }\n\n /** Run one generation. */\n const handleGenerate = async (): Promise<void> => {\n if (generating) return\n const promptText = prompt.trim()\n if (promptText === '') {\n setError(tt('prompt.required'))\n return\n }\n if (mode === 'edit' && refImage === null) {\n setError(tt('edit.required'))\n return\n }\n const request: GenerateRequest = {\n mode,\n model,\n prompt: promptText,\n size,\n quality,\n n: count,\n detail,\n ...mode === 'edit' && refImage !== null ? { image: refImage.dataUrl } : {},\n ...mode === 'edit' && refImage !== null ? { refName: refImage.name } : {},\n }\n setGenerating(true)\n setError(null)\n setImages([])\n setStartedAt(Date.now())\n try {\n const result = await api.generate(request)\n setImages(result.images)\n setViewingHistoryId(null)\n if (result.history !== undefined) setHistory(result.history)\n if (result.historyError !== undefined) setError(result.historyError)\n } catch (caught) {\n setError(errorMessage(caught))\n } finally {\n setGenerating(false)\n setStartedAt(null)\n }\n }\n\n /** Open the full-screen image preview at a given index. */\n const openPreview = (previewImages: GeneratedImage[], index: number): void => {\n setPreview({ images: previewImages, index })\n setPreviewScale(1)\n setPromptCopied(false)\n }\n\n const closePreview = (): void => {\n setPreview(null)\n setPreviewScale(1)\n setPromptCopied(false)\n }\n\n /** Step the preview by ±1, wrapping around. */\n const stepPreview = (delta: number): void => {\n setPreviewScale(1)\n setPromptCopied(false)\n setPreview(current => {\n if (current === null) return null\n const total = current.images.length\n return { images: current.images, index: (current.index + delta + total) % total }\n })\n }\n\n // Keyboard navigation for the preview overlay.\n useEffect(() => {\n if (preview === null) return\n const onKey = (event: KeyboardEvent): void => {\n if (event.key === 'Escape') closePreview()\n else if (event.key === 'ArrowLeft') stepPreview(-1)\n else if (event.key === 'ArrowRight') stepPreview(1)\n else if (event.key === '+' || event.key === '=') setPreviewScale(current => clampPreviewScale(current + PREVIEW_SCALE_STEP))\n else if (event.key === '-') setPreviewScale(current => clampPreviewScale(current - PREVIEW_SCALE_STEP))\n else if (event.key === '0') setPreviewScale(1)\n }\n window.addEventListener('keydown', onKey)\n return () => window.removeEventListener('keydown', onKey)\n }, [preview])\n\n // A scaled image owns real scrollable space, rather than being visually\n // transformed and clipped. Recenter the viewport after every zoom or slide.\n useEffect(() => {\n if (preview === null) return\n const frame = window.requestAnimationFrame(() => {\n const stage = previewStage.current\n if (stage === null) return\n stage.scrollLeft = Math.max(0, (stage.scrollWidth - stage.clientWidth) / 2)\n stage.scrollTop = Math.max(0, (stage.scrollHeight - stage.clientHeight) / 2)\n })\n return () => window.cancelAnimationFrame(frame)\n }, [preview, previewScale])\n\n /** Load a past generation's images into the canvas. */\n const viewHistoryEntry = async (entry: HistoryEntry): Promise<void> => {\n try {\n setImages(await historyImagesToGenerated(entry.images))\n setError(null)\n setViewingHistoryId(entry.id)\n } catch (caught) {\n setError(errorMessage(caught))\n }\n }\n\n /** Restore a past generation's parameters (and its images) into the form. */\n const restoreHistoryEntry = async (entry: HistoryEntry): Promise<void> => {\n try {\n const restored = await historyImagesToGenerated(entry.images)\n setMode(entry.mode)\n setPrompt(entry.prompt)\n setSize((SIZES as readonly string[]).includes(entry.size) ? entry.size : 'auto')\n setQuality((QUALITIES as readonly string[]).includes(entry.quality) ? entry.quality : 'auto')\n setDetail((DETAILS as readonly string[]).includes(entry.detail) ? entry.detail : '')\n setCount(entry.n >= 1 && entry.n <= 4 ? entry.n : 1)\n setModel((MODELS as readonly string[]).includes(entry.model) ? entry.model : MODELS[0])\n setRefImage(null)\n setImages(restored)\n setError(null)\n setViewingHistoryId(entry.id)\n } catch (caught) {\n setError(errorMessage(caught))\n }\n }\n\n /** Remove one history entry. */\n const deleteHistoryEntry = async (id: string): Promise<void> => {\n setHistory(history.filter(entry => entry.id !== id))\n if (viewingHistoryId === id) setViewingHistoryId(null)\n try {\n setHistory(await api.historyRemove(id))\n } catch {\n // Keep the optimistic local removal.\n }\n }\n\n /** Remove all history entries. */\n const clearHistory = async (): Promise<void> => {\n setHistory([])\n setViewingHistoryId(null)\n try {\n setHistory(await api.historyClear())\n } catch {\n // Keep the cleared local state.\n }\n }\n\n const generateDisabled = generating || !enabled || !configured\n const viewingEntry = viewingHistoryId === null ? null : history.find(entry => entry.id === viewingHistoryId) ?? null\n const previewImage = preview === null ? null : preview.images[preview.index] ?? null\n const previewFrameScale = Math.max(1, previewScale)\n const previewImageScale = previewScale / previewFrameScale\n\n const copyPreviewPrompt = async (text: string): Promise<void> => {\n try {\n if (navigator.clipboard?.writeText !== undefined) {\n await navigator.clipboard.writeText(text)\n } else {\n const textarea = document.createElement('textarea')\n textarea.value = text\n textarea.style.position = 'fixed'\n textarea.style.opacity = '0'\n document.body.appendChild(textarea)\n textarea.select()\n const copied = document.execCommand('copy')\n textarea.remove()\n if (!copied) throw new Error('copy failed')\n }\n setPromptCopied(true)\n window.setTimeout(() => { setPromptCopied(false) }, 1800)\n } catch {\n setPromptCopied(false)\n }\n }\n\n const addPreviewToEdit = (): void => {\n if (previewImage === null || preview === null) return\n setMode('edit')\n setRefImage({\n dataUrl: srcOf(previewImage),\n name: `dsh-image-${preview.index + 1}.${extensionOf(previewImage.mime)}`,\n })\n if (prompt.trim() === '' && previewImage.revisedPrompt !== undefined) setPrompt(previewImage.revisedPrompt)\n setError(null)\n closePreview()\n }\n\n return (\n <div className={css.panel}>\n <header className={css.panelHeader}>\n <span className={css.panelHeading}>\n <h2 className={css.panelTitle}>{tt('panel.title')}</h2>\n <span className={css.panelSubtitle}>{tt('panel.subtitle')}</span>\n </span>\n <button\n type=\"button\"\n className={css.connectionStatus}\n data-connected={connected ? 'true' : 'false'}\n aria-label={tt(connected ? 'connection.connected' : 'connection.disconnected')}\n >\n <span className={css.connectionDot} aria-hidden=\"true\" />\n {tt(connected ? 'connection.connected' : 'connection.disconnected')}\n </button>\n </header>\n\n {update !== null ? (\n <div className={css.updateBanner} data-kind={updateResult === 'success' ? 'ok' : 'warn'}>\n <span className={css.updateText}>\n {updateMessage ?? tt('update.available', { version: update.latestVersion })}\n </span>\n <span className={css.updateActions}>\n <a className={css.updateRelease} href={update.releaseUrl} target=\"_blank\" rel=\"noreferrer\">{tt('update.release')}</a>\n <Button variant=\"primary\" size=\"sm\" disabled={updating || updateMessage !== null} onClick={() => { void applyUpdate() }}>\n {updating ? tt('update.installing') : tt('update.install')}\n </Button>\n </span>\n </div>\n ) : null}\n\n <div className={css.studio}>\n {/* ---------------------------------------------------- config sidebar */}\n <aside className={css.config}>\n <div className={css.configScroll}>\n {/* mode tabs */}\n <section className={css.card}>\n <div className={css.modeRow} role=\"tablist\" aria-label={tt('panel.title')}>\n <Pill\n active={mode === 'text'}\n onClick={() => { setMode('text') }}\n className={css.modePill}\n >\n {tt('mode.text')}\n </Pill>\n <Pill\n active={mode === 'edit'}\n onClick={() => { setMode('edit') }}\n className={css.modePill}\n >\n {tt('mode.edit')}\n </Pill>\n </div>\n </section>\n\n {/* reference image (edit mode) */}\n {mode === 'edit' ? (\n <section className={css.card}>\n {refImage === null\n ? (\n <button\n type=\"button\"\n className={css.uploadBox}\n onClick={() => { fileInput.current?.click() }}\n onDragOver={(event) => { event.preventDefault() }}\n onDrop={(event) => {\n event.preventDefault()\n acceptFile(event.dataTransfer.files?.[0])\n }}\n >\n <span className={css.uploadIcon}>\n <svg viewBox=\"0 0 16 16\" width=\"18\" height=\"18\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.3\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\"><path d=\"M8 10.5V3\"/><path d=\"M5 5.5l3-3 3 3\"/><path d=\"M2.5 9v3.5h11V9\"/></svg>\n </span>\n <span>{tt('edit.upload')}</span>\n <span className={css.uploadHint}>{tt('edit.uploadHint')}</span>\n </button>\n )\n : (\n <div className={css.reference}>\n <img className={css.referenceImage} src={refImage.dataUrl} alt={refImage.name} />\n <div className={css.referenceActions}>\n <Button variant=\"outline\" size=\"sm\" onClick={() => { fileInput.current?.click() }}>\n {tt('edit.change')}\n </Button>\n <Button variant=\"outline\" size=\"sm\" onClick={() => { setRefImage(null) }}>\n {tt('edit.remove')}\n </Button>\n </div>\n </div>\n )}\n <input\n ref={fileInput}\n type=\"file\"\n accept=\"image/png,image/jpeg,image/webp,image/gif\"\n className={css.hiddenFile}\n onChange={(event) => {\n acceptFile(event.target.files?.[0])\n event.target.value = ''\n }}\n />\n </section>\n ) : null}\n\n {/* prompt */}\n <section className={css.card}>\n <textarea\n className={css.prompt}\n value={prompt}\n maxLength={PROMPT_MAX}\n placeholder={tt('prompt.placeholder')}\n onChange={(event) => { setPrompt(event.target.value) }}\n />\n <div className={css.promptFooter}>\n <span className={css.promptCount}>{tt('prompt.count', { count: prompt.length })}</span>\n </div>\n </section>\n\n {/* parameters */}\n <section className={css.card}>\n <div className={css.paramGroup}>\n <span className={css.paramLabel}>{tt('params.size')}</span>\n <div className={css.optionGrid}>\n {SIZES.map(option => (\n <Pill\n key={option}\n active={size === option}\n onClick={() => { setSize(option) }}\n className={css.optionPill}\n >\n {tt(SIZE_KEYS[option] ?? 'size.auto')}\n </Pill>\n ))}\n </div>\n </div>\n <div className={css.paramGroup}>\n <span className={css.paramLabel}>{tt('params.quality')}</span>\n <div className={css.optionRow}>\n {QUALITIES.map(option => (\n <Pill\n key={option}\n active={quality === option}\n onClick={() => { setQuality(option) }}\n className={css.optionPill}\n >\n {tt(`quality.${option}` as const)}\n </Pill>\n ))}\n </div>\n </div>\n <div className={css.paramGroup}>\n <span className={css.paramLabel}>{tt('params.count')}</span>\n <div className={css.optionRow}>\n {[1, 2, 3, 4].map(option => (\n <Pill\n key={option}\n active={count === option}\n onClick={() => { setCount(option) }}\n className={css.optionPill}\n >\n {tt(`count.${option === 1 ? 'one' : option === 2 ? 'two' : option === 3 ? 'three' : 'four'}` as const)}\n </Pill>\n ))}\n </div>\n </div>\n <div className={css.paramGroup}>\n <span className={css.paramLabel}>{tt('params.detail')}</span>\n <div className={css.optionRow}>\n {DETAILS.map(option => (\n <Pill\n key={option === '' ? 'auto' : option}\n active={detail === option}\n onClick={() => { setDetail(option) }}\n className={css.optionPill}\n >\n {tt(option === '' ? 'detail.auto' : option === 'standard' ? 'detail.standard' : 'detail.high')}\n </Pill>\n ))}\n </div>\n <span className={css.paramHint}>{tt('detail.hint')}</span>\n </div>\n </section>\n </div>\n\n {/* footer: model + generate — a fixed sibling of the scroll area, so\n it never overlaps the cards scrolling above it. */}\n <section className={css.footer}>\n <label className={css.modelWrap}>\n <span className={css.modelLabel}>{tt('model.label')}</span>\n <select\n className={css.modelSelect}\n value={model}\n disabled={generating}\n onChange={(event) => { setModel(event.target.value) }}\n >\n {MODELS.map(option => <option key={option} value={option}>{option}</option>)}\n </select>\n </label>\n <Button\n variant=\"primary\"\n size=\"md\"\n className={css.generateButton}\n disabled={generateDisabled}\n onClick={() => { void handleGenerate() }}\n >\n {generating ? (\n <span className={css.generateInner}>\n <span className={css.spinner} />\n {tt('generating')}\n </span>\n ) : tt('generate')}\n </Button>\n </section>\n </aside>\n\n {/* --------------------------------------------------------- canvas */}\n <section className={css.canvas}>\n {generating ? (\n <div className={css.canvasState} role=\"status\">\n <span className={css.bigSpinner} />\n <span className={css.canvasStateTitle}>{tt('canvas.generating')}</span>\n <span className={css.canvasStateHint}>{tt('canvas.elapsed', { seconds: elapsed })}</span>\n </div>\n ) : null}\n\n {!generating && error !== null ? (\n <div className={css.canvasError} role=\"alert\">{tt('canvas.error', { error })}</div>\n ) : null}\n\n {!generating && !error && images.length === 0 ? (\n <div className={css.canvasState}>\n <span className={css.canvasEmptyIcon}>\n <svg viewBox=\"0 0 24 24\" width=\"34\" height=\"34\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"3\"/><circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\"/><path d=\"M21 15l-5-5L5 21\"/></svg>\n </span>\n <span className={css.canvasStateTitle}>{tt('canvas.emptyTitle')}</span>\n <span className={css.canvasStateHint}>{tt('canvas.emptyHint')}</span>\n </div>\n ) : null}\n\n {!generating && images.length > 0 ? (\n <div className={css.canvasBody}>\n <div className={css.canvasMeta}>\n <span>{tt('canvas.images', { count: images.length })}</span>\n {viewingEntry !== null ? (\n <span className={css.canvasHistoryTag}>{tt('history.viewing', { time: formatTime(viewingEntry.createdAt) })}</span>\n ) : null}\n </div>\n <div className={css.grid} data-count={images.length}>\n {images.map((image, index) => (\n <figure\n key={index}\n className={css.imageCard}\n role=\"button\"\n tabIndex={0}\n title={tt('preview.open')}\n onClick={() => { openPreview(images, index) }}\n onKeyDown={(event) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n openPreview(images, index)\n }\n }}\n >\n <img\n className={css.image}\n src={srcOf(image)}\n alt={image.revisedPrompt ?? `${tt('panel.title')} ${index + 1}`}\n />\n {image.revisedPrompt !== undefined ? (\n <figcaption className={css.imageCaption} title={image.revisedPrompt}>\n {tt('revisedPrompt', { prompt: image.revisedPrompt })}\n </figcaption>\n ) : null}\n <span className={css.zoomHint}>\n <svg viewBox=\"0 0 16 16\" width=\"13\" height=\"13\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.4\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\"><circle cx=\"7\" cy=\"7\" r=\"4\"/><path d=\"M13 13l-3.2-3.2\"/><path d=\"M7 5.4v3.2M5.4 7h3.2\"/></svg>\n {tt('preview.open')}\n </span>\n <a\n className={css.download}\n href={srcOf(image)}\n download={`dsh-image-${index + 1}.${extensionOf(image.mime)}`}\n onClick={(event) => { event.stopPropagation() }}\n >\n {tt('download')}\n </a>\n </figure>\n ))}\n </div>\n </div>\n ) : null}\n </section>\n\n {/* -------------------------------------------------------- history */}\n <aside className={css.history}>\n <header className={css.historyHeader}>\n <span className={css.historyTitle}>{tt('history.title')}</span>\n {history.length > 0 ? (\n <button type=\"button\" className={css.historyClear} onClick={() => { void clearHistory() }}>\n {tt('history.clear')}\n </button>\n ) : null}\n </header>\n\n {history.length === 0 ? (\n <div className={css.historyEmpty}>{tt('history.empty')}</div>\n ) : (\n <div className={css.historyList}>\n {history.map(entry => (\n <div\n key={entry.id}\n className={css.historyItem}\n data-active={entry.id === viewingHistoryId ? '' : undefined}\n >\n <button\n type=\"button\"\n className={css.historyMain}\n onClick={() => { void viewHistoryEntry(entry) }}\n >\n {entry.images.length > 0 ? (\n <img className={css.historyThumb} src={entry.images[0]!.url} alt=\"\" />\n ) : (\n <span className={css.historyThumbPlaceholder} />\n )}\n <span className={css.historyInfo}>\n <span className={css.historyPrompt}>{entry.prompt}</span>\n <span className={css.historyMeta}>\n {tt(`mode.${entry.mode === 'edit' ? 'edit' : 'text'}` as const)}\n {' · '}{formatTime(entry.createdAt)}\n {' · '}{entry.images.length} {tt('history.images')}\n </span>\n </span>\n </button>\n <span className={css.historyActions}>\n <button type=\"button\" className={css.historyAction} onClick={() => { void restoreHistoryEntry(entry) }}>\n {tt('history.restore')}\n </button>\n <button type=\"button\" className={css.historyAction} data-danger onClick={() => { void deleteHistoryEntry(entry.id) }}>\n {tt('history.delete')}\n </button>\n </span>\n </div>\n ))}\n </div>\n )}\n </aside>\n </div>\n\n {/* -------------------------------------------------- preview overlay */}\n {preview !== null && previewImage !== null\n ? createPortal(\n <div\n className={css.lightbox}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={tt('preview.title')}\n onClick={closePreview}\n >\n <button type=\"button\" className={css.lightboxClose} aria-label={tt('preview.close')} title={tt('preview.close')} onClick={closePreview}>\n <svg viewBox=\"0 0 16 16\" width=\"18\" height=\"18\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.6\" strokeLinecap=\"round\" aria-hidden=\"true\"><path d=\"M4 4l8 8M12 4l-8 8\"/></svg>\n </button>\n {preview.images.length > 1 ? (\n <>\n <button type=\"button\" className={css.lightboxNav} data-dir=\"prev\" aria-label={tt('preview.prev')} onClick={(event) => { event.stopPropagation(); stepPreview(-1) }}>\n <svg viewBox=\"0 0 16 16\" width=\"20\" height=\"20\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.8\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\"><path d=\"M10 3l-5 5 5 5\"/></svg>\n </button>\n <button type=\"button\" className={css.lightboxNav} data-dir=\"next\" aria-label={tt('preview.next')} onClick={(event) => { event.stopPropagation(); stepPreview(1) }}>\n <svg viewBox=\"0 0 16 16\" width=\"20\" height=\"20\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.8\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\"><path d=\"M6 3l5 5-5 5\"/></svg>\n </button>\n </>\n ) : null}\n <figure className={css.lightboxFigure} onClick={(event) => { event.stopPropagation() }}>\n <div\n ref={previewStage}\n className={css.lightboxStage}\n onWheel={(event) => {\n event.preventDefault()\n setPreviewScale(current => clampPreviewScale(current + (event.deltaY < 0 ? PREVIEW_SCALE_STEP : -PREVIEW_SCALE_STEP)))\n }}\n >\n <div\n className={css.lightboxScaleFrame}\n style={{ width: `${previewFrameScale * 100}%`, height: `${previewFrameScale * 100}%` }}\n >\n <img\n className={css.lightboxImage}\n style={{ width: `${previewImageScale * 100}%`, height: `${previewImageScale * 100}%` }}\n src={srcOf(previewImage)}\n alt={previewImage.revisedPrompt ?? tt('preview.title')}\n />\n </div>\n </div>\n <div className={css.lightboxTools} role=\"group\" aria-label={tt('preview.zoomControls')}>\n <button type=\"button\" className={css.lightboxTool} aria-label={tt('preview.zoomOut')} title={tt('preview.zoomOut')} onClick={() => { setPreviewScale(current => clampPreviewScale(current - PREVIEW_SCALE_STEP)) }}>\n <svg viewBox=\"0 0 16 16\" width=\"17\" height=\"17\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.7\" strokeLinecap=\"round\" aria-hidden=\"true\"><circle cx=\"7\" cy=\"7\" r=\"4.2\"/><path d=\"M4.8 7h4.4M13 13l-2.8-2.8\"/></svg>\n </button>\n <button type=\"button\" className={css.lightboxZoomLevel} aria-label={tt('preview.zoomReset')} title={tt('preview.zoomReset')} onClick={() => { setPreviewScale(1) }}>\n {tt('preview.zoomLevel', { percent: Math.round(previewScale * 100) })}\n </button>\n <button type=\"button\" className={css.lightboxTool} aria-label={tt('preview.zoomIn')} title={tt('preview.zoomIn')} onClick={() => { setPreviewScale(current => clampPreviewScale(current + PREVIEW_SCALE_STEP)) }}>\n <svg viewBox=\"0 0 16 16\" width=\"17\" height=\"17\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.7\" strokeLinecap=\"round\" aria-hidden=\"true\"><circle cx=\"7\" cy=\"7\" r=\"4.2\"/><path d=\"M7 4.8v4.4M4.8 7h4.4M13 13l-2.8-2.8\"/></svg>\n </button>\n </div>\n {previewImage.revisedPrompt !== undefined ? (\n <div className={css.lightboxCaptionRow}>\n <figcaption className={css.lightboxCaption} title={previewImage.revisedPrompt}>\n {tt('revisedPrompt', { prompt: previewImage.revisedPrompt })}\n </figcaption>\n <button type=\"button\" className={css.lightboxCopy} aria-label={tt(promptCopied ? 'preview.copied' : 'preview.copyPrompt')} title={tt(promptCopied ? 'preview.copied' : 'preview.copyPrompt')} onClick={() => { void copyPreviewPrompt(previewImage.revisedPrompt!) }}>\n {promptCopied ? (\n <svg viewBox=\"0 0 16 16\" width=\"16\" height=\"16\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.8\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\"><path d=\"M3 8l3 3 7-7\"/></svg>\n ) : (\n <svg viewBox=\"0 0 16 16\" width=\"16\" height=\"16\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\"><rect x=\"5\" y=\"5\" width=\"7\" height=\"8\" rx=\"1\"/><path d=\"M3 10V3.8c0-.44.36-.8.8-.8H9\"/></svg>\n )}\n <span>{tt(promptCopied ? 'preview.copied' : 'preview.copyPrompt')}</span>\n </button>\n </div>\n ) : null}\n <div className={css.lightboxMeta}>\n <span className={css.lightboxIndex}>{tt('preview.index', { index: preview.index + 1, total: preview.images.length })}</span>\n <span className={css.lightboxActions}>\n <button type=\"button\" className={css.lightboxEdit} onClick={addPreviewToEdit}>\n {tt('preview.addToEdit')}\n </button>\n <a\n className={css.lightboxDownload}\n href={srcOf(previewImage)}\n download={`dsh-image-${preview.index + 1}.${extensionOf(previewImage.mime)}`}\n >\n {tt('download')}\n </a>\n </span>\n </div>\n </figure>\n </div>,\n document.body,\n )\n : null}\n </div>\n )\n}\n\n/** File extension for a MIME type (download filenames). */\nfunction extensionOf(mime: string): string {\n switch (mime.split(';')[0]!.trim()) {\n case 'image/jpeg': return 'jpg'\n case 'image/webp': return 'webp'\n case 'image/gif': return 'gif'\n default: return 'png'\n }\n}\n","/**\n * Panel view mounting.\n *\n * The `conversation` slot is single-occupant (ui-conversation) and external\n * plugins cannot declare slots, so the panel takes over the center column at\n * the DOM level: a container is appended inside the `[data-pane=\"conversation\"]`\n * grid item (an extra trailing child React never manages), and a stylesheet\n * rule hides the conversation content while the panel is active. Toggling is\n * a data attribute on <html> — no React involvement, so the conversation\n * subtree underneath stays mounted and stateful.\n */\n\nimport { createRoot, type Root } from 'react-dom/client'\nimport type { ImageGenApi } from './api.ts'\nimport type { ImageGenController } from './controller.ts'\nimport { ImageGenPanel } from './ImageGenPanel.tsx'\nimport type { ImageGenScope } from './settings-scope.ts'\nimport css from './panel.module.css'\n\n/** The injected panel container (kept in the DOM, hidden when inactive). */\nexport const PANEL_VIEW_SELECTOR = '[data-dsh-imagegen-view]'\n\nconst CONVERSATION_COLUMN_SELECTOR = '[data-pane=\"conversation\"]'\nconst ACTIVE_ATTR = 'data-dsh-imagegen-active'\n/** Sibling panels' activation attributes, removed when this panel opens. */\nconst OTHER_ACTIVE_ATTRS = ['data-dsh-taskboard-active', 'data-dsh-ssh-active']\n/** Cross-plugin activation event; detail is the activating panel name. */\nconst ACTIVATE_EVENT = 'dsh-panel-activate'\nconst PANEL_NAME = 'imagegen'\n\n/** Find the center column, or undefined while the frame is not mounted. */\nfunction conversationColumn(): HTMLElement | undefined {\n return document.querySelector<HTMLElement>(CONVERSATION_COLUMN_SELECTOR) ?? undefined\n}\n\n/**\n * Mount the panel React tree into the center column and bind its visibility\n * to the controller's panelOpen state.\n * @param controller - the panel controller driving the view.\n * @param api - the image-generation API client the panel operates through.\n * @param scope - the settings scope (config status banner).\n * @returns disposer unmounting the tree and restoring the column.\n */\nexport function mountPanel(\n controller: ImageGenController,\n api: ImageGenApi,\n scope: ImageGenScope,\n): () => void {\n let root: Root | undefined\n let container: HTMLDivElement | undefined\n\n const ensure = (): void => {\n if (container !== undefined) {\n if (container.isConnected) return\n // The conversation pane was replaced; drop the stale tree and remount.\n root?.unmount()\n root = undefined\n container.remove()\n container = undefined\n }\n const column = conversationColumn()\n if (column === undefined) return\n container = document.createElement('div')\n container.dataset.dshImagegenView = ''\n container.className = css.view\n column.appendChild(container)\n root = createRoot(container)\n root.render(<ImageGenPanel api={api} scope={scope} />)\n }\n\n // The frame mounts after boot settlement; watch for the column's arrival.\n const waitObserver = new MutationObserver(() => { ensure() })\n waitObserver.observe(document.body, { childList: true, subtree: true })\n\n const applyActive = (): void => {\n if (controller.getSnapshot().panelOpen) {\n // Single-occupant center column: opening this panel must evict sibling\n // panels (task board / ssh), both their html attributes and their\n // controller states, otherwise the visibility rules fight.\n for (const attr of OTHER_ACTIVE_ATTRS) document.documentElement.removeAttribute(attr)\n document.documentElement.setAttribute(ACTIVE_ATTR, '')\n document.dispatchEvent(new CustomEvent(ACTIVATE_EVENT, { detail: PANEL_NAME }))\n } else {\n document.documentElement.removeAttribute(ACTIVE_ATTR)\n }\n }\n const onOtherActivate = (event: Event): void => {\n const detail = (event as CustomEvent).detail\n if ((detail === 'ssh' || detail === 'taskboard') && controller.getSnapshot().panelOpen) {\n controller.close()\n }\n }\n // Jump out on sidebar context clicks: clicking a session/workspace row\n // hands the center column back to the conversation. Capture phase.\n const SIDEBAR_ROW_SELECTOR = '[class*=\"sessionRow\"], [class*=\"projectRow\"], [class*=\"searchResultRow\"], [class*=\"searchResultWorkspace\"], [class*=\"newSession\"]'\n const onClickSidebarRow = (event: MouseEvent): void => {\n if (!controller.getSnapshot().panelOpen) return\n const target = event.target as HTMLElement | null\n if (target === null) return\n if (target.closest(SIDEBAR_ROW_SELECTOR) !== null) controller.close()\n }\n document.addEventListener('click', onClickSidebarRow, true)\n document.addEventListener(ACTIVATE_EVENT, onOtherActivate)\n const unsubscribe = controller.subscribe(applyActive)\n applyActive()\n ensure()\n\n return () => {\n document.removeEventListener('click', onClickSidebarRow, true)\n document.removeEventListener(ACTIVATE_EVENT, onOtherActivate)\n waitObserver.disconnect()\n unsubscribe()\n document.documentElement.removeAttribute(ACTIVE_ATTR)\n root?.unmount()\n root = undefined\n container?.remove()\n container = undefined\n }\n}\n","/**\n * Sidebar entry injection.\n *\n * dsh's sidebar shell exposes no slot an external plugin can register into,\n * so — following the dsh-ssh / task-board precedent of DOM-level extension —\n * the entry row is injected after the shell's New Session button (after the\n * sibling plugin family block). The injection self-heals: a MutationObserver\n * watches the sidebar root and re-inserts the row whenever a React re-render\n * displaces it (re-insertion happens in the same frame, before paint).\n *\n * The row is plain DOM (no React tree) so it can never disturb the shell's\n * reconciliation; the panel view it toggles is a separate React root mounted\n * in the center column (see mount.tsx).\n */\n\nimport type { ImageGenController } from './controller.ts'\nimport css from './panel.module.css'\n\n/** Stable data attribute identifying the injected entry row. */\nexport const ENTRY_SELECTOR = '[data-dsh-imagegen-entry]'\n\n/** Inline icon (matches the shell's 16px nav-icon look): a picture glyph. */\nconst ICON = '<svg viewBox=\"0 0 16 16\" width=\"14\" height=\"14\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.3\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><rect x=\"2\" y=\"2.5\" width=\"12\" height=\"11\" rx=\"1.5\"/><circle cx=\"5.6\" cy=\"5.8\" r=\"1\"/><path d=\"M2.5 12.5l3.6-3.4 2.4 2.2 3-3 2 2.4\"/></svg>'\n\n/** Family entry selectors of sibling plugins (relative placement anchor). */\nconst FAMILY_ENTRY_SELECTOR = '[data-dsh-taskboard-entry], [data-dsh-ssh-entry], [data-dsh-imagegen-entry]'\n\n/** Find the sidebar shell root element, or undefined while not yet mounted. */\nfunction sidebarRoot(): HTMLElement | undefined {\n const column = document.querySelector<HTMLElement>('[data-pane=\"sidebar\"], [class*=\"sidebarCol\"]')\n if (column === null) return undefined\n const logoOwner = column.querySelector<HTMLElement>('[class*=\"logoRow\"]')?.parentElement\n return logoOwner ?? (column.firstElementChild as HTMLElement | undefined)\n}\n\n/** The New Session button: nested in the logo row on current shells, a direct child on legacy shells. */\nfunction newSessionButton(root: HTMLElement): HTMLButtonElement | undefined {\n const nested = root.querySelector<HTMLButtonElement>('button[class*=\"newSession\"]')\n if (nested !== null) return nested\n for (const child of root.children) {\n if (child.tagName === 'BUTTON') return child as HTMLButtonElement\n }\n return undefined\n}\n\n/** Build the entry row (a detached button; insert once the shell is up). */\nfunction createEntry(controller: ImageGenController, label: string, tooltip: string): HTMLButtonElement {\n const entry = document.createElement('button')\n entry.type = 'button'\n entry.dataset.dshImagegenEntry = ''\n entry.className = css.entry\n entry.setAttribute('aria-label', label)\n entry.setAttribute('title', tooltip)\n entry.innerHTML = '<span class=\"' + css.entryIcon + '\">' + ICON + '</span><span class=\"' + css.entryLabel + '\">' + label + '</span>'\n entry.addEventListener('click', () => { controller.toggle() })\n return entry\n}\n\n/** Re-insert the entry after the family block (task board → ssh → imagegen). */\nfunction placeEntry(root: HTMLElement, entry: HTMLButtonElement): boolean {\n const button = newSessionButton(root)\n if (button === undefined) return false\n if (entry.parentElement !== root) {\n // Position relative to the family block, never relative to transient\n // logoRow geometry: every family plugin that self-heals during a\n // re-render then lands in the same relative order.\n const row = button.closest('[class*=\"logoRow\"]')\n const base = (row !== null && row.parentElement === root) ? row : button\n const family = Array.from(root.children).filter(\n (el): el is HTMLElement => el instanceof HTMLElement && el.matches(FAMILY_ENTRY_SELECTOR),\n )\n const anchor = family.length > 0 ? family[family.length - 1].nextElementSibling : base.nextElementSibling\n root.insertBefore(entry, anchor)\n }\n return true\n}\n\n/**\n * Mount the sidebar entry, waiting for the shell to render and self-healing\n * on later React re-renders.\n * @param controller - the panel controller the entry toggles.\n * @param label - the entry label (localized).\n * @param tooltip - the entry tooltip (localized).\n * @returns disposer removing the entry and its observers.\n */\nexport function mountSidebarEntry(controller: ImageGenController, label: string, tooltip: string): () => void {\n const entry = createEntry(controller, label, tooltip)\n let root: HTMLElement | undefined\n let placed = false\n\n const tryPlace = (): void => {\n if (root !== undefined && !root.isConnected) {\n rootObserver.disconnect()\n root = undefined\n placed = false\n }\n if (placed) {\n if (document.body.contains(entry)) return\n rootObserver.disconnect()\n root = undefined\n placed = false\n }\n root ??= sidebarRoot()\n if (root === undefined) return\n placed = placeEntry(root, entry)\n if (placed) {\n rootObserver.observe(root, { childList: true, subtree: true })\n }\n }\n\n // Body-level watcher retained as the \"whole rebuild\" fallback.\n const waitObserver = new MutationObserver(() => { tryPlace() })\n waitObserver.observe(document.body, { childList: true, subtree: true })\n\n // Self-heal: if a React re-render displaces the row, re-insert it in the\n // same frame (microtask before paint -> no visible flicker).\n const rootObserver = new MutationObserver(() => {\n if (root === undefined || !root.isConnected) {\n placed = false\n tryPlace()\n return\n }\n if (!root.contains(entry)) {\n placed = placeEntry(root, entry)\n }\n })\n\n // Reflect the panel's open state on the row (active highlight).\n const syncActive = () => {\n if (controller.getSnapshot().panelOpen) entry.dataset.active = 'true'\n else delete entry.dataset.active\n }\n const unsubscribe = controller.subscribe(syncActive)\n syncActive()\n\n tryPlace()\n\n return () => {\n waitObserver.disconnect()\n rootObserver.disconnect()\n unsubscribe()\n entry.remove()\n }\n}\n","/**\n * Staged form model behind the plugin settings card. A card stages what the\n * user types and writes it only when they save — the settings write is a\n * durable, revision-fenced document mutation, so staging keeps what is on\n * screen exactly what a save would store. Self-contained slice of the same\n * pattern the dsh-web-ui family cards use (this package must not depend on a\n * sibling UI package).\n */\n\nimport { createSnapshotStore, type SettingsScope, type SettingsScopeSnapshot, type SnapshotStore } from '@deepseek-ai/dsh-client-runtime/client'\n\n/** The write one field's staged text performs when the card is saved. */\nexport type FieldWrite =\n | { kind: 'set'; value: unknown }\n | { kind: 'clear' }\n\n/** How one field converts between its stored value and its draft text. */\nexport interface FieldSpec {\n /** Field name inside the namespace section. */\n field: string\n /** Render a stored value as draft text; the empty string when the section carries none. */\n format: (value: unknown) => string\n /**\n * The write this draft text stages, or undefined when the text is not a\n * value this field accepts — which blocks the save rather than discarding it.\n */\n parse: (text: string) => FieldWrite | undefined\n /**\n * True for secret fields (role('secret') in the namespace schema): the\n * redacted wire view never returns the stored value, so the form treats an\n * empty draft as \"no change\" and judges writes by the namespace's secrets\n * sidecar instead of the user layer.\n */\n secret?: boolean\n}\n\n/** One field as the card renders it. */\nexport interface FieldState {\n /** Draft text the control renders. */\n text: string\n /** Whether saving would leave a user-layer entry for this field. */\n overridden: boolean\n /** Whether the draft is not a value this field accepts, which blocks saving. */\n invalid: boolean\n}\n\n/** Form state every plugin settings card shares. */\nexport interface CardShell {\n /** False while the namespace is still loading; the card renders nothing. */\n available: boolean\n /** Whether the namespace is actually served (the bridge answered). */\n exposed: boolean\n /** Whether the Host document accepts writes. */\n writable: boolean\n /** Whether the form holds edits that a save would write. */\n dirty: boolean\n /** Whether any staged draft is invalid, which blocks the save. */\n invalid: boolean\n /** Whether a save is crossing the wire. */\n saving: boolean\n /** Whether the last save did not land as staged; cleared by the next edit or save. */\n failed: boolean\n}\n\n/** The write actions the card's slot entry injects. */\nexport interface CardActions {\n /** Stage draft text for one field. */\n edit: (field: string, text: string) => void\n /** Stage a clear, so saving lets the field re-inherit the composition layer. */\n resetField: (field: string) => void\n /** Write every staged edit, then re-seed from what the Host accepted. */\n save: () => void\n /** Drop every staged edit. */\n discard: () => void\n}\n\n/** One field's staged edit. */\ninterface StagedEdit {\n /** Draft text the control renders. */\n text: string\n /** True when this edit clears the field whatever text it shows. */\n clear: boolean\n}\n\n/** One staged edit resolved into the write a save performs. */\ninterface PlannedWrite {\n /** Field this entry writes. */\n field: string\n /** Perform the write and report whether the Host holds the staged value afterwards. */\n run: (() => Promise<boolean>) | undefined\n}\n\n/** A free-text field. An empty draft clears the field. */\nexport function textField(field: string): FieldSpec {\n return {\n field,\n format: value => typeof value === 'string' ? value : '',\n parse: (text) => {\n const trimmed = text.trim()\n return trimmed === '' ? { kind: 'clear' } : { kind: 'set', value: trimmed }\n },\n }\n}\n\n/** A boolean field, edited through true/false draft text. */\nexport function booleanField(field: string): FieldSpec {\n return {\n field,\n format: value => typeof value === 'boolean' ? String(value) : '',\n parse: (text) => {\n if (text === 'true') return { kind: 'set', value: true }\n if (text === 'false') return { kind: 'set', value: false }\n return undefined\n },\n }\n}\n\n/**\n * A secret field (role('secret') in the namespace schema). The stored value is\n * never rendered or returned by the redacted wire view, so:\n * - an empty draft means \"no change\" (typing nothing must never clear an\n * invisible stored key); the dedicated clear action stages an explicit clear;\n * - a write's outcome is judged by the namespace's secrets sidecar through\n * the {@link CardForm} `secretSettled` hook, never by the user layer.\n */\nexport function secretField(field: string): FieldSpec {\n return {\n field,\n secret: true,\n format: () => '',\n parse: (text) => {\n const trimmed = text.trim()\n if (trimmed === '') return undefined\n return { kind: 'set', value: trimmed }\n },\n }\n}\n\n/**\n * Stages one card's edits over one settings scope and writes them on save.\n *\n * The Host is the only authority on whether a value was accepted — its\n * validators own the constraints no schema can express — so the outcome is\n * read back from the section rather than predicted here. A save that did not\n * land keeps its drafts, so the user can correct them instead of retyping.\n */\nexport class CardForm<T> {\n private readonly specs: Map<string, FieldSpec>\n private readonly staged = new Map<string, StagedEdit>()\n private readonly listeners = new Set<() => void>()\n private saving = false\n private failed = false\n\n /**\n * @param scope - the bound settings scope for this card's namespace.\n * @param specs - the fields this card edits.\n * @param options.secretSettled - for secret fields, whether the namespace\n * currently holds a stored secret (the redacted view never round-trips the\n * value, so a write's outcome is read from the secrets sidecar instead).\n */\n constructor(\n private readonly scope: SettingsScope<T>,\n specs: FieldSpec[],\n private readonly options: { secretSettled?: (field: string) => boolean } = {},\n ) {\n this.specs = new Map(specs.map(spec => [spec.field, spec]))\n scope.subscribe(() => { this.publish() })\n }\n\n /** Publish a projection of this form, rebuilt whenever the scope or a draft changes. */\n bind<S>(project: () => S): SnapshotStore<S> {\n const store = createSnapshotStore(project())\n this.listeners.add(() => { store.set(project()) })\n return store\n }\n\n /** Read the card-level state: what the Host serves, and what a save would do. */\n shell(): CardShell {\n const snapshot = this.scope.getSnapshot()\n const plan = this.plan()\n return {\n available: snapshot.status !== 'loading',\n exposed: snapshot.status === 'ready',\n writable: snapshot.writable,\n dirty: plan.length > 0,\n invalid: plan.some(item => item.run === undefined),\n saving: this.saving,\n failed: this.failed,\n }\n }\n\n /** Read one field's state from the effective section and its staged draft. */\n field(field: string): FieldState {\n const spec = this.specOf(field)\n const staged = this.staged.get(field)\n if (staged === undefined) {\n return { text: spec.format(this.sectionValue(field)), overridden: this.stored(field), invalid: false }\n }\n const write = staged.clear ? { kind: 'clear' as const } : spec.parse(staged.text)\n return {\n text: staged.text,\n overridden: write?.kind === 'set',\n // A secret field's empty draft is \"no change\" (see secretField), never\n // an invalid state — the stored value is invisible, so the user cannot\n // be expected to type over it.\n invalid: write === undefined && !(spec.secret === true && staged.text.trim() === ''),\n }\n }\n\n /** The actions the card's slot registration injects. */\n actions(): CardActions {\n return {\n edit: (field, text) => { this.stage(field, { text, clear: false }) },\n resetField: (field) => {\n this.stage(field, { text: this.specOf(field).format(this.baseValue(field)), clear: true })\n },\n save: () => { void this.save() },\n discard: () => {\n if (this.staged.size === 0 && !this.failed) return\n this.staged.clear()\n this.failed = false\n this.publish()\n },\n }\n }\n\n /**\n * Write every staged edit, then re-seed from what the Host accepted.\n * @returns settlement after every write and the read-back.\n */\n async save(): Promise<void> {\n const plan = this.plan()\n const writes = plan.flatMap(item => item.run === undefined ? [] : [item.run])\n if (plan.length === 0 || this.saving || writes.length !== plan.length) return\n this.saving = true\n this.failed = false\n this.publish()\n let landed = true\n for (const write of writes) {\n landed = await write() && landed\n }\n if (landed) this.staged.clear()\n this.saving = false\n this.failed = !landed\n this.publish()\n }\n\n /**\n * Every staged edit a save would write. An entry whose draft is not a value\n * its field accepts carries no write: the form is still dirty, and the save\n * refuses rather than dropping the edit. A staged edit that matches the\n * effective section is not a write at all.\n */\n private plan(): PlannedWrite[] {\n const plan: PlannedWrite[] = []\n for (const [field, staged] of this.staged) {\n const spec = this.specOf(field)\n if (staged.clear) {\n const present = spec.secret === true\n ? (this.options.secretSettled?.(field) ?? false)\n : this.stored(field)\n if (present) plan.push({ field, run: () => this.clear(field) })\n continue\n }\n if (staged.text === spec.format(this.sectionValue(field))) continue\n const write = spec.parse(staged.text)\n if (write === undefined) plan.push({ field, run: undefined })\n else if (write.kind === 'clear') plan.push({ field, run: () => this.clear(field) })\n else plan.push({ field, run: () => this.store(field, write.value) })\n }\n return plan\n }\n\n private async clear(field: string): Promise<boolean> {\n await this.scope.unset(field)\n const spec = this.specOf(field)\n if (spec.secret === true) return !(this.options.secretSettled?.(field) ?? false)\n return !this.stored(field)\n }\n\n private async store(field: string, value: unknown): Promise<boolean> {\n await this.scope.set(field, value)\n const spec = this.specOf(field)\n if (spec.secret === true) return this.options.secretSettled?.(field) ?? true\n return this.userLayer()?.[field] === value\n }\n\n private stage(field: string, edit: StagedEdit): void {\n this.staged.set(field, edit)\n this.failed = false\n this.publish()\n }\n\n private specOf(field: string): FieldSpec {\n const spec = this.specs.get(field)\n if (spec === undefined) throw new Error(`settings card has no field ${field}`)\n return spec\n }\n\n private snapshotOf(): SettingsScopeSnapshot<T> {\n return this.scope.getSnapshot()\n }\n\n private sectionValue(field: string): unknown {\n return (this.snapshotOf().value as Record<string, unknown> | undefined)?.[field]\n }\n\n private baseValue(field: string): unknown {\n return (this.snapshotOf().base as Record<string, unknown> | undefined)?.[field]\n }\n\n private userLayer(): Record<string, unknown> | undefined {\n return this.snapshotOf().user as Record<string, unknown> | undefined\n }\n\n private stored(field: string): boolean {\n const user = this.userLayer()\n return user !== undefined && Object.hasOwn(user, field)\n }\n\n private publish(): void {\n for (const listener of [...this.listeners]) listener()\n }\n}\n","/**\n * The dsh-imagegen settings card: api_url, api_key (secret, display-only\n * \"set\" state), and the plugin switches. Registers into the official\n * `settings.plugin.item` slot (the Settings → Plugins → Configurable tab),\n * independent of the dsh-web-ui family group, bound to the plugin's own\n * bridge settings scope.\n */\n\nimport { useState } from 'react'\nimport type { InjectFace, PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport { createSnapshotStore, type SnapshotStore } from '@deepseek-ai/dsh-client-runtime/client'\nimport { CardForm, booleanField, secretField, textField, type CardActions, type CardShell, type FieldState as CardFieldState } from './settings-form.ts'\nimport type { ImageGenScope } from './settings-scope.ts'\nimport { PLUGIN_VERSION } from '../protocol.ts'\nimport css from './settings-card.module.css'\n\n/** The fields this card edits (the namespace's full schema). */\nexport interface ImageGenSettings {\n enabled?: boolean\n announceToAgent?: boolean\n apiUrl?: string\n apiKey?: string\n}\n\n/** What the card renders. */\nexport interface ImageGenSettingsCardState extends CardShell {\n /** Master switch. */\n enabled: CardFieldState\n /** System-prompt announcement flag. */\n announceToAgent: CardFieldState\n /** API base URL. */\n apiUrl: CardFieldState\n /** API key draft (the stored value is never rendered). */\n apiKey: CardFieldState\n}\n\n/** The registration-side face the card's slot entry injects. */\nexport interface ImageGenSettingsCardFace extends CardActions {\n hooks: {\n /** Card snapshot bound by the renderer as useImageGenSettingsCard. */\n imageGenSettingsCard: SnapshotStore<ImageGenSettingsCardState>\n /** Whether a secret (apiKey) is currently stored. */\n imageGenKeySet: SnapshotStore<boolean>\n }\n}\n\n/** Bridges the imagegen scope onto the card's staged form. */\nexport class ImageGenSettingsCardController {\n private readonly form: CardForm<ImageGenSettings>\n\n /** @param scope - the bound bridge scope for the dsh-imagegen namespace. */\n constructor(private readonly scope: ImageGenScope) {\n this.form = new CardForm(scope, [\n booleanField('enabled'),\n booleanField('announceToAgent'),\n textField('apiUrl'),\n secretField('apiKey'),\n ], {\n // The redacted wire view never returns the key; a save's outcome is\n // judged by the namespace's secrets sidecar instead.\n secretSettled: () => this.scope.getKeySetSnapshot(),\n })\n }\n\n private projection(): ImageGenSettingsCardState {\n return {\n ...this.form.shell(),\n enabled: this.form.field('enabled'),\n announceToAgent: this.form.field('announceToAgent'),\n apiUrl: this.form.field('apiUrl'),\n apiKey: this.form.field('apiKey'),\n }\n }\n\n /**\n * Build the face the card's slot registration injects.\n * @returns the card's snapshot, the key-set flag, and the form actions.\n */\n inject(): ImageGenSettingsCardFace {\n const cardStore = this.form.bind(() => this.projection())\n const keySetStore = createSnapshotStore(this.scope.getKeySetSnapshot())\n this.scope.subscribeKeySet(() => { keySetStore.set(this.scope.getKeySetSnapshot()) })\n return {\n hooks: {\n imageGenSettingsCard: cardStore,\n imageGenKeySet: keySetStore,\n },\n ...this.form.actions(),\n }\n }\n}\n\n/** Props the renderer binds for this card. */\nexport type ImageGenSettingsCardProps =\n PropsRuntime<'settings.plugin.item'>\n & PropsLocale<'dsh-imagegen'>\n & InjectFace<ImageGenSettingsCardFace>\n\n/**\n * Render the card.\n * @param props - locale copy, the card snapshot, and the form actions.\n * @returns the card, or nothing while the namespace is still loading.\n */\nexport function ImageGenSettingsCard(props: ImageGenSettingsCardProps) {\n const { t } = props\n const state = props.useImageGenSettingsCard(snapshot => snapshot)\n const keySet = props.useImageGenKeySet(snapshot => snapshot)\n const [open, setOpen] = useState(false)\n if (!state.available) return null\n const title = t('settings.title')\n const blocked = !state.dirty || state.invalid || state.saving\n const disabled = !state.writable\n const fieldProps = {\n overriddenLabel: t('settings.overridden'),\n resetLabel: t('settings.reset'),\n invalidLabel: t('settings.invalidNumber'),\n disabled,\n }\n if (!state.exposed) {\n return (\n <li className={css.card}>\n <button\n type=\"button\"\n className={css.header}\n aria-expanded={open}\n aria-label={`${t(open ? 'settings.collapse' : 'settings.expand')}: ${title}`}\n onClick={() => { setOpen(!open) }}\n >\n <span className={css.headText}>\n <span className={css.name}>{title}</span>\n <span className={css.description}>{t('settings.description')}</span>\n </span>\n <span className={open ? css.chevronOpen : css.chevron}>▾</span>\n </button>\n {open\n ? (\n <div className={css.body}>\n <p className={css.notExposed} role=\"status\">{t('settings.notExposed')}</p>\n </div>\n )\n : null}\n </li>\n )\n }\n return (\n <li className={css.card}>\n <button\n type=\"button\"\n className={css.header}\n aria-expanded={open}\n aria-label={`${t(open ? 'settings.collapse' : 'settings.expand')}: ${title}`}\n onClick={() => { setOpen(!open) }}\n >\n <span className={css.headText}>\n <span className={css.name}>{title}</span>\n <span className={css.description}>{t('settings.description')}</span>\n </span>\n {state.dirty ? <span className={css.pending}>{t('settings.unsaved')}</span> : null}\n <span className={open ? css.chevronOpen : css.chevron}>▾</span>\n </button>\n {open\n ? (\n <div className={css.body}>\n {!state.writable ? <p className={css.readOnly} role=\"status\">{t('settings.readOnly')}</p> : null}\n <div className={css.versionRow}>\n <span className={css.versionLabel}>{t('settings.currentVersion')}</span>\n <code className={css.versionValue}>v{PLUGIN_VERSION}</code>\n </div>\n <ValueField\n id=\"dsh-imagegen-settings-apikey\"\n label={t('settings.apiKey')}\n hint={keySet ? t('settings.apiKeySet') : t('settings.apiKeyHint')}\n placeholder=\"sk-…\"\n secret\n {...fieldProps}\n {...state.apiKey}\n overridden={false}\n onEdit={(text) => { props.edit('apiKey', text) }}\n onReset={() => { props.resetField('apiKey') }}\n clearLabel={t('settings.apiKeyClear')}\n onClear={() => { props.resetField('apiKey') }}\n canClear={keySet}\n />\n <ValueField\n id=\"dsh-imagegen-settings-apiurl\"\n label={t('settings.apiUrl')}\n hint={t('settings.apiUrlHint')}\n placeholder=\"https://api.openai.com/v1\"\n {...fieldProps}\n {...state.apiUrl}\n onEdit={(text) => { props.edit('apiUrl', text) }}\n onReset={() => { props.resetField('apiUrl') }}\n />\n <BooleanField\n id=\"dsh-imagegen-settings-enabled\"\n label={t('settings.enabled')}\n hint={t('settings.enabledHint')}\n inheritLabel={t('settings.inherit')}\n onLabel={t('settings.on')}\n offLabel={t('settings.off')}\n {...fieldProps}\n {...state.enabled}\n onEdit={(text) => { props.edit('enabled', text) }}\n onReset={() => { props.resetField('enabled') }}\n />\n <BooleanField\n id=\"dsh-imagegen-settings-announce\"\n label={t('settings.announceToAgent')}\n hint={t('settings.announceToAgentHint')}\n inheritLabel={t('settings.inherit')}\n onLabel={t('settings.on')}\n offLabel={t('settings.off')}\n {...fieldProps}\n {...state.announceToAgent}\n onEdit={(text) => { props.edit('announceToAgent', text) }}\n onReset={() => { props.resetField('announceToAgent') }}\n />\n <div className={css.footer}>\n {state.failed ? <p className={css.failed} role=\"status\">{t('settings.saveFailed')}</p> : null}\n <button\n type=\"button\"\n className={css.discard}\n disabled={!state.dirty || state.saving}\n onClick={props.discard}\n >\n {t('settings.discard')}\n </button>\n <button\n type=\"button\"\n className={css.save}\n disabled={blocked}\n onClick={props.save}\n >\n {t(!state.saving ? 'settings.save' : 'settings.saving')}\n </button>\n </div>\n </div>\n )\n : null}\n </li>\n )\n}\n\n/** Props every field control needs regardless of its value type. */\ninterface FieldProps {\n /** Stable id associating the label with its control. */\n id: string\n /** Visible label. */\n label: string\n /** One-line explanation rendered under the control. */\n hint: string\n /** Draft text this control renders. */\n text: string\n /** True when saving would leave a user-layer entry for this field. */\n overridden: boolean\n /** True when the draft is not a value this field accepts. */\n invalid: boolean\n /** Copy for the overridden badge. */\n overriddenLabel: string\n /** Copy for the reset control. */\n resetLabel: string\n /** Copy shown in place of the hint while the draft is invalid. */\n invalidLabel: string\n /** Disables every control (read-only document, or an unavailable namespace). */\n disabled: boolean\n /** Stage draft text. */\n onEdit: (text: string) => void\n /** Stage a clear so the field re-inherits the composition layer. */\n onReset: () => void\n}\n\n/** A staged value field; `secret` renders a password control. */\nfunction ValueField(props: FieldProps & {\n /** Render a password control. */\n secret?: boolean\n /** Placeholder shown while the draft is empty. */\n placeholder?: string\n /** Label of the dedicated clear control (secret fields). */\n clearLabel?: string\n /** Stage a clear of the stored secret. */\n onClear?: () => void\n /** Whether a stored secret exists (enables the clear control). */\n canClear?: boolean\n}) {\n return (\n <div className={css.field}>\n <div className={css.head}>\n <label className={css.label} htmlFor={props.id}>{props.label}</label>\n {props.overridden\n ? (\n <span className={css.badges}>\n <span className={css.badge}>{props.overriddenLabel}</span>\n <button\n type=\"button\"\n className={css.reset}\n disabled={props.disabled}\n onClick={props.onReset}\n >\n {props.resetLabel}\n </button>\n </span>\n )\n : null}\n {props.secret === true && props.canClear === true\n ? (\n <button\n type=\"button\"\n className={css.reset}\n disabled={props.disabled}\n onClick={props.onClear}\n >\n {props.clearLabel ?? props.resetLabel}\n </button>\n )\n : null}\n </div>\n <input\n id={props.id}\n className={props.invalid ? css.inputInvalid : css.input}\n type={props.secret === true ? 'password' : 'text'}\n autoComplete={props.secret === true ? 'off' : undefined}\n {...props.invalid ? { 'aria-invalid': true } : {}}\n value={props.text}\n placeholder={props.placeholder ?? ''}\n disabled={props.disabled}\n onChange={(event) => { props.onEdit(event.target.value) }}\n />\n <p className={props.invalid ? css.invalid : css.hint}>\n {props.invalid ? props.invalidLabel : props.hint}\n </p>\n </div>\n )\n}\n\n/** A staged boolean field: 继承 / 开 / 关. */\nfunction BooleanField(props: FieldProps & {\n /** Copy for the inherit option. */\n inheritLabel: string\n /** Copy for the on option. */\n onLabel: string\n /** Copy for the off option. */\n offLabel: string\n}) {\n return (\n <div className={css.field}>\n <div className={css.head}>\n <label className={css.label} htmlFor={props.id}>{props.label}</label>\n {props.overridden\n ? (\n <span className={css.badges}>\n <span className={css.badge}>{props.overriddenLabel}</span>\n <button\n type=\"button\"\n className={css.reset}\n disabled={props.disabled}\n onClick={props.onReset}\n >\n {props.resetLabel}\n </button>\n </span>\n )\n : null}\n </div>\n <select\n id={props.id}\n className={css.select}\n value={props.text}\n disabled={props.disabled}\n onChange={(event) => { props.onEdit(event.target.value) }}\n >\n <option value=\"\">{props.inheritLabel}</option>\n <option value=\"true\">{props.onLabel}</option>\n <option value=\"false\">{props.offLabel}</option>\n </select>\n <p className={css.hint}>{props.hint}</p>\n </div>\n )\n}\n","/**\n * Browser-side settings scope for the dsh-imagegen namespace, served by the\n * plugin's own loopback bridge routes (/api/dsh-imagegen/settings). The\n * official rc.6 settings scope answers \"unavailable\" for every third-party\n * namespace (the host-apiproxy allowlist is hard-coded), so this package\n * re-serves its namespace through the host settings seam over a same-origin,\n * loopback-only HTTP pair — the same pattern the dsh-web-ui family bridge\n * uses, self-contained per plugin.\n */\n\nimport {\n createSnapshotStore,\n type SettingsScope,\n type SettingsScopeSnapshot,\n type SnapshotStore,\n} from '@deepseek-ai/dsh-client-runtime/client'\nimport { SETTINGS_API } from '../protocol.ts'\n\n/** The fields this plugin's settings card edits. */\nexport interface ImageGenConfig {\n enabled?: boolean\n announceToAgent?: boolean\n apiUrl?: string\n apiKey?: string\n}\n\n/** Wire shape of one namespace view from the bridge. */\ninterface BridgeView {\n ns: string\n value: unknown\n base?: unknown\n user?: unknown\n revision: number\n secrets?: Array<{ path: string[]; set: boolean }>\n}\n\n/** The bridge response envelope ({ ok: true, value } | { ok: false, code, message }). */\ntype BridgeEnvelope =\n | { ok: true; value: { namespaces?: BridgeView[]; writable?: boolean } | BridgeView }\n | { ok: false; code: string; message: string }\n\n/** Settings wire face over the bridge routes (fetch-backed). */\nfunction createBridgeApi(fetchFn: typeof fetch): {\n settings: {\n describe(payload: Record<string, never>): Promise<{ result: BridgeEnvelope }>\n mutate(payload: { ns: string; ops: unknown[]; expectedRevision?: number }): Promise<{ result: BridgeEnvelope }>\n }\n} {\n const post = async (path: string, body: unknown): Promise<{ result: BridgeEnvelope }> => {\n try {\n const response = await fetchFn(path, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(body),\n })\n if (!response.ok) {\n return { result: { ok: false, code: 'internal', message: `bridge HTTP ${response.status}` } }\n }\n return { result: await response.json() as BridgeEnvelope }\n } catch {\n return { result: { ok: false, code: 'internal', message: 'settings bridge unreachable' } }\n }\n }\n return {\n settings: {\n describe: async payload => post(SETTINGS_API.describe, payload),\n mutate: async payload => post(SETTINGS_API.mutate, payload),\n },\n }\n}\n\n/**\n * A SettingsScope over the bridge face: serialized queue, revision-fenced\n * writes, recovery read after a refusal. Mirrors the official controller's\n * ordering but trusts the Host-seam value without re-running the wire-schema\n * validation — the seam already validated it.\n */\nclass BridgeScopeController<T> implements SettingsScope<T> {\n private readonly store: SnapshotStore<SettingsScopeSnapshot<T>>\n /** Whether the namespace currently holds a stored secret (e.g. apiKey). */\n private readonly keySet: SnapshotStore<boolean>\n private tail: Promise<void> = Promise.resolve()\n private disposed = false\n\n constructor(\n private readonly api: ReturnType<typeof createBridgeApi>['settings'],\n private readonly spec: { namespace: string },\n ) {\n this.store = createSnapshotStore<SettingsScopeSnapshot<T>>({\n status: 'loading',\n value: undefined,\n base: undefined,\n user: undefined,\n revision: undefined,\n writable: false,\n mode: 'host',\n })\n this.keySet = createSnapshotStore(false)\n }\n\n getSnapshot(): SettingsScopeSnapshot<T> {\n return this.store.getSnapshot()\n }\n\n /** Whether a stored secret exists (from the redacted view's secrets list). */\n getKeySetSnapshot(): boolean {\n return this.keySet.getSnapshot()\n }\n\n /** Observe the secret-set flag. */\n subscribeKeySet(listener: () => void): () => void {\n return this.keySet.subscribe(listener)\n }\n\n subscribe(listener: () => void): () => void {\n return this.store.subscribe(listener)\n }\n\n /** Queue a bridge refresh. */\n load(): Promise<void> {\n return this.enqueue(() => this.read())\n }\n\n set(field: string, value: unknown): Promise<void> {\n return this.enqueue(() => this.write({ op: 'set', path: [field], value }))\n }\n\n unset(field: string): Promise<void> {\n return this.enqueue(() => this.write({ op: 'unset', path: [field] }))\n }\n\n async dispose(): Promise<void> {\n this.disposed = true\n await this.tail\n }\n\n private enqueue(operation: () => Promise<void>): Promise<void> {\n if (this.disposed) return Promise.resolve()\n const task = this.tail.then(async () => {\n if (this.disposed) return\n await operation()\n })\n this.tail = task.catch(() => {})\n return task\n }\n\n private async read(): Promise<void> {\n let response\n try {\n response = await this.api.describe({})\n } catch {\n if (!this.disposed) this.store.update(draft => { draft.status = 'unavailable' })\n return\n }\n if (!response.result.ok || this.disposed) {\n if (!this.disposed) this.store.update(draft => { draft.status = 'unavailable' })\n return\n }\n const { namespaces, writable } = response.result.value as { namespaces?: BridgeView[]; writable?: boolean }\n const view = namespaces?.find(candidate => candidate.ns === this.spec.namespace)\n if (view === undefined) {\n this.store.update(draft => {\n draft.status = 'unavailable'\n draft.writable = writable === true\n })\n this.keySet.set(false)\n return\n }\n this.accept(view, writable)\n }\n\n private async write(op: { op: 'set' | 'unset'; path: string[]; value?: unknown }): Promise<void> {\n const revision = this.getSnapshot().revision\n let response\n try {\n response = await this.api.mutate({\n ns: this.spec.namespace,\n ops: [op],\n ...revision === undefined ? {} : { expectedRevision: revision },\n })\n } catch {\n await this.read()\n return\n }\n if (!response.result.ok || this.disposed) {\n await this.read()\n return\n }\n this.accept(response.result.value as BridgeView, undefined)\n }\n\n private accept(view: BridgeView, writable: boolean | undefined): void {\n this.store.update(draft => {\n draft.revision = view.revision\n draft.base = view.base\n draft.user = view.user\n if (writable !== undefined) draft.writable = writable\n draft.status = 'ready'\n // Trust the Host-seam value: the seam already validated it, and the\n // card binds without a narrowing decoder.\n draft.value = view.value as T\n })\n this.keySet.set(Array.isArray(view.secrets) && view.secrets.some(secret => secret.set))\n }\n}\n\n/** The bound scope plus the secret-set flag, as the card and panel consume it. */\nexport interface ImageGenScope extends SettingsScope<ImageGenConfig> {\n /** Queue a bridge refresh (the invalidation path re-reads the namespace). */\n load(): Promise<void>\n getKeySetSnapshot(): boolean\n subscribeKeySet(listener: () => void): () => void\n}\n\n/**\n * Bind the dsh-imagegen settings scope over the bridge routes and start its\n * initial read (the caller mounts nothing until the scope settles).\n * @param fetchFn - the fetch implementation (the global fetch on loopback).\n * @returns the scope; unavailable when the bridge is unreachable.\n */\nexport function bindImageGenScope(fetchFn: typeof fetch = fetch): ImageGenScope {\n const controller = new BridgeScopeController<ImageGenConfig>(createBridgeApi(fetchFn).settings, {\n namespace: 'dsh-imagegen',\n })\n void controller.load()\n return controller\n}\n","/**\n * Browser-half entry for the dsh-imagegen plugin — runs inside the dsh web\n * GUI.\n *\n * Registers the dsh-imagegen locale dictionaries, binds the plugin's own\n * settings scope (its bridge routes serve the namespace the official rc.6\n * allowlist would refuse), registers the settings card into the Web UI plugin\n * group slot, and mounts the two DOM surfaces: the sidebar entry row (toggles\n * the panel) and the generation studio in the center column. Failure policy:\n * DOM mounting problems are logged, never thrown — the web shell fails the\n * whole boot when a plugin apply throws, and an external plugin must not take\n * the GUI down.\n */\nimport type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'\nimport type { ConnectionHandle } from '@deepseek-ai/dsh-client-connection/client'\n// Type-only: pulls the locale plugin's Context merge (ctx.locale).\nimport type {} from '@deepseek-ai/dsh-client-locale/client'\n// Type-only: pulls the LocaleNamespaceMap merge table.\nimport type {} from '@deepseek-ai/dsh-client-ui-slots'\nimport { ImageGenApi } from './api.ts'\nimport { ImageGenController } from './controller.ts'\nimport { tt } from './helpers.ts'\nimport { en, zh, type ImageGenKey } from './locales.ts'\nimport { mountPanel } from './mount.tsx'\nimport { mountSidebarEntry } from './sidebar-entry.ts'\nimport { ImageGenSettingsCard, ImageGenSettingsCardController } from './SettingsCard.tsx'\nimport { bindImageGenScope, type ImageGenScope } from './settings-scope.ts'\n\n/** Locale namespace this plugin owns. */\nconst NS = 'dsh-imagegen'\n\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface LocaleNamespaceMap {\n /** dsh-imagegen surface copy. */\n 'dsh-imagegen': ImageGenKey\n }\n\n interface SlotMap {\n /**\n * The official plugin-configuration slot the Settings → Plugins →\n * Configurable tab declares and renders. This card registers there as its\n * own standalone card — independent of the dsh-web-ui family group — so\n * this plugin never reads as part of that family. Spelled here with the\n * same shape so this package can register without depending on the\n * sibling UI package.\n */\n 'settings.plugin.item': { kind: 'list'; scope: 'root'; owner: ImageGenPluginItemOwnerProps }\n }\n}\n\n/** Owner share of a plugin card (the section supplies nothing). */\nexport interface ImageGenPluginItemOwnerProps {\n /** Marker field: card owner props are intentionally empty. */\n children?: never\n}\n\n/** Required services (fiber inject waiting — the runtime must be up first). */\nexport const inject = ['slots', 'locale', 'connection']\n\n/**\n * Mount the studio, its sidebar entry, and the settings card.\n * @param ctx - client root context (services: slots, locale, connection).\n */\nexport function apply(ctx: ClientContext): void {\n ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'dsh-imagegen: dictionaries')\n\n const connection = ctx.get('connection') as ConnectionHandle | undefined\n const loopback = connection?.isLoopback === true\n // The bridge routes are loopback-fenced; remote browsers get an unavailable\n // scope (the card explains the gap) instead of failing fetches.\n const scope: ImageGenScope = bindImageGenScope(loopback\n ? (input, init) => fetch(input, init)\n : () => { throw new Error('settings bridge is loopback-only') })\n\n // Re-read the scope whenever the connection resets (same invalidation the\n // official settings binder wires).\n ctx.effect(() => {\n const disposers = [\n ctx.on('connection/reset', () => { void scope.load() }),\n ]\n return () => { for (const dispose of disposers) dispose() }\n }, 'dsh-imagegen: settings scope invalidation')\n\n // Plugin configuration card: one staged form over the `dsh-imagegen` scope,\n // registered into the official plugin-configuration slot (Settings →\n // Plugins → Configurable) as a standalone card.\n const settingsCard = new ImageGenSettingsCardController(scope)\n ctx.slots.inject('settings.plugin.item', () => ctx.slots.register({\n name: 'settings.plugin.item',\n id: 'imagegen',\n order: 30,\n locale: NS,\n inject: () => settingsCard.inject(),\n }, ImageGenSettingsCard))\n\n // The sidebar entry and studio mount once the settings scope settles; while\n // the scope is still loading, the composition default is unknown, so nothing\n // mounts yet. Only an unavailable scope falls back to the default (enabled).\n let uiDisposer: (() => void) | undefined\n const mountUi = (): void => {\n if (uiDisposer !== undefined) return\n const controller = new ImageGenController()\n const api = new ImageGenApi()\n const disposers: Array<() => void> = []\n try {\n disposers.push(mountSidebarEntry(controller, tt('entry.label'), tt('entry.tooltip')))\n disposers.push(mountPanel(controller, api, scope))\n } catch (error) {\n // DOM failures degrade the studio, never the GUI.\n console.warn('[dsh-imagegen] mount failed:', error)\n }\n uiDisposer = () => {\n for (const dispose of disposers.splice(0)) dispose()\n uiDisposer = undefined\n }\n }\n const syncEnabled = (): void => {\n const snapshot = scope.getSnapshot()\n const enabled = snapshot.status === 'ready'\n ? snapshot.value?.enabled ?? true\n : snapshot.status === 'unavailable'\n if (enabled) mountUi()\n else uiDisposer?.()\n }\n scope.subscribe(syncEnabled)\n syncEnabled()\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"client.js","names":["css","Button","Pill","css","css","css"],"sources":["../src/protocol.ts","../src/client/api.ts","../src/client/controller.ts","../src/client/locales.ts","../src/client/helpers.ts","../src/client/ImageGenPanel.tsx","../src/client/mount.tsx","../src/client/sidebar-entry.ts","../src/client/settings-form.ts","../src/client/SettingsCard.tsx","../src/client/settings-scope.ts","../src/client/index.ts"],"sourcesContent":["/**\n * Wire contract shared by the host and client halves of dsh-imagegen: the\n * settings namespace, the route paths, and the generate payload/result shapes.\n * Pure types + constants — safe for the client bundle to inline.\n */\n\n/** Settings namespace this plugin owns (host settings seam + bridge). */\nexport const IMAGEGEN_SETTINGS_NAMESPACE = 'dsh-imagegen'\n\n/** Published package version shared by the host updater and the client UI. */\nexport const PLUGIN_VERSION = '1.0.6'\n\n/** Same-origin route family (loopback-only, mirroring the dsh-ssh fence). */\nexport const SETTINGS_API = {\n describe: '/api/dsh-imagegen/settings/describe',\n mutate: '/api/dsh-imagegen/settings/mutate',\n} as const\n\n/** The image-generation proxy route. */\nexport const GENERATE_API = '/api/dsh-imagegen/generate'\n\n/** Host-mediated GitHub Release update routes. */\nexport const UPDATE_API = {\n check: '/api/dsh-imagegen/update/check',\n apply: '/api/dsh-imagegen/update/apply',\n} as const\n\n/**\n * Same-origin route family for the host-persisted generation history. Images\n * live as files under ~/.dsh/dsh-imagegen/images/ and are served back through\n * the `image` prefix route, so list responses carry metadata only (never\n * base64) and the browser loads thumbnails/previews lazily.\n */\nexport const HISTORY_API = {\n list: '/api/dsh-imagegen/history/list',\n append: '/api/dsh-imagegen/history/append',\n remove: '/api/dsh-imagegen/history/remove',\n clear: '/api/dsh-imagegen/history/clear',\n image: '/api/dsh-imagegen/history/image',\n} as const\n\n/** Maximum number of history entries retained host-side (oldest evicted). */\nexport const HISTORY_MAX = 50\n\n/** Generation modes. */\nexport type GenerateMode = 'text' | 'edit'\n\n/** A client → host generate request (what the panel collects). */\nexport interface GenerateRequest {\n /** text-to-image (images/generations) or image-to-image (images/edits). */\n mode: GenerateMode\n /** Upstream model name, e.g. gpt-image-2. */\n model: string\n /** The prompt (up to 2000 chars in the UI). */\n prompt: string\n /** Canvas size: 'auto' or a pixel size like '1024x1024'. */\n size: string\n /** Quality: 'auto' | 'low' | 'medium' | 'high'. */\n quality: string\n /** Number of images, 1-4. */\n n: number\n /**\n * Passthrough detail parameter: '' (omit), 'standard', or 'high'. Some\n * gpt-image-2 gateways expose it; official OpenAI endpoints reject unknown\n * parameters, so the UI defaults to '' (omit).\n */\n detail: string\n /** Reference image as a data URL (edit mode only). */\n image?: string\n /** Original reference-image name, retained in the history entry. */\n refName?: string\n}\n\n/** One generated image, normalized host-side to base64 so the browser never\n * has to fetch the upstream (no CORS, no key exposure). */\nexport interface GeneratedImage {\n /** Raw base64 payload (no data: prefix). */\n b64: string\n /** MIME type of the payload, e.g. image/png. */\n mime: string\n /** Upstream revised prompt, when provided. */\n revisedPrompt?: string\n}\n\n/** Successful generate outcome. */\nexport interface GenerateResult {\n images: GeneratedImage[]\n /** Updated host-persisted history, when returned by the generate route. */\n history?: HistoryEntry[]\n /** Persistence failure after images were successfully generated. */\n historyError?: string\n}\n\n/** GitHub Release update information shown by the client. */\nexport interface UpdateInfo {\n currentVersion: string\n latestVersion: string\n updateAvailable: boolean\n releaseUrl: string\n publishedAt?: string\n}\n\n/** One history image reference as the browser consumes it (a served URL). */\nexport interface HistoryImageRef {\n /** Same-origin URL: `${HISTORY_API.image}/<file>`. */\n url: string\n /** MIME type, e.g. image/png. */\n mime: string\n /** Upstream revised prompt, when provided. */\n revisedPrompt?: string\n}\n\n/** A saved generation as the browser consumes it (metadata + served images). */\nexport interface HistoryEntry {\n id: string\n createdAt: number\n mode: GenerateMode\n model: string\n prompt: string\n size: string\n quality: string\n detail: string\n n: number\n images: HistoryImageRef[]\n /** Reference-image filename (edit mode), kept for display only. */\n refName?: string\n}\n\n/** A history entry the client submits for persistence (images still carry base64). */\nexport interface HistoryEntryInput {\n id: string\n createdAt: number\n mode: GenerateMode\n model: string\n prompt: string\n size: string\n quality: string\n detail: string\n n: number\n images: GeneratedImage[]\n refName?: string\n}\n","/**\n * Browser-side API client for the /api/dsh-imagegen route family. The only\n * data access path the panel uses — plain fetch, same origin.\n */\n\nimport { GENERATE_API, HISTORY_API, UPDATE_API, type GenerateRequest, type GenerateResult, type HistoryEntry, type UpdateInfo } from '../protocol.ts'\n\n/** Error carrying the route's JSON error message. */\nexport class ImageGenApiError extends Error {\n /** Stable wire code from the host. */\n readonly code: string\n\n constructor(message: string, code = 'generate-failed') {\n super(message)\n this.name = 'ImageGenApiError'\n this.code = code\n }\n}\n\n/** Parse the { ok, ... } envelope or throw an ImageGenApiError. */\nasync function readEnvelope<T>(response: Response): Promise<T> {\n let body: unknown\n try {\n body = await response.json()\n } catch {\n throw new ImageGenApiError(`HTTP ${response.status}: invalid JSON response`)\n }\n if (body === null || typeof body !== 'object') {\n throw new ImageGenApiError(`HTTP ${response.status}: malformed response`)\n }\n const record = body as { ok?: unknown; message?: unknown; code?: unknown }\n if (record.ok !== true) {\n throw new ImageGenApiError(\n typeof record.message === 'string' ? record.message : `HTTP ${response.status}`,\n typeof record.code === 'string' ? record.code : 'generate-failed',\n )\n }\n return body as T\n}\n\n/** The browser half's data entry point. */\nexport class ImageGenApi {\n /** Ask the host to check the latest stable GitHub Release. */\n async updateCheck(): Promise<UpdateInfo> {\n const response = await fetch(UPDATE_API.check, { method: 'POST' })\n const body = await readEnvelope<{ ok: true; update: UpdateInfo }>(response)\n return body.update\n }\n\n /** Ask the host to install a previously discovered Release. */\n async updateApply(version: string): Promise<{ updatedVersion: string; restartRequired: boolean }> {\n const response = await fetch(UPDATE_API.apply, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ version }),\n })\n const body = await readEnvelope<{ ok: true; updatedVersion: string; restartRequired: boolean }>(response)\n return { updatedVersion: body.updatedVersion, restartRequired: body.restartRequired }\n }\n\n /** Forward one generate request to the host proxy. */\n async generate(request: GenerateRequest): Promise<GenerateResult> {\n const response = await fetch(GENERATE_API, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(request),\n })\n const body = await readEnvelope<{ ok: true; images: GenerateResult['images']; history?: HistoryEntry[]; historyError?: string }>(response)\n return {\n images: body.images,\n ...body.history === undefined ? {} : { history: body.history },\n ...body.historyError === undefined ? {} : { historyError: body.historyError },\n }\n }\n\n /** List the host-persisted history (newest first). */\n async historyList(): Promise<HistoryEntry[]> {\n const response = await fetch(HISTORY_API.list, { method: 'POST' })\n const body = await readEnvelope<{ ok: true; entries: HistoryEntry[] }>(response)\n return body.entries\n }\n\n /** Remove one history entry by id. */\n async historyRemove(id: string): Promise<HistoryEntry[]> {\n const response = await fetch(HISTORY_API.remove, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ id }),\n })\n const body = await readEnvelope<{ ok: true; entries: HistoryEntry[] }>(response)\n return body.entries\n }\n\n /** Clear the entire history. */\n async historyClear(): Promise<HistoryEntry[]> {\n const response = await fetch(HISTORY_API.clear, { method: 'POST' })\n const body = await readEnvelope<{ ok: true; entries: HistoryEntry[] }>(response)\n return body.entries\n }\n}\n","/**\n * Image-gen panel controller: the single owner of the panel's open/closed\n * state. Framework-free so the DOM mounts and the React panel share one tiny\n * subscription surface. The state lives only for the browser session.\n */\n\n/** Immutable controller snapshot for UI subscriptions. */\nexport interface ImageGenControllerSnapshot {\n panelOpen: boolean\n}\n\n/** The panel state owner the sidebar entry toggles and the view renders from. */\nexport class ImageGenController {\n private panelOpen = false\n private listeners = new Set<() => void>()\n\n getSnapshot(): ImageGenControllerSnapshot {\n return { panelOpen: this.panelOpen }\n }\n\n subscribe(fn: () => void): () => void {\n this.listeners.add(fn)\n return () => { this.listeners.delete(fn) }\n }\n\n open(): void {\n if (this.panelOpen) return\n this.panelOpen = true\n this.notify()\n }\n\n close(): void {\n if (!this.panelOpen) return\n this.panelOpen = false\n this.notify()\n }\n\n toggle(): void {\n if (this.panelOpen) this.close()\n else this.open()\n }\n\n private notify(): void {\n for (const fn of [...this.listeners]) fn()\n }\n}\n","/**\n * dsh-imagegen surface copy: zh is the key source, en mirrors every key.\n */\n\nexport const zh = {\n 'entry.label': 'AI 生图',\n 'entry.tooltip': 'AI 生图面板(gpt-image-2)',\n 'panel.title': 'AI 生图',\n 'panel.subtitle': 'gpt-image-2 图像生成',\n // mode\n 'mode.text': '文生图',\n 'mode.edit': '图生图',\n // prompt\n 'prompt.placeholder': '描述你想要的画面,例如:一只戴着宇航员头盔的橘猫,在月球上举起望远镜,水彩风格,柔和光线…',\n 'prompt.required': '请输入提示词',\n 'prompt.count': '{count}/2000',\n // parameters\n 'params.size': '尺寸',\n 'params.quality': '清晰度',\n 'params.count': '生成数量',\n 'params.detail': '细节',\n 'size.auto': '自动',\n 'size.square': '1024×1024',\n 'size.landscape': '1536×1024',\n 'size.portrait': '1024×1536',\n 'size.small': '512×512',\n 'size.wide': '1792×1024',\n 'size.tall': '1024×1792',\n 'quality.auto': '自动',\n 'quality.low': '低',\n 'quality.medium': '中',\n 'quality.high': '高',\n 'count.one': '1 张',\n 'count.two': '2 张',\n 'count.three': '3 张',\n 'count.four': '4 张',\n 'detail.auto': '自动',\n 'detail.standard': '标准',\n 'detail.high': '高清',\n 'detail.hint': '透传参数,部分 gpt-image-2 网关支持;官方接口请保持「自动」',\n // footer\n 'model.label': '模型',\n 'generate': '开始生成',\n 'generating': '生成中…',\n // edit reference image\n 'edit.upload': '点击或拖拽上传参考图片',\n 'edit.uploadHint': 'PNG / JPG / WEBP,不超过 10MB',\n 'edit.change': '更换图片',\n 'edit.remove': '移除',\n 'edit.required': '请先上传参考图片',\n // canvas\n 'canvas.emptyTitle': '开始你的创作',\n 'canvas.emptyHint': '在左侧输入提示词并点击「开始生成」,结果将显示在这里',\n 'canvas.error': '生成失败:{error}',\n 'canvas.generating': '正在生成图片…',\n 'canvas.elapsed': '已用时 {seconds}s',\n 'canvas.images': '本次生成 {count} 张',\n 'download': '下载',\n 'revisedPrompt': '优化提示词:{prompt}',\n // history\n 'history.title': '历史记录',\n 'history.empty': '暂无历史记录,生成图片后会保存在这里',\n 'history.clear': '清空',\n 'history.restore': '恢复',\n 'history.delete': '删除',\n 'history.images': '张',\n 'history.viewing': '历史 · {time}',\n // preview\n 'preview.title': '图片预览',\n 'preview.open': '点击预览',\n 'preview.close': '关闭',\n 'preview.prev': '上一张',\n 'preview.next': '下一张',\n 'preview.index': '{index} / {total}',\n 'preview.zoomControls': '图片缩放控制',\n 'preview.zoomIn': '放大',\n 'preview.zoomOut': '缩小',\n 'preview.zoomReset': '重置缩放',\n 'preview.zoomLevel': '{percent}%',\n 'preview.copyPrompt': '复制提示词',\n 'preview.copied': '已复制',\n 'preview.addToEdit': '添加到图生图',\n // config banner\n 'config.missing': '尚未配置 API:请前往「设置 → 插件 → 可配置」为 AI 生图填写 api_url 与 api_key。',\n 'config.configured': '已连接 {url}',\n 'config.disabled': '插件已停用,请在设置中重新启用。',\n 'connection.connected': '已连接',\n 'connection.disconnected': '未连接',\n // plugin update\n 'update.available': '检测到新版本:{version}',\n 'update.install': '在线更新',\n 'update.installing': '更新中…',\n 'update.success': '已更新到 {version},请重启 DSH',\n 'update.failed': '更新失败,请重试',\n 'update.release': '查看 Release',\n // settings card\n 'settings.title': 'AI 生图(dsh-imagegen)',\n 'settings.description': '配置图像生成 API 地址与密钥',\n 'settings.currentVersion': '当前版本',\n 'settings.apiUrl': 'API 地址(api_url)',\n 'settings.apiUrlHint': 'OpenAI 兼容接口基址,如 https://api.openai.com/v1;将自动拼接 /images/generations 与 /images/edits',\n 'settings.apiKey': 'API 密钥(api_key)',\n 'settings.apiKeyHint': 'Bearer 密钥,明文存于本机设置文档;界面只显示是否已设置',\n 'settings.apiKeySet': '已保存密钥;输入新值可更换,点击「清除」可删除',\n 'settings.apiKeyClear': '清除',\n 'settings.announceToAgent': '向 Agent 播报本插件',\n 'settings.announceToAgentHint': '开启后,本插件的存在与能力会写入每个 Agent 的系统提示词',\n 'settings.enabled': '启用插件',\n 'settings.enabledHint': '关闭后生图面板不可用(设置卡片始终可用)',\n 'settings.save': '保存',\n 'settings.saving': '保存中…',\n 'settings.discard': '放弃修改',\n 'settings.unsaved': '有未保存的修改',\n 'settings.saveFailed': '保存失败,请重试',\n 'settings.readOnly': '当前设置文档为只读,无法保存。',\n 'settings.notExposed': '设置命名空间不可用:本部署未提供该插件的设置服务。',\n 'settings.expand': '展开',\n 'settings.collapse': '收起',\n 'settings.inherit': '继承',\n 'settings.on': '开',\n 'settings.off': '关',\n 'settings.overridden': '已覆盖',\n 'settings.reset': '重置',\n 'settings.invalidNumber': '请输入有效数字',\n} as const\n\nexport const en: Record<keyof typeof zh, string> = {\n 'entry.label': 'AI Image',\n 'entry.tooltip': 'AI image generation studio (gpt-image-2)',\n 'panel.title': 'AI Image',\n 'panel.subtitle': 'gpt-image-2 image generation',\n 'mode.text': 'Text to Image',\n 'mode.edit': 'Image to Image',\n 'prompt.placeholder': 'Describe the picture you want, e.g. an orange cat in an astronaut helmet raising a telescope on the moon, watercolor style, soft light…',\n 'prompt.required': 'Enter a prompt first',\n 'prompt.count': '{count}/2000',\n 'params.size': 'Size',\n 'params.quality': 'Quality',\n 'params.count': 'Count',\n 'params.detail': 'Detail',\n 'size.auto': 'Auto',\n 'size.square': '1024×1024',\n 'size.landscape': '1536×1024',\n 'size.portrait': '1024×1536',\n 'size.small': '512×512',\n 'size.wide': '1792×1024',\n 'size.tall': '1024×1792',\n 'quality.auto': 'Auto',\n 'quality.low': 'Low',\n 'quality.medium': 'Medium',\n 'quality.high': 'High',\n 'count.one': '1',\n 'count.two': '2',\n 'count.three': '3',\n 'count.four': '4',\n 'detail.auto': 'Auto',\n 'detail.standard': 'Standard',\n 'detail.high': 'High',\n 'detail.hint': 'Passthrough parameter supported by some gpt-image-2 gateways; keep \"Auto\" for official endpoints',\n 'model.label': 'Model',\n 'generate': 'Generate',\n 'generating': 'Generating…',\n 'edit.upload': 'Click or drag to upload a reference image',\n 'edit.uploadHint': 'PNG / JPG / WEBP, up to 10MB',\n 'edit.change': 'Change image',\n 'edit.remove': 'Remove',\n 'edit.required': 'Upload a reference image first',\n 'canvas.emptyTitle': 'Start creating',\n 'canvas.emptyHint': 'Enter a prompt on the left and click \"Generate\"; results appear here',\n 'canvas.error': 'Generation failed: {error}',\n 'canvas.generating': 'Generating images…',\n 'canvas.elapsed': 'Elapsed {seconds}s',\n 'canvas.images': '{count} image(s) generated',\n 'download': 'Download',\n 'revisedPrompt': 'Refined prompt: {prompt}',\n 'history.title': 'History',\n 'history.empty': 'No history yet — generations will be saved here',\n 'history.clear': 'Clear',\n 'history.restore': 'Restore',\n 'history.delete': 'Delete',\n 'history.images': 'images',\n 'history.viewing': 'History · {time}',\n 'preview.title': 'Image preview',\n 'preview.open': 'Click to preview',\n 'preview.close': 'Close',\n 'preview.prev': 'Previous',\n 'preview.next': 'Next',\n 'preview.index': '{index} / {total}',\n 'preview.zoomControls': 'Image zoom controls',\n 'preview.zoomIn': 'Zoom in',\n 'preview.zoomOut': 'Zoom out',\n 'preview.zoomReset': 'Reset zoom',\n 'preview.zoomLevel': '{percent}%',\n 'preview.copyPrompt': 'Copy prompt',\n 'preview.copied': 'Copied',\n 'preview.addToEdit': 'Add to image to image',\n 'config.missing': 'API not configured: open \"Settings → Plugins → Configurable\" and fill in api_url and api_key for AI Image.',\n 'config.configured': 'Connected to {url}',\n 'config.disabled': 'The plugin is disabled — re-enable it in Settings.',\n 'connection.connected': 'Connected',\n 'connection.disconnected': 'Disconnected',\n 'update.available': 'A new version is available: {version}',\n 'update.install': 'Update online',\n 'update.installing': 'Updating…',\n 'update.success': 'Updated to {version}; restart DSH to load it',\n 'update.failed': 'Update failed; please try again',\n 'update.release': 'View Release',\n 'settings.title': 'AI Image (dsh-imagegen)',\n 'settings.description': 'Configure the image generation API endpoint and key',\n 'settings.currentVersion': 'Current version',\n 'settings.apiUrl': 'API URL (api_url)',\n 'settings.apiUrlHint': 'OpenAI-compatible base URL, e.g. https://api.openai.com/v1; /images/generations and /images/edits are appended',\n 'settings.apiKey': 'API Key (api_key)',\n 'settings.apiKeyHint': 'Bearer key, stored in plaintext in the local settings document; the UI only shows whether it is set',\n 'settings.apiKeySet': 'A key is stored; type a new value to replace it, or click \"Clear\" to remove it',\n 'settings.apiKeyClear': 'Clear',\n 'settings.announceToAgent': 'Announce this plugin to agents',\n 'settings.announceToAgentHint': 'When on, the plugin presence and capabilities are written into every agent system prompt',\n 'settings.enabled': 'Enable plugin',\n 'settings.enabledHint': 'When off, the generation studio is unavailable (this card stays available)',\n 'settings.save': 'Save',\n 'settings.saving': 'Saving…',\n 'settings.discard': 'Discard',\n 'settings.unsaved': 'Unsaved changes',\n 'settings.saveFailed': 'Save failed, please retry',\n 'settings.readOnly': 'The settings document is read-only; saving is disabled.',\n 'settings.notExposed': 'Settings namespace unavailable: this deployment does not serve this plugin\\'s settings.',\n 'settings.expand': 'Expand',\n 'settings.collapse': 'Collapse',\n 'settings.inherit': 'Inherit',\n 'settings.on': 'On',\n 'settings.off': 'Off',\n 'settings.overridden': 'Overridden',\n 'settings.reset': 'Reset',\n 'settings.invalidNumber': 'Enter a valid number',\n}\n\n/** Locale key union. */\nexport type ImageGenKey = keyof typeof zh\n","/**\n * Shared panel helpers: the active-dictionary pick (document-language based,\n * dsh-ssh precedent) bound to the dsh-imagegen interpolator, plus a small\n * error-message extractor. All copy stays in the locale dictionaries.\n */\n\nimport { en, zh, type ImageGenKey } from './locales.ts'\n\n/** Template values accepted by the interpolator. */\nexport type TranslateValues = Record<string, string | number>\n\n/** Active dictionary, picked by the document language at call time. */\nexport function dictionary(): Record<string, string> {\n const lang = typeof document !== 'undefined' ? document.documentElement.lang : 'zh'\n return lang.toLowerCase().startsWith('en') ? { ...en } : { ...zh }\n}\n\n/** Translate a key with optional {name} template params (current language). */\nexport function tt(key: ImageGenKey, values?: TranslateValues): string {\n const text = dictionary()[key] ?? key\n if (values === undefined) return text\n let rendered = text\n for (const [name, value] of Object.entries(values)) {\n rendered = rendered.replaceAll(`{${name}}`, String(value))\n }\n return rendered\n}\n\n/** Human-readable error text from an unknown thrown value. */\nexport function errorMessage(error: unknown): string {\n if (error instanceof Error) return error.message\n return String(error)\n}\n","/**\n * The AI 生图 studio: a three-column layout — left, a card-grouped\n * configuration sidebar (mode tabs, prompt with counter, rounded parameter\n * selectors, model dropdown + generate button); center, the result canvas;\n * right, a persistent generation history column.\n *\n * Controls ride the system UI primitives (@deepseek-ai/dsh-client-ui-primitives,\n * a platform module) so the studio matches the dsh shell look by construction.\n */\n\nimport { useEffect, useRef, useState } from 'react'\nimport { createPortal } from 'react-dom'\nimport { Button, Pill } from '@deepseek-ai/dsh-client-ui-primitives'\nimport type { ImageGenApi } from './api.ts'\nimport { errorMessage, tt } from './helpers.ts'\nimport type { GeneratedImage, GenerateMode, GenerateRequest, HistoryEntry, HistoryImageRef, UpdateInfo } from '../protocol.ts'\nimport type { ImageGenConfig, ImageGenScope } from './settings-scope.ts'\nimport css from './panel.module.css'\n\n/** The model dropdown offers exactly the plugin's namesake model. */\nconst MODELS = ['gpt-image-2'] as const\n\n/** All size options for gpt-image-2. */\nconst SIZES = ['auto', '1024x1024', '1536x1024', '1024x1536', '512x512', '1792x1024', '1024x1792'] as const\n\n/** Size option keys in the locale dictionary. */\nconst SIZE_KEYS: Record<string, 'size.auto' | 'size.square' | 'size.landscape' | 'size.portrait' | 'size.small' | 'size.wide' | 'size.tall'> = {\n auto: 'size.auto',\n '1024x1024': 'size.square',\n '1536x1024': 'size.landscape',\n '1024x1536': 'size.portrait',\n '512x512': 'size.small',\n '1792x1024': 'size.wide',\n '1024x1792': 'size.tall',\n}\n\n/** Quality options. */\nconst QUALITIES = ['auto', 'low', 'medium', 'high'] as const\n\n/** Detail options ('' = omit the passthrough). */\nconst DETAILS = ['', 'standard', 'high'] as const\n\nconst PROMPT_MAX = 2000\nconst REF_IMAGE_MAX_BYTES = 10 * 1024 * 1024\nconst PREVIEW_SCALE_MIN = 0.5\nconst PREVIEW_SCALE_MAX = 3\nconst PREVIEW_SCALE_STEP = 0.25\n\nfunction clampPreviewScale(scale: number): number {\n return Math.min(PREVIEW_SCALE_MAX, Math.max(PREVIEW_SCALE_MIN, scale))\n}\n\n/** Read the current config from the settings scope snapshot. */\nfunction useConfig(scope: ImageGenScope): ImageGenConfig | undefined {\n const [value, setValue] = useState(scope.getSnapshot().value)\n useEffect(() => scope.subscribe(() => { setValue(scope.getSnapshot().value) }), [scope])\n return value\n}\n\n/** Track the redacted api-key presence bit exposed by the settings bridge. */\nfunction useKeySet(scope: ImageGenScope): boolean {\n const [keySet, setKeySet] = useState(scope.getKeySetSnapshot())\n useEffect(() => scope.subscribeKeySet(() => { setKeySet(scope.getKeySetSnapshot()) }), [scope])\n return keySet\n}\n\n/** Tick a seconds counter while `running`. */\nfunction useElapsed(running: boolean, startedAt: number | null): number {\n const [elapsed, setElapsed] = useState(0)\n useEffect(() => {\n if (!running || startedAt === null) return\n const timer = window.setInterval(() => {\n setElapsed(Math.max(1, Math.round((Date.now() - startedAt) / 1000)))\n }, 1000)\n return () => window.clearInterval(timer)\n }, [running, startedAt])\n return elapsed\n}\n\n/** Data URL for a generated image. */\nfunction srcOf(image: GeneratedImage): string {\n return `data:${image.mime};base64,${image.b64}`\n}\n\n/** Fetch persisted history image refs and decode them back to in-memory\n * GeneratedImage[] (base64), so the canvas/preview can reuse the same\n * rendering path as a fresh generation. */\nasync function historyImagesToGenerated(refs: HistoryImageRef[]): Promise<GeneratedImage[]> {\n return Promise.all(refs.map(async ref => {\n const response = await fetch(ref.url)\n if (!response.ok) throw new Error(`HTTP ${response.status}`)\n const blob = await response.blob()\n const dataUrl = await new Promise<string>((resolve, reject) => {\n const reader = new FileReader()\n reader.onload = () => resolve(typeof reader.result === 'string' ? reader.result : '')\n reader.onerror = () => reject(new Error('image read failed'))\n reader.readAsDataURL(blob)\n })\n const comma = dataUrl.indexOf(',')\n return {\n b64: comma >= 0 ? dataUrl.slice(comma + 1) : '',\n mime: ref.mime,\n ...ref.revisedPrompt === undefined ? {} : { revisedPrompt: ref.revisedPrompt },\n }\n }))\n}\n\n/** Compact, locale-independent timestamp for history entries. */\nfunction formatTime(timestamp: number): string {\n const d = new Date(timestamp)\n const pad = (n: number): string => String(n).padStart(2, '0')\n return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`\n}\n\n/** Render the studio. */\nexport function ImageGenPanel(props: {\n api: ImageGenApi\n scope: ImageGenScope\n}) {\n const { api, scope } = props\n const config = useConfig(scope)\n const enabled = config?.enabled ?? true\n const apiUrl = config?.apiUrl ?? ''\n const configured = apiUrl.trim() !== ''\n const keySet = useKeySet(scope)\n const connected = enabled && configured && keySet\n\n const [mode, setMode] = useState<GenerateMode>('text')\n const [prompt, setPrompt] = useState('')\n const [size, setSize] = useState<string>('auto')\n const [quality, setQuality] = useState<string>('auto')\n const [count, setCount] = useState(1)\n const [detail, setDetail] = useState('')\n const [model, setModel] = useState<string>(MODELS[0])\n const [refImage, setRefImage] = useState<{ dataUrl: string; name: string } | null>(null)\n const [images, setImages] = useState<GeneratedImage[]>([])\n const [error, setError] = useState<string | null>(null)\n const [generating, setGenerating] = useState(false)\n const [startedAt, setStartedAt] = useState<number | null>(null)\n const [history, setHistory] = useState<HistoryEntry[]>([])\n const [viewingHistoryId, setViewingHistoryId] = useState<string | null>(null)\n const [preview, setPreview] = useState<{ images: GeneratedImage[]; index: number } | null>(null)\n const [previewScale, setPreviewScale] = useState(1)\n const [promptCopied, setPromptCopied] = useState(false)\n const [update, setUpdate] = useState<UpdateInfo | null>(null)\n const [updating, setUpdating] = useState(false)\n const [updateMessage, setUpdateMessage] = useState<string | null>(null)\n const [updateResult, setUpdateResult] = useState<'success' | 'failed' | null>(null)\n const fileInput = useRef<HTMLInputElement>(null)\n const previewStage = useRef<HTMLDivElement>(null)\n const elapsed = useElapsed(generating, startedAt)\n\n // Load the host-persisted history once on mount (it lives in ~/.dsh on the\n // DSH host, so every browser/device sees the same list).\n useEffect(() => {\n let disposed = false\n api.historyList()\n .then(entries => { if (!disposed) setHistory(entries) })\n .catch(() => { /* history unavailable — leave the list empty */ })\n return () => { disposed = true }\n }, [api])\n\n // Release checks are host-mediated and intentionally best-effort: a GitHub\n // outage must never make the image-generation studio unavailable.\n useEffect(() => {\n let disposed = false\n api.updateCheck()\n .then(info => {\n if (!disposed && info.updateAvailable) setUpdate(info)\n })\n .catch(() => { /* update discovery is optional */ })\n return () => { disposed = true }\n }, [api])\n\n const applyUpdate = async (): Promise<void> => {\n if (update === null || updating) return\n setUpdating(true)\n setUpdateMessage(null)\n setUpdateResult(null)\n try {\n const result = await api.updateApply(update.latestVersion)\n setUpdateMessage(tt('update.success', { version: result.updatedVersion }))\n setUpdateResult('success')\n } catch {\n setUpdateMessage(tt('update.failed'))\n setUpdateResult('failed')\n } finally {\n setUpdating(false)\n }\n }\n\n /** Read an uploaded reference image into a data URL. */\n const acceptFile = (file: File | undefined): void => {\n if (file === undefined) return\n if (!file.type.startsWith('image/')) {\n setError(tt('edit.uploadHint'))\n return\n }\n if (file.size > REF_IMAGE_MAX_BYTES) {\n setError(tt('edit.uploadHint'))\n return\n }\n const reader = new FileReader()\n reader.onload = () => {\n if (typeof reader.result === 'string') setRefImage({ dataUrl: reader.result, name: file.name })\n }\n reader.onerror = () => { setError(tt('edit.uploadHint')) }\n reader.readAsDataURL(file)\n }\n\n /** Run one generation. */\n const handleGenerate = async (): Promise<void> => {\n if (generating) return\n const promptText = prompt.trim()\n if (promptText === '') {\n setError(tt('prompt.required'))\n return\n }\n if (mode === 'edit' && refImage === null) {\n setError(tt('edit.required'))\n return\n }\n const request: GenerateRequest = {\n mode,\n model,\n prompt: promptText,\n size,\n quality,\n n: count,\n detail,\n ...mode === 'edit' && refImage !== null ? { image: refImage.dataUrl } : {},\n ...mode === 'edit' && refImage !== null ? { refName: refImage.name } : {},\n }\n setGenerating(true)\n setError(null)\n setImages([])\n setStartedAt(Date.now())\n try {\n const result = await api.generate(request)\n setImages(result.images)\n setViewingHistoryId(null)\n if (result.history !== undefined) setHistory(result.history)\n if (result.historyError !== undefined) setError(result.historyError)\n } catch (caught) {\n setError(errorMessage(caught))\n } finally {\n setGenerating(false)\n setStartedAt(null)\n }\n }\n\n /** Open the full-screen image preview at a given index. */\n const openPreview = (previewImages: GeneratedImage[], index: number): void => {\n setPreview({ images: previewImages, index })\n setPreviewScale(1)\n setPromptCopied(false)\n }\n\n const closePreview = (): void => {\n setPreview(null)\n setPreviewScale(1)\n setPromptCopied(false)\n }\n\n /** Step the preview by ±1, wrapping around. */\n const stepPreview = (delta: number): void => {\n setPreviewScale(1)\n setPromptCopied(false)\n setPreview(current => {\n if (current === null) return null\n const total = current.images.length\n return { images: current.images, index: (current.index + delta + total) % total }\n })\n }\n\n // Keyboard navigation for the preview overlay.\n useEffect(() => {\n if (preview === null) return\n const onKey = (event: KeyboardEvent): void => {\n if (event.key === 'Escape') closePreview()\n else if (event.key === 'ArrowLeft') stepPreview(-1)\n else if (event.key === 'ArrowRight') stepPreview(1)\n else if (event.key === '+' || event.key === '=') setPreviewScale(current => clampPreviewScale(current + PREVIEW_SCALE_STEP))\n else if (event.key === '-') setPreviewScale(current => clampPreviewScale(current - PREVIEW_SCALE_STEP))\n else if (event.key === '0') setPreviewScale(1)\n }\n window.addEventListener('keydown', onKey)\n return () => window.removeEventListener('keydown', onKey)\n }, [preview])\n\n // A scaled image owns real scrollable space, rather than being visually\n // transformed and clipped. Recenter the viewport after every zoom or slide.\n useEffect(() => {\n if (preview === null) return\n const frame = window.requestAnimationFrame(() => {\n const stage = previewStage.current\n if (stage === null) return\n stage.scrollLeft = Math.max(0, (stage.scrollWidth - stage.clientWidth) / 2)\n stage.scrollTop = Math.max(0, (stage.scrollHeight - stage.clientHeight) / 2)\n })\n return () => window.cancelAnimationFrame(frame)\n }, [preview, previewScale])\n\n /** Load a past generation's images into the canvas. */\n const viewHistoryEntry = async (entry: HistoryEntry): Promise<void> => {\n try {\n setImages(await historyImagesToGenerated(entry.images))\n setError(null)\n setViewingHistoryId(entry.id)\n } catch (caught) {\n setError(errorMessage(caught))\n }\n }\n\n /** Restore a past generation's parameters (and its images) into the form. */\n const restoreHistoryEntry = async (entry: HistoryEntry): Promise<void> => {\n try {\n const restored = await historyImagesToGenerated(entry.images)\n setMode(entry.mode)\n setPrompt(entry.prompt)\n setSize((SIZES as readonly string[]).includes(entry.size) ? entry.size : 'auto')\n setQuality((QUALITIES as readonly string[]).includes(entry.quality) ? entry.quality : 'auto')\n setDetail((DETAILS as readonly string[]).includes(entry.detail) ? entry.detail : '')\n setCount(entry.n >= 1 && entry.n <= 4 ? entry.n : 1)\n setModel((MODELS as readonly string[]).includes(entry.model) ? entry.model : MODELS[0])\n setRefImage(null)\n setImages(restored)\n setError(null)\n setViewingHistoryId(entry.id)\n } catch (caught) {\n setError(errorMessage(caught))\n }\n }\n\n /** Remove one history entry. */\n const deleteHistoryEntry = async (id: string): Promise<void> => {\n setHistory(history.filter(entry => entry.id !== id))\n if (viewingHistoryId === id) setViewingHistoryId(null)\n try {\n setHistory(await api.historyRemove(id))\n } catch {\n // Keep the optimistic local removal.\n }\n }\n\n /** Remove all history entries. */\n const clearHistory = async (): Promise<void> => {\n setHistory([])\n setViewingHistoryId(null)\n try {\n setHistory(await api.historyClear())\n } catch {\n // Keep the cleared local state.\n }\n }\n\n const generateDisabled = generating || !enabled || !configured\n const viewingEntry = viewingHistoryId === null ? null : history.find(entry => entry.id === viewingHistoryId) ?? null\n const previewImage = preview === null ? null : preview.images[preview.index] ?? null\n const previewFrameScale = Math.max(1, previewScale)\n const previewImageScale = previewScale / previewFrameScale\n\n const copyPreviewPrompt = async (text: string): Promise<void> => {\n try {\n if (navigator.clipboard?.writeText !== undefined) {\n await navigator.clipboard.writeText(text)\n } else {\n const textarea = document.createElement('textarea')\n textarea.value = text\n textarea.style.position = 'fixed'\n textarea.style.opacity = '0'\n document.body.appendChild(textarea)\n textarea.select()\n const copied = document.execCommand('copy')\n textarea.remove()\n if (!copied) throw new Error('copy failed')\n }\n setPromptCopied(true)\n window.setTimeout(() => { setPromptCopied(false) }, 1800)\n } catch {\n setPromptCopied(false)\n }\n }\n\n const addPreviewToEdit = (): void => {\n if (previewImage === null || preview === null) return\n setMode('edit')\n setRefImage({\n dataUrl: srcOf(previewImage),\n name: `dsh-image-${preview.index + 1}.${extensionOf(previewImage.mime)}`,\n })\n if (prompt.trim() === '' && previewImage.revisedPrompt !== undefined) setPrompt(previewImage.revisedPrompt)\n setError(null)\n closePreview()\n }\n\n return (\n <div className={css.panel}>\n <header className={css.panelHeader}>\n <span className={css.panelHeading}>\n <h2 className={css.panelTitle}>{tt('panel.title')}</h2>\n <span className={css.panelSubtitle}>{tt('panel.subtitle')}</span>\n </span>\n <button\n type=\"button\"\n className={css.connectionStatus}\n data-connected={connected ? 'true' : 'false'}\n aria-label={tt(connected ? 'connection.connected' : 'connection.disconnected')}\n >\n <span className={css.connectionDot} aria-hidden=\"true\" />\n {tt(connected ? 'connection.connected' : 'connection.disconnected')}\n </button>\n </header>\n\n {update !== null ? (\n <div className={css.updateBanner} data-kind={updateResult === 'success' ? 'ok' : 'warn'}>\n <span className={css.updateText}>\n {updateMessage ?? tt('update.available', { version: update.latestVersion })}\n </span>\n <span className={css.updateActions}>\n <a className={css.updateRelease} href={update.releaseUrl} target=\"_blank\" rel=\"noreferrer\">{tt('update.release')}</a>\n <Button variant=\"primary\" size=\"sm\" disabled={updating || updateMessage !== null} onClick={() => { void applyUpdate() }}>\n {updating ? tt('update.installing') : tt('update.install')}\n </Button>\n </span>\n </div>\n ) : null}\n\n <div className={css.studio}>\n {/* ---------------------------------------------------- config sidebar */}\n <aside className={css.config}>\n <div className={css.configScroll}>\n {/* mode tabs */}\n <section className={css.card}>\n <div className={css.modeRow} role=\"tablist\" aria-label={tt('panel.title')}>\n <Pill\n active={mode === 'text'}\n onClick={() => { setMode('text') }}\n className={css.modePill}\n >\n {tt('mode.text')}\n </Pill>\n <Pill\n active={mode === 'edit'}\n onClick={() => { setMode('edit') }}\n className={css.modePill}\n >\n {tt('mode.edit')}\n </Pill>\n </div>\n </section>\n\n {/* reference image (edit mode) */}\n {mode === 'edit' ? (\n <section className={css.card}>\n {refImage === null\n ? (\n <button\n type=\"button\"\n className={css.uploadBox}\n onClick={() => { fileInput.current?.click() }}\n onDragOver={(event) => { event.preventDefault() }}\n onDrop={(event) => {\n event.preventDefault()\n acceptFile(event.dataTransfer.files?.[0])\n }}\n >\n <span className={css.uploadIcon}>\n <svg viewBox=\"0 0 16 16\" width=\"18\" height=\"18\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.3\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\"><path d=\"M8 10.5V3\"/><path d=\"M5 5.5l3-3 3 3\"/><path d=\"M2.5 9v3.5h11V9\"/></svg>\n </span>\n <span>{tt('edit.upload')}</span>\n <span className={css.uploadHint}>{tt('edit.uploadHint')}</span>\n </button>\n )\n : (\n <div className={css.reference}>\n <img className={css.referenceImage} src={refImage.dataUrl} alt={refImage.name} />\n <div className={css.referenceActions}>\n <Button variant=\"outline\" size=\"sm\" onClick={() => { fileInput.current?.click() }}>\n {tt('edit.change')}\n </Button>\n <Button variant=\"outline\" size=\"sm\" onClick={() => { setRefImage(null) }}>\n {tt('edit.remove')}\n </Button>\n </div>\n </div>\n )}\n <input\n ref={fileInput}\n type=\"file\"\n accept=\"image/png,image/jpeg,image/webp,image/gif\"\n className={css.hiddenFile}\n onChange={(event) => {\n acceptFile(event.target.files?.[0])\n event.target.value = ''\n }}\n />\n </section>\n ) : null}\n\n {/* prompt */}\n <section className={css.card}>\n <textarea\n className={css.prompt}\n value={prompt}\n maxLength={PROMPT_MAX}\n placeholder={tt('prompt.placeholder')}\n onChange={(event) => { setPrompt(event.target.value) }}\n />\n <div className={css.promptFooter}>\n <span className={css.promptCount}>{tt('prompt.count', { count: prompt.length })}</span>\n </div>\n </section>\n\n {/* parameters */}\n <section className={css.card}>\n <div className={css.paramGroup}>\n <span className={css.paramLabel}>{tt('params.size')}</span>\n <div className={css.optionGrid}>\n {SIZES.map(option => (\n <Pill\n key={option}\n active={size === option}\n onClick={() => { setSize(option) }}\n className={css.optionPill}\n >\n {tt(SIZE_KEYS[option] ?? 'size.auto')}\n </Pill>\n ))}\n </div>\n </div>\n <div className={css.paramGroup}>\n <span className={css.paramLabel}>{tt('params.quality')}</span>\n <div className={css.optionRow}>\n {QUALITIES.map(option => (\n <Pill\n key={option}\n active={quality === option}\n onClick={() => { setQuality(option) }}\n className={css.optionPill}\n >\n {tt(`quality.${option}` as const)}\n </Pill>\n ))}\n </div>\n </div>\n <div className={css.paramGroup}>\n <span className={css.paramLabel}>{tt('params.count')}</span>\n <div className={css.optionRow}>\n {[1, 2, 3, 4].map(option => (\n <Pill\n key={option}\n active={count === option}\n onClick={() => { setCount(option) }}\n className={css.optionPill}\n >\n {tt(`count.${option === 1 ? 'one' : option === 2 ? 'two' : option === 3 ? 'three' : 'four'}` as const)}\n </Pill>\n ))}\n </div>\n </div>\n <div className={css.paramGroup}>\n <span className={css.paramLabel}>{tt('params.detail')}</span>\n <div className={css.optionRow}>\n {DETAILS.map(option => (\n <Pill\n key={option === '' ? 'auto' : option}\n active={detail === option}\n onClick={() => { setDetail(option) }}\n className={css.optionPill}\n >\n {tt(option === '' ? 'detail.auto' : option === 'standard' ? 'detail.standard' : 'detail.high')}\n </Pill>\n ))}\n </div>\n <span className={css.paramHint}>{tt('detail.hint')}</span>\n </div>\n </section>\n </div>\n\n {/* footer: model + generate — a fixed sibling of the scroll area, so\n it never overlaps the cards scrolling above it. */}\n <section className={css.footer}>\n <label className={css.modelWrap}>\n <span className={css.modelLabel}>{tt('model.label')}</span>\n <select\n className={css.modelSelect}\n value={model}\n disabled={generating}\n onChange={(event) => { setModel(event.target.value) }}\n >\n {MODELS.map(option => <option key={option} value={option}>{option}</option>)}\n </select>\n </label>\n <Button\n variant=\"primary\"\n size=\"md\"\n className={css.generateButton}\n disabled={generateDisabled}\n onClick={() => { void handleGenerate() }}\n >\n {generating ? (\n <span className={css.generateInner}>\n <span className={css.spinner} />\n {tt('generating')}\n </span>\n ) : tt('generate')}\n </Button>\n </section>\n </aside>\n\n {/* --------------------------------------------------------- canvas */}\n <section className={css.canvas}>\n {generating ? (\n <div className={css.canvasState} role=\"status\">\n <span className={css.bigSpinner} />\n <span className={css.canvasStateTitle}>{tt('canvas.generating')}</span>\n <span className={css.canvasStateHint}>{tt('canvas.elapsed', { seconds: elapsed })}</span>\n </div>\n ) : null}\n\n {!generating && error !== null ? (\n <div className={css.canvasError} role=\"alert\">{tt('canvas.error', { error })}</div>\n ) : null}\n\n {!generating && !error && images.length === 0 ? (\n <div className={css.canvasState}>\n <span className={css.canvasEmptyIcon}>\n <svg viewBox=\"0 0 24 24\" width=\"34\" height=\"34\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"3\"/><circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\"/><path d=\"M21 15l-5-5L5 21\"/></svg>\n </span>\n <span className={css.canvasStateTitle}>{tt('canvas.emptyTitle')}</span>\n <span className={css.canvasStateHint}>{tt('canvas.emptyHint')}</span>\n </div>\n ) : null}\n\n {!generating && images.length > 0 ? (\n <div className={css.canvasBody}>\n <div className={css.canvasMeta}>\n <span>{tt('canvas.images', { count: images.length })}</span>\n {viewingEntry !== null ? (\n <span className={css.canvasHistoryTag}>{tt('history.viewing', { time: formatTime(viewingEntry.createdAt) })}</span>\n ) : null}\n </div>\n <div className={css.grid} data-count={images.length}>\n {images.map((image, index) => (\n <figure\n key={index}\n className={css.imageCard}\n role=\"button\"\n tabIndex={0}\n title={tt('preview.open')}\n onClick={() => { openPreview(images, index) }}\n onKeyDown={(event) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n openPreview(images, index)\n }\n }}\n >\n <img\n className={css.image}\n src={srcOf(image)}\n alt={image.revisedPrompt ?? `${tt('panel.title')} ${index + 1}`}\n />\n {image.revisedPrompt !== undefined ? (\n <figcaption className={css.imageCaption} title={image.revisedPrompt}>\n {tt('revisedPrompt', { prompt: image.revisedPrompt })}\n </figcaption>\n ) : null}\n <span className={css.zoomHint}>\n <svg viewBox=\"0 0 16 16\" width=\"13\" height=\"13\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.4\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\"><circle cx=\"7\" cy=\"7\" r=\"4\"/><path d=\"M13 13l-3.2-3.2\"/><path d=\"M7 5.4v3.2M5.4 7h3.2\"/></svg>\n {tt('preview.open')}\n </span>\n <a\n className={css.download}\n href={srcOf(image)}\n download={`dsh-image-${index + 1}.${extensionOf(image.mime)}`}\n onClick={(event) => { event.stopPropagation() }}\n >\n {tt('download')}\n </a>\n </figure>\n ))}\n </div>\n </div>\n ) : null}\n </section>\n\n {/* -------------------------------------------------------- history */}\n <aside className={css.history}>\n <header className={css.historyHeader}>\n <span className={css.historyTitle}>{tt('history.title')}</span>\n {history.length > 0 ? (\n <button type=\"button\" className={css.historyClear} onClick={() => { void clearHistory() }}>\n {tt('history.clear')}\n </button>\n ) : null}\n </header>\n\n {history.length === 0 ? (\n <div className={css.historyEmpty}>{tt('history.empty')}</div>\n ) : (\n <div className={css.historyList}>\n {history.map(entry => (\n <div\n key={entry.id}\n className={css.historyItem}\n data-active={entry.id === viewingHistoryId ? '' : undefined}\n >\n <button\n type=\"button\"\n className={css.historyMain}\n onClick={() => { void viewHistoryEntry(entry) }}\n >\n {entry.images.length > 0 ? (\n <img className={css.historyThumb} src={entry.images[0]!.url} alt=\"\" />\n ) : (\n <span className={css.historyThumbPlaceholder} />\n )}\n <span className={css.historyInfo}>\n <span className={css.historyPrompt}>{entry.prompt}</span>\n <span className={css.historyMeta}>\n {tt(`mode.${entry.mode === 'edit' ? 'edit' : 'text'}` as const)}\n {' · '}{formatTime(entry.createdAt)}\n {' · '}{entry.images.length} {tt('history.images')}\n </span>\n </span>\n </button>\n <span className={css.historyActions}>\n <button type=\"button\" className={css.historyAction} onClick={() => { void restoreHistoryEntry(entry) }}>\n {tt('history.restore')}\n </button>\n <button type=\"button\" className={css.historyAction} data-danger onClick={() => { void deleteHistoryEntry(entry.id) }}>\n {tt('history.delete')}\n </button>\n </span>\n </div>\n ))}\n </div>\n )}\n </aside>\n </div>\n\n {/* -------------------------------------------------- preview overlay */}\n {preview !== null && previewImage !== null\n ? createPortal(\n <div\n className={css.lightbox}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={tt('preview.title')}\n onClick={closePreview}\n >\n <button type=\"button\" className={css.lightboxClose} aria-label={tt('preview.close')} title={tt('preview.close')} onClick={closePreview}>\n <svg viewBox=\"0 0 16 16\" width=\"18\" height=\"18\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.6\" strokeLinecap=\"round\" aria-hidden=\"true\"><path d=\"M4 4l8 8M12 4l-8 8\"/></svg>\n </button>\n {preview.images.length > 1 ? (\n <>\n <button type=\"button\" className={css.lightboxNav} data-dir=\"prev\" aria-label={tt('preview.prev')} onClick={(event) => { event.stopPropagation(); stepPreview(-1) }}>\n <svg viewBox=\"0 0 16 16\" width=\"20\" height=\"20\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.8\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\"><path d=\"M10 3l-5 5 5 5\"/></svg>\n </button>\n <button type=\"button\" className={css.lightboxNav} data-dir=\"next\" aria-label={tt('preview.next')} onClick={(event) => { event.stopPropagation(); stepPreview(1) }}>\n <svg viewBox=\"0 0 16 16\" width=\"20\" height=\"20\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.8\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\"><path d=\"M6 3l5 5-5 5\"/></svg>\n </button>\n </>\n ) : null}\n <figure className={css.lightboxFigure} onClick={(event) => { event.stopPropagation() }}>\n <div\n ref={previewStage}\n className={css.lightboxStage}\n onWheel={(event) => {\n event.preventDefault()\n setPreviewScale(current => clampPreviewScale(current + (event.deltaY < 0 ? PREVIEW_SCALE_STEP : -PREVIEW_SCALE_STEP)))\n }}\n >\n <div\n className={css.lightboxScaleFrame}\n style={{ width: `${previewFrameScale * 100}%`, height: `${previewFrameScale * 100}%` }}\n >\n <img\n className={css.lightboxImage}\n style={{ width: `${previewImageScale * 100}%`, height: `${previewImageScale * 100}%` }}\n src={srcOf(previewImage)}\n alt={previewImage.revisedPrompt ?? tt('preview.title')}\n />\n </div>\n </div>\n <div className={css.lightboxTools} role=\"group\" aria-label={tt('preview.zoomControls')}>\n <button type=\"button\" className={css.lightboxTool} aria-label={tt('preview.zoomOut')} title={tt('preview.zoomOut')} onClick={() => { setPreviewScale(current => clampPreviewScale(current - PREVIEW_SCALE_STEP)) }}>\n <svg viewBox=\"0 0 16 16\" width=\"17\" height=\"17\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.7\" strokeLinecap=\"round\" aria-hidden=\"true\"><circle cx=\"7\" cy=\"7\" r=\"4.2\"/><path d=\"M4.8 7h4.4M13 13l-2.8-2.8\"/></svg>\n </button>\n <button type=\"button\" className={css.lightboxZoomLevel} aria-label={tt('preview.zoomReset')} title={tt('preview.zoomReset')} onClick={() => { setPreviewScale(1) }}>\n {tt('preview.zoomLevel', { percent: Math.round(previewScale * 100) })}\n </button>\n <button type=\"button\" className={css.lightboxTool} aria-label={tt('preview.zoomIn')} title={tt('preview.zoomIn')} onClick={() => { setPreviewScale(current => clampPreviewScale(current + PREVIEW_SCALE_STEP)) }}>\n <svg viewBox=\"0 0 16 16\" width=\"17\" height=\"17\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.7\" strokeLinecap=\"round\" aria-hidden=\"true\"><circle cx=\"7\" cy=\"7\" r=\"4.2\"/><path d=\"M7 4.8v4.4M4.8 7h4.4M13 13l-2.8-2.8\"/></svg>\n </button>\n </div>\n {previewImage.revisedPrompt !== undefined ? (\n <div className={css.lightboxCaptionRow}>\n <figcaption className={css.lightboxCaption} title={previewImage.revisedPrompt}>\n {tt('revisedPrompt', { prompt: previewImage.revisedPrompt })}\n </figcaption>\n <button type=\"button\" className={css.lightboxCopy} aria-label={tt(promptCopied ? 'preview.copied' : 'preview.copyPrompt')} title={tt(promptCopied ? 'preview.copied' : 'preview.copyPrompt')} onClick={() => { void copyPreviewPrompt(previewImage.revisedPrompt!) }}>\n {promptCopied ? (\n <svg viewBox=\"0 0 16 16\" width=\"16\" height=\"16\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.8\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\"><path d=\"M3 8l3 3 7-7\"/></svg>\n ) : (\n <svg viewBox=\"0 0 16 16\" width=\"16\" height=\"16\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\"><rect x=\"5\" y=\"5\" width=\"7\" height=\"8\" rx=\"1\"/><path d=\"M3 10V3.8c0-.44.36-.8.8-.8H9\"/></svg>\n )}\n <span>{tt(promptCopied ? 'preview.copied' : 'preview.copyPrompt')}</span>\n </button>\n </div>\n ) : null}\n <div className={css.lightboxMeta}>\n <span className={css.lightboxIndex}>{tt('preview.index', { index: preview.index + 1, total: preview.images.length })}</span>\n <span className={css.lightboxActions}>\n <button type=\"button\" className={css.lightboxEdit} onClick={addPreviewToEdit}>\n {tt('preview.addToEdit')}\n </button>\n <a\n className={css.lightboxDownload}\n href={srcOf(previewImage)}\n download={`dsh-image-${preview.index + 1}.${extensionOf(previewImage.mime)}`}\n >\n {tt('download')}\n </a>\n </span>\n </div>\n </figure>\n </div>,\n document.body,\n )\n : null}\n </div>\n )\n}\n\n/** File extension for a MIME type (download filenames). */\nfunction extensionOf(mime: string): string {\n switch (mime.split(';')[0]!.trim()) {\n case 'image/jpeg': return 'jpg'\n case 'image/webp': return 'webp'\n case 'image/gif': return 'gif'\n default: return 'png'\n }\n}\n","/**\n * Panel view mounting.\n *\n * The `conversation` slot is single-occupant (ui-conversation) and external\n * plugins cannot declare slots, so the panel takes over the center column at\n * the DOM level: a container is appended inside the `[data-pane=\"conversation\"]`\n * grid item (an extra trailing child React never manages), and a stylesheet\n * rule hides the conversation content while the panel is active. Toggling is\n * a data attribute on <html> — no React involvement, so the conversation\n * subtree underneath stays mounted and stateful.\n */\n\nimport { createRoot, type Root } from 'react-dom/client'\nimport type { ImageGenApi } from './api.ts'\nimport type { ImageGenController } from './controller.ts'\nimport { ImageGenPanel } from './ImageGenPanel.tsx'\nimport type { ImageGenScope } from './settings-scope.ts'\nimport css from './panel.module.css'\n\n/** The injected panel container (kept in the DOM, hidden when inactive). */\nexport const PANEL_VIEW_SELECTOR = '[data-dsh-imagegen-view]'\n\nconst CONVERSATION_COLUMN_SELECTOR = '[data-pane=\"conversation\"]'\nconst ACTIVE_ATTR = 'data-dsh-imagegen-active'\n/** Sibling panels' activation attributes, removed when this panel opens. */\nconst OTHER_ACTIVE_ATTRS = ['data-dsh-taskboard-active', 'data-dsh-ssh-active']\n/** Cross-plugin activation event; detail is the activating panel name. */\nconst ACTIVATE_EVENT = 'dsh-panel-activate'\nconst PANEL_NAME = 'imagegen'\n\n/** Find the center column, or undefined while the frame is not mounted. */\nfunction conversationColumn(): HTMLElement | undefined {\n return document.querySelector<HTMLElement>(CONVERSATION_COLUMN_SELECTOR) ?? undefined\n}\n\n/**\n * Mount the panel React tree into the center column and bind its visibility\n * to the controller's panelOpen state.\n * @param controller - the panel controller driving the view.\n * @param api - the image-generation API client the panel operates through.\n * @param scope - the settings scope (config status banner).\n * @returns disposer unmounting the tree and restoring the column.\n */\nexport function mountPanel(\n controller: ImageGenController,\n api: ImageGenApi,\n scope: ImageGenScope,\n): () => void {\n let root: Root | undefined\n let container: HTMLDivElement | undefined\n\n const ensure = (): void => {\n if (container !== undefined) {\n if (container.isConnected) return\n // The conversation pane was replaced; drop the stale tree and remount.\n root?.unmount()\n root = undefined\n container.remove()\n container = undefined\n }\n const column = conversationColumn()\n if (column === undefined) return\n container = document.createElement('div')\n container.dataset.dshImagegenView = ''\n container.className = css.view\n column.appendChild(container)\n root = createRoot(container)\n root.render(<ImageGenPanel api={api} scope={scope} />)\n }\n\n // The frame mounts after boot settlement; watch for the column's arrival.\n const waitObserver = new MutationObserver(() => { ensure() })\n waitObserver.observe(document.body, { childList: true, subtree: true })\n\n const applyActive = (): void => {\n if (controller.getSnapshot().panelOpen) {\n // Single-occupant center column: opening this panel must evict sibling\n // panels (task board / ssh), both their html attributes and their\n // controller states, otherwise the visibility rules fight.\n for (const attr of OTHER_ACTIVE_ATTRS) document.documentElement.removeAttribute(attr)\n document.documentElement.setAttribute(ACTIVE_ATTR, '')\n document.dispatchEvent(new CustomEvent(ACTIVATE_EVENT, { detail: PANEL_NAME }))\n } else {\n document.documentElement.removeAttribute(ACTIVE_ATTR)\n }\n }\n const onOtherActivate = (event: Event): void => {\n const detail = (event as CustomEvent).detail\n if ((detail === 'ssh' || detail === 'taskboard') && controller.getSnapshot().panelOpen) {\n controller.close()\n }\n }\n // Jump out on sidebar context clicks: clicking a session/workspace row\n // hands the center column back to the conversation. Capture phase.\n const SIDEBAR_ROW_SELECTOR = '[class*=\"sessionRow\"], [class*=\"projectRow\"], [class*=\"searchResultRow\"], [class*=\"searchResultWorkspace\"], [class*=\"newSession\"]'\n const onClickSidebarRow = (event: MouseEvent): void => {\n if (!controller.getSnapshot().panelOpen) return\n const target = event.target as HTMLElement | null\n if (target === null) return\n if (target.closest(SIDEBAR_ROW_SELECTOR) !== null) controller.close()\n }\n document.addEventListener('click', onClickSidebarRow, true)\n document.addEventListener(ACTIVATE_EVENT, onOtherActivate)\n const unsubscribe = controller.subscribe(applyActive)\n applyActive()\n ensure()\n\n return () => {\n document.removeEventListener('click', onClickSidebarRow, true)\n document.removeEventListener(ACTIVATE_EVENT, onOtherActivate)\n waitObserver.disconnect()\n unsubscribe()\n document.documentElement.removeAttribute(ACTIVE_ATTR)\n root?.unmount()\n root = undefined\n container?.remove()\n container = undefined\n }\n}\n","/**\n * Sidebar entry injection.\n *\n * dsh's sidebar shell exposes no slot an external plugin can register into,\n * so — following the dsh-ssh / task-board precedent of DOM-level extension —\n * the entry row is injected after the shell's New Session button (after the\n * sibling plugin family block). The injection self-heals: a MutationObserver\n * watches the sidebar root and re-inserts the row whenever a React re-render\n * displaces it (re-insertion happens in the same frame, before paint).\n *\n * The row is plain DOM (no React tree) so it can never disturb the shell's\n * reconciliation; the panel view it toggles is a separate React root mounted\n * in the center column (see mount.tsx).\n */\n\nimport type { ImageGenController } from './controller.ts'\nimport css from './panel.module.css'\n\n/** Stable data attribute identifying the injected entry row. */\nexport const ENTRY_SELECTOR = '[data-dsh-imagegen-entry]'\n\n/** Inline icon (matches the shell's 16px nav-icon look): a picture glyph. */\nconst ICON = '<svg viewBox=\"0 0 16 16\" width=\"14\" height=\"14\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.3\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><rect x=\"2\" y=\"2.5\" width=\"12\" height=\"11\" rx=\"1.5\"/><circle cx=\"5.6\" cy=\"5.8\" r=\"1\"/><path d=\"M2.5 12.5l3.6-3.4 2.4 2.2 3-3 2 2.4\"/></svg>'\n\n/** Family entry selectors of sibling plugins (relative placement anchor). */\nconst FAMILY_ENTRY_SELECTOR = '[data-dsh-taskboard-entry], [data-dsh-ssh-entry], [data-dsh-imagegen-entry]'\n\n/** Find the sidebar shell root element, or undefined while not yet mounted. */\nfunction sidebarRoot(): HTMLElement | undefined {\n const column = document.querySelector<HTMLElement>('[data-pane=\"sidebar\"], [class*=\"sidebarCol\"]')\n if (column === null) return undefined\n const logoOwner = column.querySelector<HTMLElement>('[class*=\"logoRow\"]')?.parentElement\n return logoOwner ?? (column.firstElementChild as HTMLElement | undefined)\n}\n\n/** The New Session button: nested in the logo row on current shells, a direct child on legacy shells. */\nfunction newSessionButton(root: HTMLElement): HTMLButtonElement | undefined {\n const nested = root.querySelector<HTMLButtonElement>('button[class*=\"newSession\"]')\n if (nested !== null) return nested\n for (const child of root.children) {\n if (child.tagName === 'BUTTON') return child as HTMLButtonElement\n }\n return undefined\n}\n\n/** Build the entry row (a detached button; insert once the shell is up). */\nfunction createEntry(controller: ImageGenController, label: string, tooltip: string): HTMLButtonElement {\n const entry = document.createElement('button')\n entry.type = 'button'\n entry.dataset.dshImagegenEntry = ''\n entry.className = css.entry\n entry.setAttribute('aria-label', label)\n entry.setAttribute('title', tooltip)\n entry.innerHTML = '<span class=\"' + css.entryIcon + '\">' + ICON + '</span><span class=\"' + css.entryLabel + '\">' + label + '</span>'\n entry.addEventListener('click', () => { controller.toggle() })\n return entry\n}\n\n/** Re-insert the entry after the family block (task board → ssh → imagegen). */\nfunction placeEntry(root: HTMLElement, entry: HTMLButtonElement): boolean {\n const button = newSessionButton(root)\n if (button === undefined) return false\n if (entry.parentElement !== root) {\n // Position relative to the family block, never relative to transient\n // logoRow geometry: every family plugin that self-heals during a\n // re-render then lands in the same relative order.\n const row = button.closest('[class*=\"logoRow\"]')\n const base = (row !== null && row.parentElement === root) ? row : button\n const family = Array.from(root.children).filter(\n (el): el is HTMLElement => el instanceof HTMLElement && el.matches(FAMILY_ENTRY_SELECTOR),\n )\n const anchor = family.length > 0 ? family[family.length - 1].nextElementSibling : base.nextElementSibling\n root.insertBefore(entry, anchor)\n }\n return true\n}\n\n/**\n * Mount the sidebar entry, waiting for the shell to render and self-healing\n * on later React re-renders.\n * @param controller - the panel controller the entry toggles.\n * @param label - the entry label (localized).\n * @param tooltip - the entry tooltip (localized).\n * @returns disposer removing the entry and its observers.\n */\nexport function mountSidebarEntry(controller: ImageGenController, label: string, tooltip: string): () => void {\n const entry = createEntry(controller, label, tooltip)\n let root: HTMLElement | undefined\n let placed = false\n\n const tryPlace = (): void => {\n if (root !== undefined && !root.isConnected) {\n rootObserver.disconnect()\n root = undefined\n placed = false\n }\n if (placed) {\n if (document.body.contains(entry)) return\n rootObserver.disconnect()\n root = undefined\n placed = false\n }\n root ??= sidebarRoot()\n if (root === undefined) return\n placed = placeEntry(root, entry)\n if (placed) {\n rootObserver.observe(root, { childList: true, subtree: true })\n }\n }\n\n // Body-level watcher retained as the \"whole rebuild\" fallback.\n const waitObserver = new MutationObserver(() => { tryPlace() })\n waitObserver.observe(document.body, { childList: true, subtree: true })\n\n // Self-heal: if a React re-render displaces the row, re-insert it in the\n // same frame (microtask before paint -> no visible flicker).\n const rootObserver = new MutationObserver(() => {\n if (root === undefined || !root.isConnected) {\n placed = false\n tryPlace()\n return\n }\n if (!root.contains(entry)) {\n placed = placeEntry(root, entry)\n }\n })\n\n // Reflect the panel's open state on the row (active highlight).\n const syncActive = () => {\n if (controller.getSnapshot().panelOpen) entry.dataset.active = 'true'\n else delete entry.dataset.active\n }\n const unsubscribe = controller.subscribe(syncActive)\n syncActive()\n\n tryPlace()\n\n return () => {\n waitObserver.disconnect()\n rootObserver.disconnect()\n unsubscribe()\n entry.remove()\n }\n}\n","/**\n * Staged form model behind the plugin settings card. A card stages what the\n * user types and writes it only when they save — the settings write is a\n * durable, revision-fenced document mutation, so staging keeps what is on\n * screen exactly what a save would store. Self-contained slice of the same\n * pattern the dsh-web-ui family cards use (this package must not depend on a\n * sibling UI package).\n */\n\nimport { createSnapshotStore, type SettingsScope, type SettingsScopeSnapshot, type SnapshotStore } from '@deepseek-ai/dsh-client-runtime/client'\n\n/** The write one field's staged text performs when the card is saved. */\nexport type FieldWrite =\n | { kind: 'set'; value: unknown }\n | { kind: 'clear' }\n\n/** How one field converts between its stored value and its draft text. */\nexport interface FieldSpec {\n /** Field name inside the namespace section. */\n field: string\n /** Render a stored value as draft text; the empty string when the section carries none. */\n format: (value: unknown) => string\n /**\n * The write this draft text stages, or undefined when the text is not a\n * value this field accepts — which blocks the save rather than discarding it.\n */\n parse: (text: string) => FieldWrite | undefined\n /**\n * True for secret fields (role('secret') in the namespace schema): the\n * redacted wire view never returns the stored value, so the form treats an\n * empty draft as \"no change\" and judges writes by the namespace's secrets\n * sidecar instead of the user layer.\n */\n secret?: boolean\n}\n\n/** One field as the card renders it. */\nexport interface FieldState {\n /** Draft text the control renders. */\n text: string\n /** Whether saving would leave a user-layer entry for this field. */\n overridden: boolean\n /** Whether the draft is not a value this field accepts, which blocks saving. */\n invalid: boolean\n}\n\n/** Form state every plugin settings card shares. */\nexport interface CardShell {\n /** False while the namespace is still loading; the card renders nothing. */\n available: boolean\n /** Whether the namespace is actually served (the bridge answered). */\n exposed: boolean\n /** Whether the Host document accepts writes. */\n writable: boolean\n /** Whether the form holds edits that a save would write. */\n dirty: boolean\n /** Whether any staged draft is invalid, which blocks the save. */\n invalid: boolean\n /** Whether a save is crossing the wire. */\n saving: boolean\n /** Whether the last save did not land as staged; cleared by the next edit or save. */\n failed: boolean\n}\n\n/** The write actions the card's slot entry injects. */\nexport interface CardActions {\n /** Stage draft text for one field. */\n edit: (field: string, text: string) => void\n /** Stage a clear, so saving lets the field re-inherit the composition layer. */\n resetField: (field: string) => void\n /** Write every staged edit, then re-seed from what the Host accepted. */\n save: () => void\n /** Drop every staged edit. */\n discard: () => void\n}\n\n/** One field's staged edit. */\ninterface StagedEdit {\n /** Draft text the control renders. */\n text: string\n /** True when this edit clears the field whatever text it shows. */\n clear: boolean\n}\n\n/** One staged edit resolved into the write a save performs. */\ninterface PlannedWrite {\n /** Field this entry writes. */\n field: string\n /** Perform the write and report whether the Host holds the staged value afterwards. */\n run: (() => Promise<boolean>) | undefined\n}\n\n/** A free-text field. An empty draft clears the field. */\nexport function textField(field: string): FieldSpec {\n return {\n field,\n format: value => typeof value === 'string' ? value : '',\n parse: (text) => {\n const trimmed = text.trim()\n return trimmed === '' ? { kind: 'clear' } : { kind: 'set', value: trimmed }\n },\n }\n}\n\n/** A boolean field, edited through true/false draft text. */\nexport function booleanField(field: string): FieldSpec {\n return {\n field,\n format: value => typeof value === 'boolean' ? String(value) : '',\n parse: (text) => {\n if (text === 'true') return { kind: 'set', value: true }\n if (text === 'false') return { kind: 'set', value: false }\n return undefined\n },\n }\n}\n\n/**\n * A secret field (role('secret') in the namespace schema). The stored value is\n * never rendered or returned by the redacted wire view, so:\n * - an empty draft means \"no change\" (typing nothing must never clear an\n * invisible stored key); the dedicated clear action stages an explicit clear;\n * - a write's outcome is judged by the namespace's secrets sidecar through\n * the {@link CardForm} `secretSettled` hook, never by the user layer.\n */\nexport function secretField(field: string): FieldSpec {\n return {\n field,\n secret: true,\n format: () => '',\n parse: (text) => {\n const trimmed = text.trim()\n if (trimmed === '') return undefined\n return { kind: 'set', value: trimmed }\n },\n }\n}\n\n/**\n * Stages one card's edits over one settings scope and writes them on save.\n *\n * The Host is the only authority on whether a value was accepted — its\n * validators own the constraints no schema can express — so the outcome is\n * read back from the section rather than predicted here. A save that did not\n * land keeps its drafts, so the user can correct them instead of retyping.\n */\nexport class CardForm<T> {\n private readonly specs: Map<string, FieldSpec>\n private readonly staged = new Map<string, StagedEdit>()\n private readonly listeners = new Set<() => void>()\n private saving = false\n private failed = false\n\n /**\n * @param scope - the bound settings scope for this card's namespace.\n * @param specs - the fields this card edits.\n * @param options.secretSettled - for secret fields, whether the namespace\n * currently holds a stored secret (the redacted view never round-trips the\n * value, so a write's outcome is read from the secrets sidecar instead).\n */\n constructor(\n private readonly scope: SettingsScope<T>,\n specs: FieldSpec[],\n private readonly options: { secretSettled?: (field: string) => boolean } = {},\n ) {\n this.specs = new Map(specs.map(spec => [spec.field, spec]))\n scope.subscribe(() => { this.publish() })\n }\n\n /** Publish a projection of this form, rebuilt whenever the scope or a draft changes. */\n bind<S>(project: () => S): SnapshotStore<S> {\n const store = createSnapshotStore(project())\n this.listeners.add(() => { store.set(project()) })\n return store\n }\n\n /** Read the card-level state: what the Host serves, and what a save would do. */\n shell(): CardShell {\n const snapshot = this.scope.getSnapshot()\n const plan = this.plan()\n return {\n available: snapshot.status !== 'loading',\n exposed: snapshot.status === 'ready',\n writable: snapshot.writable,\n dirty: plan.length > 0,\n invalid: plan.some(item => item.run === undefined),\n saving: this.saving,\n failed: this.failed,\n }\n }\n\n /** Read one field's state from the effective section and its staged draft. */\n field(field: string): FieldState {\n const spec = this.specOf(field)\n const staged = this.staged.get(field)\n if (staged === undefined) {\n return { text: spec.format(this.sectionValue(field)), overridden: this.stored(field), invalid: false }\n }\n const write = staged.clear ? { kind: 'clear' as const } : spec.parse(staged.text)\n return {\n text: staged.text,\n overridden: write?.kind === 'set',\n // A secret field's empty draft is \"no change\" (see secretField), never\n // an invalid state — the stored value is invisible, so the user cannot\n // be expected to type over it.\n invalid: write === undefined && !(spec.secret === true && staged.text.trim() === ''),\n }\n }\n\n /** The actions the card's slot registration injects. */\n actions(): CardActions {\n return {\n edit: (field, text) => { this.stage(field, { text, clear: false }) },\n resetField: (field) => {\n this.stage(field, { text: this.specOf(field).format(this.baseValue(field)), clear: true })\n },\n save: () => { void this.save() },\n discard: () => {\n if (this.staged.size === 0 && !this.failed) return\n this.staged.clear()\n this.failed = false\n this.publish()\n },\n }\n }\n\n /**\n * Write every staged edit, then re-seed from what the Host accepted.\n * @returns settlement after every write and the read-back.\n */\n async save(): Promise<void> {\n const plan = this.plan()\n const writes = plan.flatMap(item => item.run === undefined ? [] : [item.run])\n if (plan.length === 0 || this.saving || writes.length !== plan.length) return\n this.saving = true\n this.failed = false\n this.publish()\n let landed = true\n for (const write of writes) {\n landed = await write() && landed\n }\n if (landed) this.staged.clear()\n this.saving = false\n this.failed = !landed\n this.publish()\n }\n\n /**\n * Every staged edit a save would write. An entry whose draft is not a value\n * its field accepts carries no write: the form is still dirty, and the save\n * refuses rather than dropping the edit. A staged edit that matches the\n * effective section is not a write at all.\n */\n private plan(): PlannedWrite[] {\n const plan: PlannedWrite[] = []\n for (const [field, staged] of this.staged) {\n const spec = this.specOf(field)\n if (staged.clear) {\n const present = spec.secret === true\n ? (this.options.secretSettled?.(field) ?? false)\n : this.stored(field)\n if (present) plan.push({ field, run: () => this.clear(field) })\n continue\n }\n if (staged.text === spec.format(this.sectionValue(field))) continue\n const write = spec.parse(staged.text)\n if (write === undefined) plan.push({ field, run: undefined })\n else if (write.kind === 'clear') plan.push({ field, run: () => this.clear(field) })\n else plan.push({ field, run: () => this.store(field, write.value) })\n }\n return plan\n }\n\n private async clear(field: string): Promise<boolean> {\n await this.scope.unset(field)\n const spec = this.specOf(field)\n if (spec.secret === true) return !(this.options.secretSettled?.(field) ?? false)\n return !this.stored(field)\n }\n\n private async store(field: string, value: unknown): Promise<boolean> {\n await this.scope.set(field, value)\n const spec = this.specOf(field)\n if (spec.secret === true) return this.options.secretSettled?.(field) ?? true\n return this.userLayer()?.[field] === value\n }\n\n private stage(field: string, edit: StagedEdit): void {\n this.staged.set(field, edit)\n this.failed = false\n this.publish()\n }\n\n private specOf(field: string): FieldSpec {\n const spec = this.specs.get(field)\n if (spec === undefined) throw new Error(`settings card has no field ${field}`)\n return spec\n }\n\n private snapshotOf(): SettingsScopeSnapshot<T> {\n return this.scope.getSnapshot()\n }\n\n private sectionValue(field: string): unknown {\n return (this.snapshotOf().value as Record<string, unknown> | undefined)?.[field]\n }\n\n private baseValue(field: string): unknown {\n return (this.snapshotOf().base as Record<string, unknown> | undefined)?.[field]\n }\n\n private userLayer(): Record<string, unknown> | undefined {\n return this.snapshotOf().user as Record<string, unknown> | undefined\n }\n\n private stored(field: string): boolean {\n const user = this.userLayer()\n return user !== undefined && Object.hasOwn(user, field)\n }\n\n private publish(): void {\n for (const listener of [...this.listeners]) listener()\n }\n}\n","/**\n * The dsh-imagegen settings card: api_url, api_key (secret, display-only\n * \"set\" state), and the plugin switches. Registers into the official\n * `settings.plugin.item` slot (the Settings → Plugins → Configurable tab),\n * independent of the dsh-web-ui family group, bound to the plugin's own\n * bridge settings scope.\n */\n\nimport { useState } from 'react'\nimport type { InjectFace, PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport { createSnapshotStore, type SnapshotStore } from '@deepseek-ai/dsh-client-runtime/client'\nimport { CardForm, booleanField, secretField, textField, type CardActions, type CardShell, type FieldState as CardFieldState } from './settings-form.ts'\nimport type { ImageGenScope } from './settings-scope.ts'\nimport { PLUGIN_VERSION } from '../protocol.ts'\nimport css from './settings-card.module.css'\n\n/** The fields this card edits (the namespace's full schema). */\nexport interface ImageGenSettings {\n enabled?: boolean\n announceToAgent?: boolean\n apiUrl?: string\n apiKey?: string\n}\n\n/** What the card renders. */\nexport interface ImageGenSettingsCardState extends CardShell {\n /** Master switch. */\n enabled: CardFieldState\n /** System-prompt announcement flag. */\n announceToAgent: CardFieldState\n /** API base URL. */\n apiUrl: CardFieldState\n /** API key draft (the stored value is never rendered). */\n apiKey: CardFieldState\n}\n\n/** The registration-side face the card's slot entry injects. */\nexport interface ImageGenSettingsCardFace extends CardActions {\n hooks: {\n /** Card snapshot bound by the renderer as useImageGenSettingsCard. */\n imageGenSettingsCard: SnapshotStore<ImageGenSettingsCardState>\n /** Whether a secret (apiKey) is currently stored. */\n imageGenKeySet: SnapshotStore<boolean>\n }\n}\n\n/** Bridges the imagegen scope onto the card's staged form. */\nexport class ImageGenSettingsCardController {\n private readonly form: CardForm<ImageGenSettings>\n\n /** @param scope - the bound bridge scope for the dsh-imagegen namespace. */\n constructor(private readonly scope: ImageGenScope) {\n this.form = new CardForm(scope, [\n booleanField('enabled'),\n booleanField('announceToAgent'),\n textField('apiUrl'),\n secretField('apiKey'),\n ], {\n // The redacted wire view never returns the key; a save's outcome is\n // judged by the namespace's secrets sidecar instead.\n secretSettled: () => this.scope.getKeySetSnapshot(),\n })\n }\n\n private projection(): ImageGenSettingsCardState {\n return {\n ...this.form.shell(),\n enabled: this.form.field('enabled'),\n announceToAgent: this.form.field('announceToAgent'),\n apiUrl: this.form.field('apiUrl'),\n apiKey: this.form.field('apiKey'),\n }\n }\n\n /**\n * Build the face the card's slot registration injects.\n * @returns the card's snapshot, the key-set flag, and the form actions.\n */\n inject(): ImageGenSettingsCardFace {\n const cardStore = this.form.bind(() => this.projection())\n const keySetStore = createSnapshotStore(this.scope.getKeySetSnapshot())\n this.scope.subscribeKeySet(() => { keySetStore.set(this.scope.getKeySetSnapshot()) })\n return {\n hooks: {\n imageGenSettingsCard: cardStore,\n imageGenKeySet: keySetStore,\n },\n ...this.form.actions(),\n }\n }\n}\n\n/** Props the renderer binds for this card. */\nexport type ImageGenSettingsCardProps =\n PropsRuntime<'settings.plugin.item'>\n & PropsLocale<'dsh-imagegen'>\n & InjectFace<ImageGenSettingsCardFace>\n\n/**\n * Render the card.\n * @param props - locale copy, the card snapshot, and the form actions.\n * @returns the card, or nothing while the namespace is still loading.\n */\nexport function ImageGenSettingsCard(props: ImageGenSettingsCardProps) {\n const { t } = props\n const state = props.useImageGenSettingsCard(snapshot => snapshot)\n const keySet = props.useImageGenKeySet(snapshot => snapshot)\n const [open, setOpen] = useState(false)\n if (!state.available) return null\n const title = t('settings.title')\n const blocked = !state.dirty || state.invalid || state.saving\n const disabled = !state.writable\n const fieldProps = {\n overriddenLabel: t('settings.overridden'),\n resetLabel: t('settings.reset'),\n invalidLabel: t('settings.invalidNumber'),\n disabled,\n }\n if (!state.exposed) {\n return (\n <li className={css.card}>\n <button\n type=\"button\"\n className={css.header}\n aria-expanded={open}\n aria-label={`${t(open ? 'settings.collapse' : 'settings.expand')}: ${title}`}\n onClick={() => { setOpen(!open) }}\n >\n <span className={css.headText}>\n <span className={css.name}>{title}</span>\n <span className={css.description}>{t('settings.description')}</span>\n </span>\n <span className={open ? css.chevronOpen : css.chevron}>▾</span>\n </button>\n {open\n ? (\n <div className={css.body}>\n <p className={css.notExposed} role=\"status\">{t('settings.notExposed')}</p>\n </div>\n )\n : null}\n </li>\n )\n }\n return (\n <li className={css.card}>\n <button\n type=\"button\"\n className={css.header}\n aria-expanded={open}\n aria-label={`${t(open ? 'settings.collapse' : 'settings.expand')}: ${title}`}\n onClick={() => { setOpen(!open) }}\n >\n <span className={css.headText}>\n <span className={css.name}>{title}</span>\n <span className={css.description}>{t('settings.description')}</span>\n </span>\n {state.dirty ? <span className={css.pending}>{t('settings.unsaved')}</span> : null}\n <span className={open ? css.chevronOpen : css.chevron}>▾</span>\n </button>\n {open\n ? (\n <div className={css.body}>\n {!state.writable ? <p className={css.readOnly} role=\"status\">{t('settings.readOnly')}</p> : null}\n <div className={css.versionRow}>\n <span className={css.versionLabel}>{t('settings.currentVersion')}</span>\n <code className={css.versionValue}>v{PLUGIN_VERSION}</code>\n </div>\n <ValueField\n id=\"dsh-imagegen-settings-apikey\"\n label={t('settings.apiKey')}\n hint={keySet ? t('settings.apiKeySet') : t('settings.apiKeyHint')}\n placeholder=\"sk-…\"\n secret\n {...fieldProps}\n {...state.apiKey}\n overridden={false}\n onEdit={(text) => { props.edit('apiKey', text) }}\n onReset={() => { props.resetField('apiKey') }}\n clearLabel={t('settings.apiKeyClear')}\n onClear={() => { props.resetField('apiKey') }}\n canClear={keySet}\n />\n <ValueField\n id=\"dsh-imagegen-settings-apiurl\"\n label={t('settings.apiUrl')}\n hint={t('settings.apiUrlHint')}\n placeholder=\"https://api.openai.com/v1\"\n {...fieldProps}\n {...state.apiUrl}\n onEdit={(text) => { props.edit('apiUrl', text) }}\n onReset={() => { props.resetField('apiUrl') }}\n />\n <BooleanField\n id=\"dsh-imagegen-settings-enabled\"\n label={t('settings.enabled')}\n hint={t('settings.enabledHint')}\n inheritLabel={t('settings.inherit')}\n onLabel={t('settings.on')}\n offLabel={t('settings.off')}\n {...fieldProps}\n {...state.enabled}\n onEdit={(text) => { props.edit('enabled', text) }}\n onReset={() => { props.resetField('enabled') }}\n />\n <BooleanField\n id=\"dsh-imagegen-settings-announce\"\n label={t('settings.announceToAgent')}\n hint={t('settings.announceToAgentHint')}\n inheritLabel={t('settings.inherit')}\n onLabel={t('settings.on')}\n offLabel={t('settings.off')}\n {...fieldProps}\n {...state.announceToAgent}\n onEdit={(text) => { props.edit('announceToAgent', text) }}\n onReset={() => { props.resetField('announceToAgent') }}\n />\n <div className={css.footer}>\n {state.failed ? <p className={css.failed} role=\"status\">{t('settings.saveFailed')}</p> : null}\n <button\n type=\"button\"\n className={css.discard}\n disabled={!state.dirty || state.saving}\n onClick={props.discard}\n >\n {t('settings.discard')}\n </button>\n <button\n type=\"button\"\n className={css.save}\n disabled={blocked}\n onClick={props.save}\n >\n {t(!state.saving ? 'settings.save' : 'settings.saving')}\n </button>\n </div>\n </div>\n )\n : null}\n </li>\n )\n}\n\n/** Props every field control needs regardless of its value type. */\ninterface FieldProps {\n /** Stable id associating the label with its control. */\n id: string\n /** Visible label. */\n label: string\n /** One-line explanation rendered under the control. */\n hint: string\n /** Draft text this control renders. */\n text: string\n /** True when saving would leave a user-layer entry for this field. */\n overridden: boolean\n /** True when the draft is not a value this field accepts. */\n invalid: boolean\n /** Copy for the overridden badge. */\n overriddenLabel: string\n /** Copy for the reset control. */\n resetLabel: string\n /** Copy shown in place of the hint while the draft is invalid. */\n invalidLabel: string\n /** Disables every control (read-only document, or an unavailable namespace). */\n disabled: boolean\n /** Stage draft text. */\n onEdit: (text: string) => void\n /** Stage a clear so the field re-inherits the composition layer. */\n onReset: () => void\n}\n\n/** A staged value field; `secret` renders a password control. */\nfunction ValueField(props: FieldProps & {\n /** Render a password control. */\n secret?: boolean\n /** Placeholder shown while the draft is empty. */\n placeholder?: string\n /** Label of the dedicated clear control (secret fields). */\n clearLabel?: string\n /** Stage a clear of the stored secret. */\n onClear?: () => void\n /** Whether a stored secret exists (enables the clear control). */\n canClear?: boolean\n}) {\n return (\n <div className={css.field}>\n <div className={css.head}>\n <label className={css.label} htmlFor={props.id}>{props.label}</label>\n {props.overridden\n ? (\n <span className={css.badges}>\n <span className={css.badge}>{props.overriddenLabel}</span>\n <button\n type=\"button\"\n className={css.reset}\n disabled={props.disabled}\n onClick={props.onReset}\n >\n {props.resetLabel}\n </button>\n </span>\n )\n : null}\n {props.secret === true && props.canClear === true\n ? (\n <button\n type=\"button\"\n className={css.reset}\n disabled={props.disabled}\n onClick={props.onClear}\n >\n {props.clearLabel ?? props.resetLabel}\n </button>\n )\n : null}\n </div>\n <input\n id={props.id}\n className={props.invalid ? css.inputInvalid : css.input}\n type={props.secret === true ? 'password' : 'text'}\n autoComplete={props.secret === true ? 'off' : undefined}\n {...props.invalid ? { 'aria-invalid': true } : {}}\n value={props.text}\n placeholder={props.placeholder ?? ''}\n disabled={props.disabled}\n onChange={(event) => { props.onEdit(event.target.value) }}\n />\n <p className={props.invalid ? css.invalid : css.hint}>\n {props.invalid ? props.invalidLabel : props.hint}\n </p>\n </div>\n )\n}\n\n/** A staged boolean field: 继承 / 开 / 关. */\nfunction BooleanField(props: FieldProps & {\n /** Copy for the inherit option. */\n inheritLabel: string\n /** Copy for the on option. */\n onLabel: string\n /** Copy for the off option. */\n offLabel: string\n}) {\n return (\n <div className={css.field}>\n <div className={css.head}>\n <label className={css.label} htmlFor={props.id}>{props.label}</label>\n {props.overridden\n ? (\n <span className={css.badges}>\n <span className={css.badge}>{props.overriddenLabel}</span>\n <button\n type=\"button\"\n className={css.reset}\n disabled={props.disabled}\n onClick={props.onReset}\n >\n {props.resetLabel}\n </button>\n </span>\n )\n : null}\n </div>\n <select\n id={props.id}\n className={css.select}\n value={props.text}\n disabled={props.disabled}\n onChange={(event) => { props.onEdit(event.target.value) }}\n >\n <option value=\"\">{props.inheritLabel}</option>\n <option value=\"true\">{props.onLabel}</option>\n <option value=\"false\">{props.offLabel}</option>\n </select>\n <p className={css.hint}>{props.hint}</p>\n </div>\n )\n}\n","/**\n * Browser-side settings scope for the dsh-imagegen namespace, served by the\n * plugin's own loopback bridge routes (/api/dsh-imagegen/settings). The\n * official rc.6 settings scope answers \"unavailable\" for every third-party\n * namespace (the host-apiproxy allowlist is hard-coded), so this package\n * re-serves its namespace through the host settings seam over a same-origin,\n * loopback-only HTTP pair — the same pattern the dsh-web-ui family bridge\n * uses, self-contained per plugin.\n */\n\nimport {\n createSnapshotStore,\n type SettingsScope,\n type SettingsScopeSnapshot,\n type SnapshotStore,\n} from '@deepseek-ai/dsh-client-runtime/client'\nimport { SETTINGS_API } from '../protocol.ts'\n\n/** The fields this plugin's settings card edits. */\nexport interface ImageGenConfig {\n enabled?: boolean\n announceToAgent?: boolean\n apiUrl?: string\n apiKey?: string\n}\n\n/** Wire shape of one namespace view from the bridge. */\ninterface BridgeView {\n ns: string\n value: unknown\n base?: unknown\n user?: unknown\n revision: number\n secrets?: Array<{ path: string[]; set: boolean }>\n}\n\n/** The bridge response envelope ({ ok: true, value } | { ok: false, code, message }). */\ntype BridgeEnvelope =\n | { ok: true; value: { namespaces?: BridgeView[]; writable?: boolean } | BridgeView }\n | { ok: false; code: string; message: string }\n\n/** Settings wire face over the bridge routes (fetch-backed). */\nfunction createBridgeApi(fetchFn: typeof fetch): {\n settings: {\n describe(payload: Record<string, never>): Promise<{ result: BridgeEnvelope }>\n mutate(payload: { ns: string; ops: unknown[]; expectedRevision?: number }): Promise<{ result: BridgeEnvelope }>\n }\n} {\n const post = async (path: string, body: unknown): Promise<{ result: BridgeEnvelope }> => {\n try {\n const response = await fetchFn(path, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(body),\n })\n if (!response.ok) {\n return { result: { ok: false, code: 'internal', message: `bridge HTTP ${response.status}` } }\n }\n return { result: await response.json() as BridgeEnvelope }\n } catch {\n return { result: { ok: false, code: 'internal', message: 'settings bridge unreachable' } }\n }\n }\n return {\n settings: {\n describe: async payload => post(SETTINGS_API.describe, payload),\n mutate: async payload => post(SETTINGS_API.mutate, payload),\n },\n }\n}\n\n/**\n * A SettingsScope over the bridge face: serialized queue, revision-fenced\n * writes, recovery read after a refusal. Mirrors the official controller's\n * ordering but trusts the Host-seam value without re-running the wire-schema\n * validation — the seam already validated it.\n */\nclass BridgeScopeController<T> implements SettingsScope<T> {\n private readonly store: SnapshotStore<SettingsScopeSnapshot<T>>\n /** Whether the namespace currently holds a stored secret (e.g. apiKey). */\n private readonly keySet: SnapshotStore<boolean>\n private tail: Promise<void> = Promise.resolve()\n private disposed = false\n\n constructor(\n private readonly api: ReturnType<typeof createBridgeApi>['settings'],\n private readonly spec: { namespace: string },\n ) {\n this.store = createSnapshotStore<SettingsScopeSnapshot<T>>({\n status: 'loading',\n value: undefined,\n base: undefined,\n user: undefined,\n revision: undefined,\n writable: false,\n mode: 'host',\n })\n this.keySet = createSnapshotStore(false)\n }\n\n getSnapshot(): SettingsScopeSnapshot<T> {\n return this.store.getSnapshot()\n }\n\n /** Whether a stored secret exists (from the redacted view's secrets list). */\n getKeySetSnapshot(): boolean {\n return this.keySet.getSnapshot()\n }\n\n /** Observe the secret-set flag. */\n subscribeKeySet(listener: () => void): () => void {\n return this.keySet.subscribe(listener)\n }\n\n subscribe(listener: () => void): () => void {\n return this.store.subscribe(listener)\n }\n\n /** Queue a bridge refresh. */\n load(): Promise<void> {\n return this.enqueue(() => this.read())\n }\n\n set(field: string, value: unknown): Promise<void> {\n return this.enqueue(() => this.write({ op: 'set', path: [field], value }))\n }\n\n unset(field: string): Promise<void> {\n return this.enqueue(() => this.write({ op: 'unset', path: [field] }))\n }\n\n async dispose(): Promise<void> {\n this.disposed = true\n await this.tail\n }\n\n private enqueue(operation: () => Promise<void>): Promise<void> {\n if (this.disposed) return Promise.resolve()\n const task = this.tail.then(async () => {\n if (this.disposed) return\n await operation()\n })\n this.tail = task.catch(() => {})\n return task\n }\n\n private async read(): Promise<void> {\n let response\n try {\n response = await this.api.describe({})\n } catch {\n if (!this.disposed) this.store.update(draft => { draft.status = 'unavailable' })\n return\n }\n if (!response.result.ok || this.disposed) {\n if (!this.disposed) this.store.update(draft => { draft.status = 'unavailable' })\n return\n }\n const { namespaces, writable } = response.result.value as { namespaces?: BridgeView[]; writable?: boolean }\n const view = namespaces?.find(candidate => candidate.ns === this.spec.namespace)\n if (view === undefined) {\n this.store.update(draft => {\n draft.status = 'unavailable'\n draft.writable = writable === true\n })\n this.keySet.set(false)\n return\n }\n this.accept(view, writable)\n }\n\n private async write(op: { op: 'set' | 'unset'; path: string[]; value?: unknown }): Promise<void> {\n const revision = this.getSnapshot().revision\n let response\n try {\n response = await this.api.mutate({\n ns: this.spec.namespace,\n ops: [op],\n ...revision === undefined ? {} : { expectedRevision: revision },\n })\n } catch {\n await this.read()\n return\n }\n if (!response.result.ok || this.disposed) {\n await this.read()\n return\n }\n this.accept(response.result.value as BridgeView, undefined)\n }\n\n private accept(view: BridgeView, writable: boolean | undefined): void {\n this.store.update(draft => {\n draft.revision = view.revision\n draft.base = view.base\n draft.user = view.user\n if (writable !== undefined) draft.writable = writable\n draft.status = 'ready'\n // Trust the Host-seam value: the seam already validated it, and the\n // card binds without a narrowing decoder.\n draft.value = view.value as T\n })\n this.keySet.set(Array.isArray(view.secrets) && view.secrets.some(secret => secret.set))\n }\n}\n\n/** The bound scope plus the secret-set flag, as the card and panel consume it. */\nexport interface ImageGenScope extends SettingsScope<ImageGenConfig> {\n /** Queue a bridge refresh (the invalidation path re-reads the namespace). */\n load(): Promise<void>\n getKeySetSnapshot(): boolean\n subscribeKeySet(listener: () => void): () => void\n}\n\n/**\n * Bind the dsh-imagegen settings scope over the bridge routes and start its\n * initial read (the caller mounts nothing until the scope settles).\n * @param fetchFn - the fetch implementation (the global fetch on loopback).\n * @returns the scope; unavailable when the bridge is unreachable.\n */\nexport function bindImageGenScope(fetchFn: typeof fetch = fetch): ImageGenScope {\n const controller = new BridgeScopeController<ImageGenConfig>(createBridgeApi(fetchFn).settings, {\n namespace: 'dsh-imagegen',\n })\n void controller.load()\n return controller\n}\n","/**\n * Browser-half entry for the dsh-imagegen plugin — runs inside the dsh web\n * GUI.\n *\n * Registers the dsh-imagegen locale dictionaries, binds the plugin's own\n * settings scope (its bridge routes serve the namespace the official rc.6\n * allowlist would refuse), registers the settings card into the Web UI plugin\n * group slot, and mounts the two DOM surfaces: the sidebar entry row (toggles\n * the panel) and the generation studio in the center column. Failure policy:\n * DOM mounting problems are logged, never thrown — the web shell fails the\n * whole boot when a plugin apply throws, and an external plugin must not take\n * the GUI down.\n */\nimport type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'\nimport type { ConnectionHandle } from '@deepseek-ai/dsh-client-connection/client'\n// Type-only: pulls the locale plugin's Context merge (ctx.locale).\nimport type {} from '@deepseek-ai/dsh-client-locale/client'\n// Type-only: pulls the LocaleNamespaceMap merge table.\nimport type {} from '@deepseek-ai/dsh-client-ui-slots'\nimport { ImageGenApi } from './api.ts'\nimport { ImageGenController } from './controller.ts'\nimport { tt } from './helpers.ts'\nimport { en, zh, type ImageGenKey } from './locales.ts'\nimport { mountPanel } from './mount.tsx'\nimport { mountSidebarEntry } from './sidebar-entry.ts'\nimport { ImageGenSettingsCard, ImageGenSettingsCardController } from './SettingsCard.tsx'\nimport { bindImageGenScope, type ImageGenScope } from './settings-scope.ts'\n\n/** Locale namespace this plugin owns. */\nconst NS = 'dsh-imagegen'\n\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface LocaleNamespaceMap {\n /** dsh-imagegen surface copy. */\n 'dsh-imagegen': ImageGenKey\n }\n\n interface SlotMap {\n /**\n * The official plugin-configuration slot the Settings → Plugins →\n * Configurable tab declares and renders. This card registers there as its\n * own standalone card — independent of the dsh-web-ui family group — so\n * this plugin never reads as part of that family. Spelled here with the\n * same shape so this package can register without depending on the\n * sibling UI package.\n */\n 'settings.plugin.item': { kind: 'list'; scope: 'root'; owner: ImageGenPluginItemOwnerProps }\n }\n}\n\n/** Owner share of a plugin card (the section supplies nothing). */\nexport interface ImageGenPluginItemOwnerProps {\n /** Marker field: card owner props are intentionally empty. */\n children?: never\n}\n\n/** Required services (fiber inject waiting — the runtime must be up first). */\nexport const inject = ['slots', 'locale', 'connection']\n\n/**\n * Mount the studio, its sidebar entry, and the settings card.\n * @param ctx - client root context (services: slots, locale, connection).\n */\nexport function apply(ctx: ClientContext): void {\n ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'dsh-imagegen: dictionaries')\n\n const connection = ctx.get('connection') as ConnectionHandle | undefined\n const loopback = connection?.isLoopback === true\n // The bridge routes are loopback-fenced; remote browsers get an unavailable\n // scope (the card explains the gap) instead of failing fetches.\n const scope: ImageGenScope = bindImageGenScope(loopback\n ? (input, init) => fetch(input, init)\n : () => { throw new Error('settings bridge is loopback-only') })\n\n // Re-read the scope whenever the connection resets (same invalidation the\n // official settings binder wires).\n ctx.effect(() => {\n const disposers = [\n ctx.on('connection/reset', () => { void scope.load() }),\n ]\n return () => { for (const dispose of disposers) dispose() }\n }, 'dsh-imagegen: settings scope invalidation')\n\n // Plugin configuration card: one staged form over the `dsh-imagegen` scope,\n // registered into the official plugin-configuration slot (Settings →\n // Plugins → Configurable) as a standalone card.\n const settingsCard = new ImageGenSettingsCardController(scope)\n ctx.slots.inject('settings.plugin.item', () => ctx.slots.register({\n name: 'settings.plugin.item',\n id: 'imagegen',\n order: 30,\n locale: NS,\n inject: () => settingsCard.inject(),\n }, ImageGenSettingsCard))\n\n // The sidebar entry and studio mount once the settings scope settles; while\n // the scope is still loading, the composition default is unknown, so nothing\n // mounts yet. Only an unavailable scope falls back to the default (enabled).\n let uiDisposer: (() => void) | undefined\n const mountUi = (): void => {\n if (uiDisposer !== undefined) return\n const controller = new ImageGenController()\n const api = new ImageGenApi()\n const disposers: Array<() => void> = []\n try {\n disposers.push(mountSidebarEntry(controller, tt('entry.label'), tt('entry.tooltip')))\n disposers.push(mountPanel(controller, api, scope))\n } catch (error) {\n // DOM failures degrade the studio, never the GUI.\n console.warn('[dsh-imagegen] mount failed:', error)\n }\n uiDisposer = () => {\n for (const dispose of disposers.splice(0)) dispose()\n uiDisposer = undefined\n }\n }\n const syncEnabled = (): void => {\n const snapshot = scope.getSnapshot()\n const enabled = snapshot.status === 'ready'\n ? snapshot.value?.enabled ?? true\n : snapshot.status === 'unavailable'\n if (enabled) mountUi()\n else uiDisposer?.()\n }\n scope.subscribe(syncEnabled)\n syncEnabled()\n}\n"],"mappings":"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"}
package/lib/index.js CHANGED
@@ -14,7 +14,7 @@ import { spawn } from "node:child_process";
14
14
  /** Settings namespace this plugin owns (host settings seam + bridge). */
15
15
  const IMAGEGEN_SETTINGS_NAMESPACE = "dsh-imagegen";
16
16
  /** Published package version shared by the host updater and the client UI. */
17
- const PLUGIN_VERSION = "1.0.5";
17
+ const PLUGIN_VERSION = "1.0.6";
18
18
  /** Same-origin route family (loopback-only, mirroring the dsh-ssh fence). */
19
19
  const SETTINGS_API = {
20
20
  describe: "/api/dsh-imagegen/settings/describe",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@dickpy/dsh-imagegen",
3
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 / gpt-image-1 / dall-e-3), with a settings card for api_url / api_key and a sidebar entry opening a split-pane generation studio.",
4
- "version": "1.0.5",
4
+ "version": "1.0.6",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
7
7
  "exports": {
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.0.5'
11
+ export const PLUGIN_VERSION = '1.0.6'
12
12
 
13
13
  /** Same-origin route family (loopback-only, mirroring the dsh-ssh fence). */
14
14
  export const SETTINGS_API = {