@logictan/dsh-imagegen 2.0.4 → 2.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/lib/client.js CHANGED
@@ -6,6 +6,7 @@ window.__ModuleLoader__.load({
6
6
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
7
7
  let react = require("react");
8
8
  let _deepseek_ai_dsh_client_store = require("@deepseek-ai/dsh-client-store");
9
+ let _logictan_dsh_plugins_shared_client_client = require("@logictan/dsh-plugins-shared-client/client");
9
10
  let react_jsx_runtime = require("react/jsx-runtime");
10
11
  //#region src/client/locales.ts
11
12
  /**
@@ -420,8 +421,8 @@ window.__ModuleLoader__.load({
420
421
  "settings.addModelConfirm": "添加",
421
422
  "settings.removeModel": "移除模型",
422
423
  "settings.optional": "可选",
423
- "settings.moreOptions": "更多设置",
424
424
  "settings.promptEnhanceTitle": "提示词增强模型",
425
+ "settings.scalarsTitle": "插件开关与对话模型",
425
426
  "settings.promptEnhanceHint": "用于将简短描述扩写为更完整的生图提示词;留空的地址和密钥会复用生图配置。",
426
427
  "settings.promptApiUrl": "对话 API 地址(可选)",
427
428
  "settings.promptApiUrlHint": "OpenAI 兼容基址;留空则复用图像 API 地址。",
@@ -442,9 +443,6 @@ window.__ModuleLoader__.load({
442
443
  "settings.allowAgentImageGenerationHint": "默认开启。关闭后,Agent 无法提交、查询或取消生图任务;侧边栏工作台不受影响。",
443
444
  "settings.enabled": "启用插件",
444
445
  "settings.enabledHint": "关闭后生图面板不可用(设置卡片始终可用)",
445
- "settings.save": "保存",
446
- "settings.saving": "保存中…",
447
- "settings.discard": "放弃修改",
448
446
  "settings.unsaved": "有未保存的修改",
449
447
  "settings.saveFailed": "保存失败,请重试",
450
448
  "settings.readOnly": "当前设置文档为只读,无法保存。",
@@ -1162,8 +1160,8 @@ window.__ModuleLoader__.load({
1162
1160
  "settings.addModelConfirm": "Add",
1163
1161
  "settings.removeModel": "Remove model",
1164
1162
  "settings.optional": "Optional",
1165
- "settings.moreOptions": "More settings",
1166
1163
  "settings.promptEnhanceTitle": "Prompt enhancement model",
1164
+ "settings.scalarsTitle": "Plugin switches and chat model",
1167
1165
  "settings.promptEnhanceHint": "Expands short requests into complete image prompts. Blank URL and key reuse the image API configuration.",
1168
1166
  "settings.promptApiUrl": "Chat API URL (optional)",
1169
1167
  "settings.promptApiUrlHint": "OpenAI-compatible base URL. Leave blank to reuse the image API URL.",
@@ -1184,9 +1182,6 @@ window.__ModuleLoader__.load({
1184
1182
  "settings.allowAgentImageGenerationHint": "On by default. When off, agents cannot submit, query, or cancel image tasks; the sidebar studio remains available.",
1185
1183
  "settings.enabled": "Enable plugin",
1186
1184
  "settings.enabledHint": "When off, the generation studio is unavailable (this card stays available)",
1187
- "settings.save": "Save",
1188
- "settings.saving": "Saving…",
1189
- "settings.discard": "Discard",
1190
1185
  "settings.unsaved": "Unsaved changes",
1191
1186
  "settings.saveFailed": "Save failed, please retry",
1192
1187
  "settings.readOnly": "The settings document is read-only; saving is disabled.",
@@ -1905,8 +1900,8 @@ window.__ModuleLoader__.load({
1905
1900
  "settings.addModelConfirm": "Добавить",
1906
1901
  "settings.removeModel": "Удалить модель",
1907
1902
  "settings.optional": "необязательно",
1908
- "settings.moreOptions": "Дополнительно",
1909
1903
  "settings.promptEnhanceTitle": "Модель улучшения промптов",
1904
+ "settings.scalarsTitle": "Переключатели плагина и модель чата",
1910
1905
  "settings.promptEnhanceHint": "Разворачивает краткое описание в полноценный промпт; пустые адрес и ключ наследуют настройки генерации.",
1911
1906
  "settings.promptApiUrl": "Адрес диалогового API (необязательно)",
1912
1907
  "settings.promptApiUrlHint": "OpenAI-совместимая база; если пусто — используется адрес API генерации.",
@@ -1927,9 +1922,6 @@ window.__ModuleLoader__.load({
1927
1922
  "settings.allowAgentImageGenerationHint": "Включено по умолчанию. Выключено — агенты не могут создавать, смотреть или отменять задачи; боковая панель работает.",
1928
1923
  "settings.enabled": "Включить плагин",
1929
1924
  "settings.enabledHint": "Выключено — панель генерации недоступна (карточка настроек работает всегда)",
1930
- "settings.save": "Сохранить",
1931
- "settings.saving": "Сохраняем…",
1932
- "settings.discard": "Отменить правки",
1933
1925
  "settings.unsaved": "Есть несохранённые правки",
1934
1926
  "settings.saveFailed": "Не удалось сохранить, попробуйте ещё раз",
1935
1927
  "settings.readOnly": "Документ настроек сейчас только для чтения, сохранить нельзя.",
@@ -2332,37 +2324,6 @@ window.__ModuleLoader__.load({
2332
2324
  * pattern the dsh-web-ui family cards use (this package must not depend on a
2333
2325
  * sibling UI package).
2334
2326
  */
2335
- /** A free-text field. An empty draft clears the field. */
2336
- function textField(field) {
2337
- return {
2338
- field,
2339
- format: (value) => typeof value === "string" ? value : "",
2340
- parse: (text) => {
2341
- const trimmed = text.trim();
2342
- return trimmed === "" ? { kind: "clear" } : {
2343
- kind: "set",
2344
- value: trimmed
2345
- };
2346
- }
2347
- };
2348
- }
2349
- /** A boolean field, edited through true/false draft text. */
2350
- function booleanField(field) {
2351
- return {
2352
- field,
2353
- format: (value) => typeof value === "boolean" ? String(value) : "",
2354
- parse: (text) => {
2355
- if (text === "true") return {
2356
- kind: "set",
2357
- value: true
2358
- };
2359
- if (text === "false") return {
2360
- kind: "set",
2361
- value: false
2362
- };
2363
- }
2364
- };
2365
- }
2366
2327
  /**
2367
2328
  * A secret field (role('secret') in the namespace schema). The stored value is
2368
2329
  * never rendered or returned by the redacted wire view, so:
@@ -2455,31 +2416,39 @@ window.__ModuleLoader__.load({
2455
2416
  invalid: write === void 0 && !(spec.secret === true && staged.text.trim() === "")
2456
2417
  };
2457
2418
  }
2458
- /** The actions the card's slot registration injects. */
2419
+ /**
2420
+ * The actions the card's slot registration injects.
2421
+ *
2422
+ * Built once. The slot calls `inject()` on every render, and a fresh object
2423
+ * with fresh closures each time changes the props the renderer subscribed
2424
+ * with, which re-renders forever (React error #185). These closures only ever
2425
+ * capture `this`, so one instance serves every call.
2426
+ */
2427
+ actionSet = {
2428
+ edit: (field, text) => {
2429
+ this.stage(field, {
2430
+ text,
2431
+ clear: false
2432
+ });
2433
+ },
2434
+ resetField: (field) => {
2435
+ this.stage(field, {
2436
+ text: this.specOf(field).format(this.baseValue(field)),
2437
+ clear: true
2438
+ });
2439
+ },
2440
+ save: () => {
2441
+ this.save();
2442
+ },
2443
+ discard: () => {
2444
+ if (this.staged.size === 0 && !this.failed) return;
2445
+ this.staged.clear();
2446
+ this.failed = false;
2447
+ this.publish();
2448
+ }
2449
+ };
2459
2450
  actions() {
2460
- return {
2461
- edit: (field, text) => {
2462
- this.stage(field, {
2463
- text,
2464
- clear: false
2465
- });
2466
- },
2467
- resetField: (field) => {
2468
- this.stage(field, {
2469
- text: this.specOf(field).format(this.baseValue(field)),
2470
- clear: true
2471
- });
2472
- },
2473
- save: () => {
2474
- this.save();
2475
- },
2476
- discard: () => {
2477
- if (this.staged.size === 0 && !this.failed) return;
2478
- this.staged.clear();
2479
- this.failed = false;
2480
- this.publish();
2481
- }
2482
- };
2451
+ return this.actionSet;
2483
2452
  }
2484
2453
  /**
2485
2454
  * Write every staged edit, then re-seed from what the Host accepted.
@@ -2710,36 +2679,44 @@ window.__ModuleLoader__.load({
2710
2679
  failed: this.failed
2711
2680
  };
2712
2681
  }
2713
- /** The actions the card's slot registration injects. */
2682
+ /**
2683
+ * The actions the card's slot registration injects, built once.
2684
+ *
2685
+ * The slot calls `inject()` on every render, and a fresh object with fresh
2686
+ * closures each time changes the props the renderer subscribed with, which
2687
+ * re-renders forever (React error #185). These closures only ever capture
2688
+ * `this`, so one instance serves every call.
2689
+ */
2690
+ actionSet = {
2691
+ setChannels: (channels) => {
2692
+ this.stageChannels(channels);
2693
+ },
2694
+ setChannelKey: (id, value) => {
2695
+ this.stageKey(id, value);
2696
+ },
2697
+ setDefaultChannel: (id) => {
2698
+ this.stagedDefault = id;
2699
+ this.failed = false;
2700
+ this.publish();
2701
+ },
2702
+ setDefaultModel: (model) => {
2703
+ this.stagedDefaultModel = model;
2704
+ this.failed = false;
2705
+ this.publish();
2706
+ },
2707
+ commit: () => this.commit(),
2708
+ discard: () => {
2709
+ if (this.stagedChannels === null && this.stagedKeys.size === 0 && this.stagedDefault === null && this.stagedDefaultModel === null && !this.failed) return;
2710
+ this.stagedChannels = null;
2711
+ this.stagedKeys.clear();
2712
+ this.stagedDefault = null;
2713
+ this.stagedDefaultModel = null;
2714
+ this.failed = false;
2715
+ this.publish();
2716
+ }
2717
+ };
2714
2718
  actions() {
2715
- return {
2716
- setChannels: (channels) => {
2717
- this.stageChannels(channels);
2718
- },
2719
- setChannelKey: (id, value) => {
2720
- this.stageKey(id, value);
2721
- },
2722
- setDefaultChannel: (id) => {
2723
- this.stagedDefault = id;
2724
- this.failed = false;
2725
- this.publish();
2726
- },
2727
- setDefaultModel: (model) => {
2728
- this.stagedDefaultModel = model;
2729
- this.failed = false;
2730
- this.publish();
2731
- },
2732
- commit: () => this.commit(),
2733
- discard: () => {
2734
- if (this.stagedChannels === null && this.stagedKeys.size === 0 && this.stagedDefault === null && this.stagedDefaultModel === null && !this.failed) return;
2735
- this.stagedChannels = null;
2736
- this.stagedKeys.clear();
2737
- this.stagedDefault = null;
2738
- this.stagedDefaultModel = null;
2739
- this.failed = false;
2740
- this.publish();
2741
- }
2742
- };
2719
+ return this.actionSet;
2743
2720
  }
2744
2721
  stageChannels(channels) {
2745
2722
  const cleaned = channels.map(stripChannel);
@@ -3020,7 +2997,7 @@ window.__ModuleLoader__.load({
3020
2997
  }
3021
2998
  //#endregion
3022
2999
  //#region \0dsh-css:/home/runner/work/dsh-plugins/dsh-plugins/packages/dsh-imagegen/src/client/settings-card.module.css.mjs
3023
- const css$1 = "._5JdLea_card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;list-style:none;transition:border-color .16s,background .16s}._5JdLea_card:hover{border-color:var(--dsw-alias-label-dimmed)}._5JdLea_card:has(._5JdLea_body){background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-label-dimmed)}._5JdLea_header{appearance:none;width:100%;font:inherit;color:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:12px;align-items:center;gap:12px;padding:14px 16px;display:flex}._5JdLea_header:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}._5JdLea_headText{flex-direction:column;flex:1;gap:4px;min-width:0;display:flex}._5JdLea_name{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}._5JdLea_description{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}._5JdLea_chevron,._5JdLea_chevronOpen{color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .16s}._5JdLea_chevronOpen{transform:rotate(180deg)}._5JdLea_pending{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;flex:none;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}._5JdLea_body{border-top:1px solid var(--dsw-alias-border-l2);margin:0 16px;padding-bottom:8px}._5JdLea_versionRow{border-bottom:1px solid var(--dsw-alias-border-l2);justify-content:space-between;align-items:center;gap:12px;padding:12px 0;display:flex}._5JdLea_versionLabel{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:500;line-height:1.5}._5JdLea_versionValue{background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);font-family:var(--dsw-font-family-mono,monospace);border-radius:999px;padding:1px 8px;font-size:12px;line-height:1.5}._5JdLea_field{flex-direction:column;gap:6px;padding:12px 0;display:flex}._5JdLea_field+._5JdLea_field{border-top:1px solid var(--dsw-alias-border-l2)}._5JdLea_head{align-items:center;gap:8px;display:flex}._5JdLea_label{min-width:0;color:var(--dsw-alias-label-primary);flex:1;font-size:13px;font-weight:500;line-height:1.5}._5JdLea_badges{align-items:center;gap:8px;display:inline-flex}._5JdLea_badge{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}._5JdLea_reset{font:inherit;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;padding:0;font-size:12px;line-height:1.5}._5JdLea_reset:hover:not(:disabled){color:var(--dsw-alias-label-primary)}._5JdLea_reset:disabled{cursor:default;opacity:.5}._5JdLea_input,._5JdLea_select{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);height:34px;font:inherit;color:var(--dsw-alias-label-primary);border-radius:8px;outline:none;padding:0 12px;font-size:13px;line-height:1.5}._5JdLea_input:focus-visible,._5JdLea_select:focus-visible{border-color:var(--dsw-alias-brand-primary)}._5JdLea_input:disabled,._5JdLea_select:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}._5JdLea_inputInvalid{border:1px solid var(--dsw-alias-label-error);background:var(--dsw-alias-bg-layer-3);height:34px;font:inherit;color:var(--dsw-alias-label-primary);border-radius:8px;outline:none;padding:0 12px;font-size:13px;line-height:1.5}._5JdLea_textarea,._5JdLea_textareaInvalid{resize:vertical;background:var(--dsw-alias-bg-layer-3);min-height:70px;font:inherit;color:var(--dsw-alias-label-primary);border-radius:8px;outline:none;padding:8px 12px;font-size:13px;line-height:1.5}._5JdLea_textarea{border:1px solid var(--dsw-alias-border-l2)}._5JdLea_textareaInvalid{border:1px solid var(--dsw-alias-label-error)}._5JdLea_textarea:focus-visible{border-color:var(--dsw-alias-brand-primary)}._5JdLea_textarea:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}._5JdLea_hint,._5JdLea_invalid{margin:0;font-size:12px;line-height:1.5}._5JdLea_hint{color:var(--dsw-alias-label-tertiary)}._5JdLea_invalid{color:var(--dsw-alias-label-error)}._5JdLea_readOnly,._5JdLea_notExposed{color:var(--dsw-alias-label-tertiary);margin:12px 0 0;font-size:12px;line-height:1.5}._5JdLea_sectionDivider{background:var(--dsw-alias-border-l2);height:1px;margin:18px 0 14px}._5JdLea_sectionTitle{color:var(--dsw-alias-label-primary);margin:0;font-size:14px;line-height:1.4}._5JdLea_sectionHint{color:var(--dsw-alias-label-tertiary);margin:-4px 0 2px;font-size:12px;line-height:1.5}._5JdLea_modelSection{padding:2px 0 14px}._5JdLea_sectionHeader{justify-content:space-between;align-items:flex-start;gap:12px;display:flex}._5JdLea_sectionHeader ._5JdLea_sectionHint{max-width:430px}._5JdLea_modelSummary{flex-wrap:wrap;align-items:center;gap:6px;margin-top:12px;display:flex}._5JdLea_modelChip{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);max-width:100%;color:var(--dsw-alias-label-primary);font-family:var(--dsw-font-family-mono,monospace);border-radius:6px;align-items:center;gap:5px;padding:3px 5px 3px 8px;font-size:12px;line-height:1.5;display:inline-flex}._5JdLea_modelChip>span{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}._5JdLea_modelChip button{appearance:none;width:18px;height:18px;color:var(--dsw-alias-label-tertiary);font:inherit;cursor:pointer;background:0 0;border:0;border-radius:4px;padding:0;line-height:18px}._5JdLea_modelChip button:hover:not(:disabled){color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-module-platform)}._5JdLea_modelChip button:disabled{cursor:default;opacity:.45}._5JdLea_addModel{appearance:none;border:1px dashed var(--dsw-alias-border-l2);min-height:28px;color:var(--dsw-alias-label-secondary);font:inherit;cursor:pointer;background:0 0;border-radius:6px;padding:0 9px;font-size:12px}._5JdLea_addModel:hover:not(:disabled){color:var(--dsw-alias-brand-primary);border-color:var(--dsw-alias-brand-primary)}._5JdLea_addModel:disabled{opacity:.45;cursor:default}._5JdLea_manualModelRow{gap:8px;margin-top:10px;display:flex}._5JdLea_manualModelRow ._5JdLea_input{flex:1;min-width:0}._5JdLea_disclosure{appearance:none;border:0;border-top:1px solid var(--dsw-alias-border-l2);width:100%;color:var(--dsw-alias-label-primary);font:inherit;text-align:left;cursor:pointer;background:0 0;align-items:center;gap:8px;padding:13px 0;font-size:13px;font-weight:500;display:flex}._5JdLea_disclosure>span:nth-child(2){color:var(--dsw-alias-label-tertiary);margin-left:auto;font-size:12px;font-weight:400}._5JdLea_disclosure>span:last-child{color:var(--dsw-alias-label-tertiary)}._5JdLea_disclosure:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}._5JdLea_optionalContent{padding:0 0 8px}._5JdLea_inlineDisclosure{appearance:none;color:var(--dsw-alias-label-secondary);font:inherit;cursor:pointer;background:0 0;border:0;align-items:center;gap:6px;margin-top:12px;padding:0;font-size:12px;display:inline-flex}._5JdLea_inlineDisclosure:hover{color:var(--dsw-alias-label-primary)}._5JdLea_modelFetchRow{align-items:center;gap:8px;display:flex}._5JdLea_modelFetch,._5JdLea_modelChoices{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);min-height:32px;color:var(--dsw-alias-label-secondary);font:inherit;border-radius:7px;font-size:12px}._5JdLea_modelFetch{cursor:pointer;padding:0 10px}._5JdLea_modelFetch:hover:not(:disabled){color:var(--dsw-alias-brand-primary);border-color:var(--dsw-alias-brand-primary)}._5JdLea_modelFetch:disabled{opacity:.5;cursor:default}._5JdLea_modelChoices{flex:1;min-width:0;padding:0 8px}._5JdLea_modelCandidateList{flex-wrap:wrap;gap:6px 10px;margin-top:10px;display:flex}._5JdLea_modelCandidateLabel{width:100%;color:var(--dsw-alias-label-tertiary);font-size:12px}._5JdLea_modelCandidate{appearance:none;min-width:0;color:var(--dsw-alias-label-secondary);cursor:pointer;background:var(--dsw-alias-bg-layer-3);font-size:12px;line-height:1.5;font:inherit;border:1px solid #0000;border-radius:5px;align-items:center;gap:5px;padding:3px 6px;display:inline-flex}._5JdLea_modelCandidate input{margin:0}._5JdLea_modelCandidate[data-selected]{border-color:var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary)}._5JdLea_footer{border-top:1px solid var(--dsw-alias-border-l2);justify-content:flex-end;align-items:center;gap:8px;padding:12px 0 4px;display:flex}._5JdLea_failed{min-width:0;color:var(--dsw-alias-label-error);flex:1;margin:0;font-size:12px;line-height:1.5}._5JdLea_discard,._5JdLea_save{appearance:none;font:inherit;cursor:pointer;border:1px solid #0000;border-radius:8px;padding:5px 14px;font-size:13px;line-height:1.5}._5JdLea_discard{border-color:var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);background:0 0}._5JdLea_discard:hover:not(:disabled){color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-dimmed)}._5JdLea_save{background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-layer-3)}._5JdLea_discard:disabled,._5JdLea_save:disabled{opacity:.4;cursor:default}._5JdLea_discard:focus-visible,._5JdLea_save:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}@media (prefers-reduced-motion:reduce){._5JdLea_card,._5JdLea_chevron,._5JdLea_chevronOpen{transition:none}}._5JdLea_channelSection{padding:6px 0 2px}._5JdLea_channelEmpty{color:var(--dsw-alias-label-tertiary);margin:10px 0 0;font-size:12px;line-height:1.5}._5JdLea_channelList{flex-direction:column;gap:6px;margin:10px 0 0;padding:0;list-style:none;display:flex}._5JdLea_channelRow{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:10px;align-items:center;gap:10px;padding:8px 10px;display:flex}._5JdLea_channelRow[data-action]{flex-wrap:wrap}._5JdLea_channelDotReady,._5JdLea_channelDotWarn{border-radius:50%;flex:none;width:9px;height:9px}._5JdLea_channelDotReady{background:var(--dsw-color-success,#2fbf71)}._5JdLea_channelDotWarn{background:var(--dsw-color-danger,#e5484d)}._5JdLea_channelMain{appearance:none;min-width:0;font:inherit;text-align:left;cursor:pointer;background:0 0;border:0;flex-direction:column;flex:1;gap:3px;padding:0;display:flex}._5JdLea_channelName{color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;font-size:13px;font-weight:600;line-height:1.4;overflow:hidden}._5JdLea_channelMeta{flex-wrap:wrap;align-items:center;gap:4px 8px;display:flex}._5JdLea_channelHost{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:1.5;font-family:var(--dsw-font-family-mono,monospace);text-overflow:ellipsis;white-space:nowrap;max-width:180px;overflow:hidden}._5JdLea_channelBadge{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;padding:0 7px;font-size:11px;font-weight:500;line-height:17px}._5JdLea_channelBadge[data-warn]{color:var(--dsw-alias-label-error)}._5JdLea_channelBadge[data-default]{background:var(--dsw-alias-bg-module-poped,var(--dsw-alias-bg-module-platform));color:var(--dsw-alias-brand-primary)}._5JdLea_channelAction{appearance:none;font:inherit;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:0;border-radius:6px;flex:none;padding:4px 8px;font-size:12px;line-height:1.5}._5JdLea_channelAction:hover:not(:disabled){color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-module-platform)}._5JdLea_channelAction[data-danger]{color:var(--dsw-alias-label-error)}._5JdLea_channelAction:disabled{opacity:.45;cursor:default}._5JdLea_channelDanger{appearance:none;border:1px solid var(--dsw-alias-label-error);color:var(--dsw-alias-label-error);font:inherit;cursor:pointer;background:0 0;border-radius:6px;flex:none;padding:3px 10px;font-size:12px}._5JdLea_channelDanger:hover:not(:disabled){background:color-mix(in srgb, var(--dsw-alias-label-error) 12%, transparent)}._5JdLea_channelDanger:disabled{opacity:.45;cursor:default}._5JdLea_deleteConfirmText{min-width:0;color:var(--dsw-alias-label-error);flex:1;font-size:12px;line-height:1.5}._5JdLea_defaultModelRow{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:10px;align-items:center;gap:12px;margin-top:12px;padding:10px 12px;display:flex}._5JdLea_defaultModelRow label{flex:1;min-width:0}._5JdLea_defaultModelRow strong,._5JdLea_defaultModelRow small{display:block}._5JdLea_defaultModelRow strong{color:var(--dsw-alias-label-primary);font-size:12px}._5JdLea_defaultModelRow small{color:var(--dsw-alias-label-tertiary);margin-top:3px;font-size:11px;line-height:1.4}._5JdLea_defaultModelRow select{width:min(260px,48%)}._5JdLea_channelAddRow{gap:8px;margin-top:10px;display:flex}._5JdLea_channelAdd{appearance:none;border:1px dashed var(--dsw-alias-border-l2);min-height:30px;color:var(--dsw-alias-label-secondary);font:inherit;cursor:pointer;background:0 0;border-radius:8px;padding:0 12px;font-size:12px}._5JdLea_channelAdd:hover:not(:disabled){color:var(--dsw-alias-brand-primary);border-color:var(--dsw-alias-brand-primary)}._5JdLea_channelAdd:disabled{opacity:.45;cursor:default}._5JdLea_spacer{flex:1}._5JdLea_editorBackdrop{z-index:120;background:color-mix(in srgb, var(--dsw-alias-bg-layer-1,#000) 45%, transparent);justify-content:center;align-items:flex-start;padding:9vh 16px 16px;display:flex;position:fixed;inset:0}._5JdLea_editorPanel{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);border-radius:14px;width:min(560px,100%);max-height:82vh;padding:16px;overflow-y:auto;box-shadow:0 18px 50px #00000059}._5JdLea_editorHeader{border-bottom:1px solid var(--dsw-alias-border-l2);justify-content:space-between;align-items:flex-start;gap:12px;padding-bottom:10px;display:flex}._5JdLea_editorClose{appearance:none;width:26px;height:26px;color:var(--dsw-alias-label-tertiary);font:inherit;cursor:pointer;background:0 0;border:0;border-radius:6px;flex:none;font-size:16px;line-height:26px}._5JdLea_editorClose:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-module-platform)}._5JdLea_editorField{flex-direction:column;gap:6px;padding:12px 0 0;display:flex}._5JdLea_checkboxRow{color:var(--dsw-alias-label-secondary);cursor:pointer;align-items:center;gap:7px;font-size:12px;line-height:1.5;display:inline-flex}._5JdLea_checkboxRow input{margin:0}._5JdLea_fieldHint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:11.5px;line-height:1.5}._5JdLea_editorDivider{background:var(--dsw-alias-border-l2);height:1px;margin:14px 0 4px}._5JdLea_editorSectionHeader{justify-content:space-between;align-items:center;gap:12px;padding:10px 0 4px;display:flex}._5JdLea_editorSectionHeader ._5JdLea_label{flex:1}._5JdLea_editorTools{flex-direction:column;gap:8px;margin-top:10px;display:flex}._5JdLea_editorFooter{border-top:1px solid var(--dsw-alias-border-l2);align-items:center;gap:8px;padding-top:12px;display:flex}._5JdLea_detectOk{color:var(--dsw-color-success,var(--dsw-alias-label-secondary));margin:0;font-size:12px;line-height:1.5}._5JdLea_modelRows{flex-direction:column;gap:8px;margin:8px 0 0;padding:0;list-style:none;display:flex}._5JdLea_modelRow{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:10px;justify-content:space-between;align-items:center;gap:10px;padding:8px 10px;display:flex}._5JdLea_modelRowInputs{flex:1;align-items:center;gap:6px;min-width:0;display:flex}._5JdLea_modelRowInputs ._5JdLea_input{flex:1;min-width:0}._5JdLea_modelArrow{color:var(--dsw-alias-label-tertiary);flex:none;font-size:12px}._5JdLea_modelRowBadges{flex:none;align-items:center;gap:6px;display:flex}._5JdLea_modelBadge{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-tertiary);border-radius:999px;padding:0 7px;font-size:11px;line-height:17px}._5JdLea_modelBadge[data-verified]{color:var(--dsw-color-success,var(--dsw-alias-label-secondary))}._5JdLea_modelBadge[data-warn]{color:var(--dsw-alias-label-error)}._5JdLea_modelRowRemove{appearance:none;width:20px;height:20px;color:var(--dsw-alias-label-tertiary);font:inherit;cursor:pointer;background:0 0;border:0;border-radius:4px;flex:none;padding:0;line-height:20px}._5JdLea_modelRowRemove:hover:not(:disabled){color:var(--dsw-alias-label-error);background:var(--dsw-alias-bg-module-platform)}._5JdLea_modelRowRemove:disabled{opacity:.45;cursor:default}._5JdLea_modelCandidate>._5JdLea_modelBadge{flex:none}._5JdLea_channelControls{position:relative}._5JdLea_presetInline{z-index:10;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);border-radius:10px;width:min(420px,100vw - 48px);max-height:min(440px,60vh);margin:0;padding:12px;position:absolute;bottom:calc(100% + 8px);left:0;overflow-y:auto;box-shadow:0 12px 30px #0000004d}._5JdLea_presetInlineHeader{justify-content:space-between;align-items:flex-start;gap:12px;display:flex}._5JdLea_presetList{flex-direction:column;gap:8px;margin-top:12px;display:flex}._5JdLea_presetRow{appearance:none;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);width:100%;color:inherit;font:inherit;text-align:left;cursor:pointer;border-radius:10px;flex-direction:column;align-items:flex-start;gap:3px;padding:10px 12px;display:flex}._5JdLea_presetRow:hover:not(:disabled){border-color:var(--dsw-alias-brand-primary)}._5JdLea_presetRow[data-custom]{border-style:dashed}._5JdLea_presetRow:disabled{opacity:.5;cursor:default}._5JdLea_presetName{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:600;line-height:1.4}._5JdLea_presetMeta{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:1.5;font-family:var(--dsw-font-family-mono,monospace)}._5JdLea_presetHint{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.5}._5JdLea_overview{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;margin:12px 0 14px;padding:14px}._5JdLea_overviewHead{justify-content:space-between;align-items:flex-start;gap:12px;display:flex}._5JdLea_overviewTitle{color:var(--dsw-alias-label-primary);margin:0;font-size:14px;line-height:1.4}._5JdLea_overviewHint{color:var(--dsw-alias-label-tertiary);margin:4px 0 0;font-size:11.5px;line-height:1.5}._5JdLea_healthBadge,._5JdLea_sectionSummary{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;flex:none;padding:2px 8px;font-size:11px;line-height:17px}._5JdLea_healthBadge[data-state=ready],._5JdLea_sectionSummary[data-tone=ready]{color:var(--dsw-color-success,var(--dsw-alias-label-secondary))}._5JdLea_healthBadge[data-state=attention],._5JdLea_sectionSummary[data-tone=attention]{color:var(--dsw-alias-label-error)}._5JdLea_summaryGrid{grid-template-columns:repeat(2,minmax(0,1fr));gap:8px;margin-top:12px;display:grid}._5JdLea_summaryCard{appearance:none;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);min-width:0;min-height:58px;color:inherit;font:inherit;text-align:left;cursor:pointer;border-radius:10px;flex-direction:column;justify-content:center;align-items:flex-start;gap:4px;padding:9px 10px;transition:border-color .16s,background .16s;display:flex}._5JdLea_summaryCard:hover,._5JdLea_summaryCard[data-active]{border-color:var(--dsw-alias-brand-primary)}._5JdLea_summaryCard[data-tone=ready]{background:color-mix(in srgb, var(--dsw-color-success,var(--dsw-alias-brand-primary)) 7%, var(--dsw-alias-bg-layer-2))}._5JdLea_summaryCard[data-tone=attention]{background:color-mix(in srgb, var(--dsw-alias-label-error) 6%, var(--dsw-alias-bg-layer-2))}._5JdLea_summaryLabel{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:1.4}._5JdLea_summaryValue{max-width:100%;color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;font-size:12.5px;font-weight:600;line-height:1.4;overflow:hidden}._5JdLea_settingsSection{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;margin-top:10px;overflow:clip}._5JdLea_settingsSection[data-open]{border-color:var(--dsw-alias-label-dimmed);background:var(--dsw-alias-bg-layer-2)}._5JdLea_sectionToggle{appearance:none;width:100%;color:inherit;font:inherit;text-align:left;cursor:pointer;background:0 0;border:0;grid-template-columns:minmax(0,1fr) auto auto;align-items:center;gap:10px;padding:12px 13px;display:grid}._5JdLea_sectionToggle:hover{background:color-mix(in srgb, var(--dsw-alias-bg-module-platform) 45%, transparent)}._5JdLea_sectionToggle:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}._5JdLea_sectionToggleText{flex-direction:column;gap:3px;min-width:0;display:flex}._5JdLea_sectionToggleTitle{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:600;line-height:1.4}._5JdLea_sectionToggleHint{color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;font-size:11.5px;line-height:1.45;overflow:hidden}._5JdLea_sectionChevron{width:18px;color:var(--dsw-alias-label-tertiary);text-align:center;flex:none;font-size:12px}._5JdLea_sectionContent{border-top:1px solid var(--dsw-alias-border-l2);padding:0 13px 13px}._5JdLea_footer{z-index:4;background:color-mix(in srgb, var(--dsw-alias-bg-layer-2) 94%, transparent);backdrop-filter:blur(12px);margin:14px -16px 0;padding:12px 16px 10px;position:sticky;bottom:-8px}._5JdLea_pickerOverlay{z-index:1000;background:#0000006b;place-items:center;padding:24px;display:grid;position:fixed;inset:0}._5JdLea_pickerDialog{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);border-radius:14px;flex-direction:column;width:min(540px,100vw - 32px);max-height:min(720px,84vh);padding:16px;display:flex;overflow:hidden;box-shadow:0 18px 50px #00000059}._5JdLea_pickerHeader{border-bottom:1px solid var(--dsw-alias-border-l2);justify-content:space-between;align-items:flex-start;gap:12px;padding-bottom:12px;display:flex}._5JdLea_pickerTitle{color:var(--dsw-alias-label-primary);margin:0;font-size:15px;line-height:1.4}._5JdLea_pickerHint{color:var(--dsw-alias-label-tertiary);margin:4px 0 0;font-size:12px;line-height:1.5}._5JdLea_pickerSearch{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);height:34px;color:var(--dsw-alias-label-primary);font:inherit;border-radius:8px;outline:none;flex:none;margin:12px 0 10px;padding:0 11px;font-size:13px}._5JdLea_pickerSearch:focus-visible{border-color:var(--dsw-alias-brand-primary)}._5JdLea_pickerList{flex-direction:column;gap:8px;min-height:0;padding:2px 2px 4px;display:flex;overflow-y:auto}._5JdLea_pickerList ._5JdLea_presetRow{flex:none;min-height:54px}._5JdLea_pickerEmpty{color:var(--dsw-alias-label-tertiary);text-align:center;margin:16px 0;font-size:12px;line-height:1.5}@media (width<=520px){._5JdLea_overviewHead{flex-direction:column}._5JdLea_sectionToggle{grid-template-columns:minmax(0,1fr) auto}._5JdLea_sectionToggle ._5JdLea_sectionSummary{grid-column:1/-1;justify-self:start}._5JdLea_summaryGrid{grid-template-columns:minmax(0,1fr)}}._5JdLea_subscriptionBox{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:11px;margin-top:12px;padding:12px}._5JdLea_subscriptionAccount{align-items:center;gap:9px;display:flex}._5JdLea_subscriptionAccount>div{flex-direction:column;gap:2px;min-width:0;display:flex}._5JdLea_subscriptionAccount strong{color:var(--dsw-alias-label-primary);font-size:13px;line-height:1.4}._5JdLea_subscriptionAccount small{color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;font-size:11.5px;line-height:1.45;overflow:hidden}._5JdLea_subscriptionDot{background:var(--dsw-alias-label-tertiary);border-radius:50%;flex:none;width:8px;height:8px}._5JdLea_subscriptionDot[data-state=logged-in]{background:var(--dsw-color-success,#3fb950)}._5JdLea_subscriptionDot[data-state=logged-out]{background:var(--dsw-alias-label-error)}._5JdLea_subscriptionWarning{background:color-mix(in srgb, var(--dsw-alias-label-error) 7%, transparent);color:var(--dsw-alias-label-secondary);border-radius:7px;margin:9px 0 0;padding:7px 9px;font-size:11.5px;line-height:1.5}._5JdLea_pickerTabs{background:var(--dsw-alias-bg-layer-3);border-radius:9px;flex:none;grid-template-columns:repeat(2,minmax(0,1fr));gap:4px;margin-top:12px;padding:3px;display:grid}._5JdLea_pickerTabs button{appearance:none;min-height:30px;color:var(--dsw-alias-label-secondary);font:inherit;cursor:pointer;background:0 0;border:0;border-radius:7px;font-size:12px}._5JdLea_pickerTabs button[data-active]{background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);box-shadow:0 1px 2px #00000014}._5JdLea_presetAction{color:var(--dsw-alias-brand-primary);flex:none;margin-left:auto;font-size:11px;line-height:1.5}._5JdLea_subscriptionManual{border-top:1px dashed var(--dsw-alias-border-l2);margin-top:10px;padding-top:10px}";
3000
+ const css$1 = "._5JdLea_card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;list-style:none;transition:border-color .16s,background .16s}._5JdLea_card:hover{border-color:var(--dsw-alias-label-dimmed)}._5JdLea_card:has(._5JdLea_body){background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-label-dimmed)}._5JdLea_header{appearance:none;width:100%;font:inherit;color:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:12px;align-items:center;gap:12px;padding:14px 16px;display:flex}._5JdLea_header:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}._5JdLea_headText{flex-direction:column;flex:1;gap:4px;min-width:0;display:flex}._5JdLea_name{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}._5JdLea_description{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}._5JdLea_chevron,._5JdLea_chevronOpen{color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .16s}._5JdLea_chevronOpen{transform:rotate(180deg)}._5JdLea_pending{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;flex:none;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}._5JdLea_body{border-top:1px solid var(--dsw-alias-border-l2);margin:0 16px;padding-bottom:8px}._5JdLea_field{flex-direction:column;gap:6px;padding:12px 0;display:flex}._5JdLea_field+._5JdLea_field{border-top:1px solid var(--dsw-alias-border-l2)}._5JdLea_head{align-items:center;gap:8px;display:flex}._5JdLea_label{min-width:0;color:var(--dsw-alias-label-primary);flex:1;font-size:13px;font-weight:500;line-height:1.5}._5JdLea_badges{align-items:center;gap:8px;display:inline-flex}._5JdLea_reset{font:inherit;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;padding:0;font-size:12px;line-height:1.5}._5JdLea_reset:hover:not(:disabled){color:var(--dsw-alias-label-primary)}._5JdLea_reset:disabled{cursor:default;opacity:.5}._5JdLea_hint,._5JdLea_invalid{margin:0;font-size:12px;line-height:1.5}._5JdLea_hint{color:var(--dsw-alias-label-tertiary)}._5JdLea_invalid{color:var(--dsw-alias-label-error)}._5JdLea_readOnly,._5JdLea_notExposed{color:var(--dsw-alias-label-tertiary);margin:12px 0 0;font-size:12px;line-height:1.5}._5JdLea_sectionTitle{color:var(--dsw-alias-label-primary);margin:0;font-size:14px;line-height:1.4}._5JdLea_sectionHint{color:var(--dsw-alias-label-tertiary);margin:-4px 0 2px;font-size:12px;line-height:1.5}._5JdLea_sectionHeader{justify-content:space-between;align-items:flex-start;gap:12px;display:flex}._5JdLea_sectionHeader ._5JdLea_sectionHint{max-width:430px}._5JdLea_modelSummary{flex-wrap:wrap;align-items:center;gap:6px;margin-top:12px;display:flex}._5JdLea_modelChip{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);max-width:100%;color:var(--dsw-alias-label-primary);font-family:var(--dsw-font-family-mono,monospace);border-radius:6px;align-items:center;gap:5px;padding:3px 5px 3px 8px;font-size:12px;line-height:1.5;display:inline-flex}._5JdLea_modelChip>span{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}._5JdLea_modelChip button{appearance:none;width:18px;height:18px;color:var(--dsw-alias-label-tertiary);font:inherit;cursor:pointer;background:0 0;border:0;border-radius:4px;padding:0;line-height:18px}._5JdLea_modelChip button:hover:not(:disabled){color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-module-platform)}._5JdLea_modelChip button:disabled{cursor:default;opacity:.45}._5JdLea_manualModelRow{gap:8px;margin-top:10px;display:flex}._5JdLea_disclosure{appearance:none;border:0;border-top:1px solid var(--dsw-alias-border-l2);width:100%;color:var(--dsw-alias-label-primary);font:inherit;text-align:left;cursor:pointer;background:0 0;align-items:center;gap:8px;padding:13px 0;font-size:13px;font-weight:500;display:flex}._5JdLea_disclosure>span:nth-child(2){color:var(--dsw-alias-label-tertiary);margin-left:auto;font-size:12px;font-weight:400}._5JdLea_disclosure>span:last-child{color:var(--dsw-alias-label-tertiary)}._5JdLea_disclosure:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}._5JdLea_optionalContent{padding:0 0 8px}._5JdLea_inlineDisclosure{appearance:none;color:var(--dsw-alias-label-secondary);font:inherit;cursor:pointer;background:0 0;border:0;align-items:center;gap:6px;margin-top:12px;padding:0;font-size:12px;display:inline-flex}._5JdLea_inlineDisclosure:hover{color:var(--dsw-alias-label-primary)}._5JdLea_modelCandidateList{flex-wrap:wrap;gap:6px 10px;margin-top:10px;display:flex}._5JdLea_modelCandidateLabel{width:100%;color:var(--dsw-alias-label-tertiary);font-size:12px}._5JdLea_modelCandidate{appearance:none;min-width:0;color:var(--dsw-alias-label-secondary);cursor:pointer;background:var(--dsw-alias-bg-layer-3);font-size:12px;line-height:1.5;font:inherit;border:1px solid #0000;border-radius:5px;align-items:center;gap:5px;padding:3px 6px;display:inline-flex}._5JdLea_modelCandidate[data-selected]{border-color:var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary)}._5JdLea_footer{border-top:1px solid var(--dsw-alias-border-l2);justify-content:flex-end;align-items:center;gap:8px;padding:12px 0 4px;display:flex}._5JdLea_failed{min-width:0;color:var(--dsw-alias-label-error);flex:1;margin:0;font-size:12px;line-height:1.5}@media (prefers-reduced-motion:reduce){._5JdLea_card,._5JdLea_chevron,._5JdLea_chevronOpen{transition:none}}._5JdLea_channelSection,._5JdLea_schemaSection{padding:6px 0 2px}._5JdLea_schemaSection>section{background:0 0;border:0;padding:0}._5JdLea_channelEmpty{color:var(--dsw-alias-label-tertiary);margin:10px 0 0;font-size:12px;line-height:1.5}._5JdLea_channelList{flex-direction:column;gap:6px;margin:10px 0 0;padding:0;list-style:none;display:flex}._5JdLea_channelRow{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:10px;align-items:center;gap:10px;padding:8px 10px;display:flex}._5JdLea_channelRow[data-action]{flex-wrap:wrap}._5JdLea_channelMain{appearance:none;min-width:0;font:inherit;text-align:left;cursor:pointer;background:0 0;border:0;flex-direction:column;flex:1;gap:3px;padding:0;display:flex}._5JdLea_channelName{color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;font-size:13px;font-weight:600;line-height:1.4;overflow:hidden}._5JdLea_channelMeta{flex-wrap:wrap;align-items:center;gap:4px 8px;display:flex}._5JdLea_deleteConfirmText{min-width:0;color:var(--dsw-alias-label-error);flex:1;font-size:12px;line-height:1.5}._5JdLea_channelAddRow{gap:8px;margin-top:10px;display:flex}._5JdLea_spacer{flex:1}._5JdLea_editorBackdrop{z-index:120;background:color-mix(in srgb, var(--dsw-alias-bg-layer-1,#000) 45%, transparent);justify-content:center;align-items:flex-start;padding:9vh 16px 16px;display:flex;position:fixed;inset:0}._5JdLea_editorPanel{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);border-radius:14px;width:min(560px,100%);max-height:82vh;padding:16px;overflow-y:auto;box-shadow:0 18px 50px #00000059}._5JdLea_editorHeader{border-bottom:1px solid var(--dsw-alias-border-l2);justify-content:space-between;align-items:flex-start;gap:12px;padding-bottom:10px;display:flex}._5JdLea_editorClose{appearance:none;width:26px;height:26px;color:var(--dsw-alias-label-tertiary);font:inherit;cursor:pointer;background:0 0;border:0;border-radius:6px;flex:none;font-size:16px;line-height:26px}._5JdLea_editorClose:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-module-platform)}._5JdLea_editorField{flex-direction:column;gap:6px;padding:12px 0 0;display:flex}._5JdLea_editorDivider{background:var(--dsw-alias-border-l2);height:1px;margin:14px 0 4px}._5JdLea_editorSectionHeader{justify-content:space-between;align-items:center;gap:12px;padding:10px 0 4px;display:flex}._5JdLea_editorSectionHeader ._5JdLea_label{flex:1}._5JdLea_editorTools{flex-direction:column;gap:8px;margin-top:10px;display:flex}._5JdLea_editorFooter{border-top:1px solid var(--dsw-alias-border-l2);align-items:center;gap:8px;padding-top:12px;display:flex}._5JdLea_detectOk{color:var(--dsw-color-success,var(--dsw-alias-label-secondary));margin:0;font-size:12px;line-height:1.5}._5JdLea_modelRows{flex-direction:column;gap:8px;margin:8px 0 0;padding:0;list-style:none;display:flex}._5JdLea_modelRow{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:10px;justify-content:space-between;align-items:center;gap:10px;padding:8px 10px;display:flex}._5JdLea_modelRowInputs{flex:1;align-items:center;gap:6px;min-width:0;display:flex}._5JdLea_modelArrow{color:var(--dsw-alias-label-tertiary);flex:none;font-size:12px}._5JdLea_modelRowBadges{flex:none;align-items:center;gap:6px;display:flex}._5JdLea_modelRowRemove{appearance:none;width:20px;height:20px;color:var(--dsw-alias-label-tertiary);font:inherit;cursor:pointer;background:0 0;border:0;border-radius:4px;flex:none;padding:0;line-height:20px}._5JdLea_modelRowRemove:hover:not(:disabled){color:var(--dsw-alias-label-error);background:var(--dsw-alias-bg-module-platform)}._5JdLea_modelRowRemove:disabled{opacity:.45;cursor:default}._5JdLea_channelControls{position:relative}._5JdLea_presetInline{z-index:10;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);border-radius:10px;width:min(420px,100vw - 48px);max-height:min(440px,60vh);margin:0;padding:12px;position:absolute;bottom:calc(100% + 8px);left:0;overflow-y:auto;box-shadow:0 12px 30px #0000004d}._5JdLea_presetInlineHeader{justify-content:space-between;align-items:flex-start;gap:12px;display:flex}._5JdLea_presetList{flex-direction:column;gap:8px;margin-top:12px;display:flex}._5JdLea_presetRow{appearance:none;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);width:100%;color:inherit;font:inherit;text-align:left;cursor:pointer;border-radius:10px;flex-direction:column;align-items:flex-start;gap:3px;padding:10px 12px;display:flex}._5JdLea_presetRow:hover:not(:disabled){border-color:var(--dsw-alias-brand-primary)}._5JdLea_presetRow[data-custom]{border-style:dashed}._5JdLea_presetRow:disabled{opacity:.5;cursor:default}._5JdLea_presetName{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:600;line-height:1.4}._5JdLea_presetMeta{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:1.5;font-family:var(--dsw-font-family-mono,monospace)}._5JdLea_presetHint{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.5}";
3024
3001
  const tagId$1 = "@logictan/dsh-imagegen/settings-card.module.css";
3025
3002
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
3026
3003
  const tag = document.createElement("style");
@@ -3030,132 +3007,73 @@ window.__ModuleLoader__.load({
3030
3007
  document.head.appendChild(tag);
3031
3008
  }
3032
3009
  var settings_card_module_css_default = {
3033
- "modelRow": "_5JdLea_modelRow",
3034
- "overviewHead": "_5JdLea_overviewHead",
3035
- "versionLabel": "_5JdLea_versionLabel",
3036
- "reset": "_5JdLea_reset",
3037
- "summaryCard": "_5JdLea_summaryCard",
3038
- "footer": "_5JdLea_footer",
3039
- "channelMeta": "_5JdLea_channelMeta",
3040
- "channelName": "_5JdLea_channelName",
3041
- "channelAdd": "_5JdLea_channelAdd",
3042
- "subscriptionWarning": "_5JdLea_subscriptionWarning",
3043
- "manualModelRow": "_5JdLea_manualModelRow",
3044
- "modelCandidateList": "_5JdLea_modelCandidateList",
3045
- "channelMain": "_5JdLea_channelMain",
3046
- "field": "_5JdLea_field",
3047
- "header": "_5JdLea_header",
3048
- "channelDotReady": "_5JdLea_channelDotReady",
3049
- "presetRow": "_5JdLea_presetRow",
3050
- "pickerEmpty": "_5JdLea_pickerEmpty",
3051
- "editorPanel": "_5JdLea_editorPanel",
3052
- "pending": "_5JdLea_pending",
3053
- "name": "_5JdLea_name",
3054
- "pickerHeader": "_5JdLea_pickerHeader",
3010
+ "badges": "_5JdLea_badges",
3011
+ "failed": "_5JdLea_failed",
3012
+ "deleteConfirmText": "_5JdLea_deleteConfirmText",
3013
+ "channelRow": "_5JdLea_channelRow",
3014
+ "presetInlineHeader": "_5JdLea_presetInlineHeader",
3055
3015
  "editorTools": "_5JdLea_editorTools",
3016
+ "chevron": "_5JdLea_chevron",
3056
3017
  "modelRowRemove": "_5JdLea_modelRowRemove",
3057
- "presetMeta": "_5JdLea_presetMeta",
3058
- "editorSectionHeader": "_5JdLea_editorSectionHeader",
3059
- "subscriptionManual": "_5JdLea_subscriptionManual",
3060
- "sectionTitle": "_5JdLea_sectionTitle",
3061
- "fieldHint": "_5JdLea_fieldHint",
3062
- "channelAction": "_5JdLea_channelAction",
3063
- "channelAddRow": "_5JdLea_channelAddRow",
3064
- "inputInvalid": "_5JdLea_inputInvalid",
3065
- "sectionHeader": "_5JdLea_sectionHeader",
3066
3018
  "inlineDisclosure": "_5JdLea_inlineDisclosure",
3067
3019
  "editorBackdrop": "_5JdLea_editorBackdrop",
3068
- "presetInline": "_5JdLea_presetInline",
3069
- "versionRow": "_5JdLea_versionRow",
3070
- "overviewTitle": "_5JdLea_overviewTitle",
3020
+ "sectionHint": "_5JdLea_sectionHint",
3021
+ "editorPanel": "_5JdLea_editorPanel",
3022
+ "channelMeta": "_5JdLea_channelMeta",
3023
+ "chevronOpen": "_5JdLea_chevronOpen",
3024
+ "headText": "_5JdLea_headText",
3025
+ "footer": "_5JdLea_footer",
3026
+ "editorField": "_5JdLea_editorField",
3027
+ "modelRow": "_5JdLea_modelRow",
3071
3028
  "disclosure": "_5JdLea_disclosure",
3029
+ "presetMeta": "_5JdLea_presetMeta",
3030
+ "editorDivider": "_5JdLea_editorDivider",
3031
+ "presetInline": "_5JdLea_presetInline",
3032
+ "name": "_5JdLea_name",
3072
3033
  "invalid": "_5JdLea_invalid",
3073
- "notExposed": "_5JdLea_notExposed",
3074
- "modelRows": "_5JdLea_modelRows",
3075
- "subscriptionDot": "_5JdLea_subscriptionDot",
3076
- "channelSection": "_5JdLea_channelSection",
3077
- "versionValue": "_5JdLea_versionValue",
3078
- "modelSection": "_5JdLea_modelSection",
3079
- "settingsSection": "_5JdLea_settingsSection",
3080
- "pickerHint": "_5JdLea_pickerHint",
3081
- "hint": "_5JdLea_hint",
3082
- "spacer": "_5JdLea_spacer",
3083
- "readOnly": "_5JdLea_readOnly",
3084
- "label": "_5JdLea_label",
3085
- "detectOk": "_5JdLea_detectOk",
3086
- "sectionSummary": "_5JdLea_sectionSummary",
3087
- "summaryValue": "_5JdLea_summaryValue",
3034
+ "reset": "_5JdLea_reset",
3088
3035
  "presetName": "_5JdLea_presetName",
3089
- "editorHeader": "_5JdLea_editorHeader",
3090
- "defaultModelRow": "_5JdLea_defaultModelRow",
3091
- "headText": "_5JdLea_headText",
3092
- "editorFooter": "_5JdLea_editorFooter",
3093
- "pickerTitle": "_5JdLea_pickerTitle",
3094
- "pickerSearch": "_5JdLea_pickerSearch",
3095
- "pickerDialog": "_5JdLea_pickerDialog",
3096
- "pickerTabs": "_5JdLea_pickerTabs",
3097
- "description": "_5JdLea_description",
3098
- "presetAction": "_5JdLea_presetAction",
3099
- "summaryLabel": "_5JdLea_summaryLabel",
3100
- "head": "_5JdLea_head",
3101
- "channelBadge": "_5JdLea_channelBadge",
3102
- "overview": "_5JdLea_overview",
3103
- "sectionDivider": "_5JdLea_sectionDivider",
3104
- "editorDivider": "_5JdLea_editorDivider",
3105
- "sectionToggle": "_5JdLea_sectionToggle",
3106
- "modelRowInputs": "_5JdLea_modelRowInputs",
3107
- "subscriptionAccount": "_5JdLea_subscriptionAccount",
3108
- "sectionToggleText": "_5JdLea_sectionToggleText",
3109
- "editorField": "_5JdLea_editorField",
3110
- "save": "_5JdLea_save",
3111
3036
  "card": "_5JdLea_card",
3112
- "badge": "_5JdLea_badge",
3113
- "modelSummary": "_5JdLea_modelSummary",
3114
- "badges": "_5JdLea_badges",
3115
- "modelRowBadges": "_5JdLea_modelRowBadges",
3116
- "failed": "_5JdLea_failed",
3037
+ "description": "_5JdLea_description",
3038
+ "channelEmpty": "_5JdLea_channelEmpty",
3117
3039
  "channelList": "_5JdLea_channelList",
3118
- "modelFetch": "_5JdLea_modelFetch",
3040
+ "header": "_5JdLea_header",
3041
+ "modelCandidateLabel": "_5JdLea_modelCandidateLabel",
3042
+ "editorSectionHeader": "_5JdLea_editorSectionHeader",
3043
+ "detectOk": "_5JdLea_detectOk",
3044
+ "modelArrow": "_5JdLea_modelArrow",
3045
+ "modelRowBadges": "_5JdLea_modelRowBadges",
3046
+ "presetRow": "_5JdLea_presetRow",
3119
3047
  "presetHint": "_5JdLea_presetHint",
3120
- "checkboxRow": "_5JdLea_checkboxRow",
3121
- "sectionToggleTitle": "_5JdLea_sectionToggleTitle",
3122
- "deleteConfirmText": "_5JdLea_deleteConfirmText",
3123
- "presetList": "_5JdLea_presetList",
3048
+ "manualModelRow": "_5JdLea_manualModelRow",
3049
+ "notExposed": "_5JdLea_notExposed",
3050
+ "hint": "_5JdLea_hint",
3051
+ "channelMain": "_5JdLea_channelMain",
3052
+ "body": "_5JdLea_body",
3053
+ "optionalContent": "_5JdLea_optionalContent",
3054
+ "channelSection": "_5JdLea_channelSection",
3055
+ "editorFooter": "_5JdLea_editorFooter",
3056
+ "modelRowInputs": "_5JdLea_modelRowInputs",
3057
+ "head": "_5JdLea_head",
3058
+ "pending": "_5JdLea_pending",
3059
+ "editorHeader": "_5JdLea_editorHeader",
3124
3060
  "channelControls": "_5JdLea_channelControls",
3125
- "discard": "_5JdLea_discard",
3126
- "channelDanger": "_5JdLea_channelDanger",
3127
- "healthBadge": "_5JdLea_healthBadge",
3128
- "textareaInvalid": "_5JdLea_textareaInvalid",
3129
- "chevron": "_5JdLea_chevron",
3130
- "sectionContent": "_5JdLea_sectionContent",
3131
- "presetInlineHeader": "_5JdLea_presetInlineHeader",
3061
+ "channelName": "_5JdLea_channelName",
3062
+ "readOnly": "_5JdLea_readOnly",
3132
3063
  "modelCandidate": "_5JdLea_modelCandidate",
3133
- "subscriptionBox": "_5JdLea_subscriptionBox",
3134
- "optionalContent": "_5JdLea_optionalContent",
3135
- "sectionHint": "_5JdLea_sectionHint",
3136
- "channelEmpty": "_5JdLea_channelEmpty",
3137
- "channelDotWarn": "_5JdLea_channelDotWarn",
3138
- "modelChoices": "_5JdLea_modelChoices",
3139
- "channelRow": "_5JdLea_channelRow",
3140
- "pickerOverlay": "_5JdLea_pickerOverlay",
3141
- "select": "_5JdLea_select",
3142
- "modelBadge": "_5JdLea_modelBadge",
3143
- "overviewHint": "_5JdLea_overviewHint",
3144
- "pickerList": "_5JdLea_pickerList",
3145
- "sectionChevron": "_5JdLea_sectionChevron",
3146
- "modelFetchRow": "_5JdLea_modelFetchRow",
3147
- "body": "_5JdLea_body",
3148
- "modelChip": "_5JdLea_modelChip",
3064
+ "channelAddRow": "_5JdLea_channelAddRow",
3065
+ "presetList": "_5JdLea_presetList",
3066
+ "modelCandidateList": "_5JdLea_modelCandidateList",
3149
3067
  "editorClose": "_5JdLea_editorClose",
3150
- "chevronOpen": "_5JdLea_chevronOpen",
3151
- "textarea": "_5JdLea_textarea",
3152
- "addModel": "_5JdLea_addModel",
3153
- "modelCandidateLabel": "_5JdLea_modelCandidateLabel",
3154
- "summaryGrid": "_5JdLea_summaryGrid",
3155
- "input": "_5JdLea_input",
3156
- "channelHost": "_5JdLea_channelHost",
3157
- "modelArrow": "_5JdLea_modelArrow",
3158
- "sectionToggleHint": "_5JdLea_sectionToggleHint"
3068
+ "spacer": "_5JdLea_spacer",
3069
+ "label": "_5JdLea_label",
3070
+ "field": "_5JdLea_field",
3071
+ "schemaSection": "_5JdLea_schemaSection",
3072
+ "sectionHeader": "_5JdLea_sectionHeader",
3073
+ "modelChip": "_5JdLea_modelChip",
3074
+ "modelSummary": "_5JdLea_modelSummary",
3075
+ "sectionTitle": "_5JdLea_sectionTitle",
3076
+ "modelRows": "_5JdLea_modelRows"
3159
3077
  };
3160
3078
  //#endregion
3161
3079
  //#region src/client/SettingsCard.tsx
@@ -3172,23 +3090,106 @@ window.__ModuleLoader__.load({
3172
3090
  * and an editor holding API key, display name, API URL, and the model catalog
3173
3091
  * with detection.
3174
3092
  */
3093
+ /**
3094
+ * The schema mirror the shared `ConfigForm` reads its field list from.
3095
+ *
3096
+ * The host's `configForms.describe()` does not carry this namespace: the plugin
3097
+ * re-serves it over its own bridge (`/api/dsh-imagegen/settings/*`) so the key
3098
+ * writes can be diverted into the credential store. The bridge does return the
3099
+ * schema envelope, so the scope snapshot carries it and this adapter presents it
3100
+ * in the shape the form expects.
3101
+ *
3102
+ * The snapshot object is cached per schema identity. `useSyncExternalStore`
3103
+ * compares snapshots by reference, so rebuilding it on every `getSnapshot()`
3104
+ * call would re-render without end.
3105
+ */
3106
+ function createSchemaMirror(scope) {
3107
+ let cachedSchema;
3108
+ let cached = {
3109
+ status: "loading",
3110
+ view: { namespaces: [] }
3111
+ };
3112
+ return {
3113
+ getSnapshot() {
3114
+ const snapshot = scope.getSnapshot();
3115
+ const schema = snapshot.schema;
3116
+ if (schema !== cachedSchema) {
3117
+ cachedSchema = schema;
3118
+ cached = {
3119
+ status: snapshot.status,
3120
+ view: { namespaces: schema === void 0 ? [] : [{
3121
+ ns: IMAGEGEN_SETTINGS_NAMESPACE,
3122
+ schema
3123
+ }] }
3124
+ };
3125
+ }
3126
+ return cached;
3127
+ },
3128
+ subscribe(listener) {
3129
+ return scope.subscribe(listener);
3130
+ }
3131
+ };
3132
+ }
3133
+ /**
3134
+ * Present the bridge scope as the shared form's handle.
3135
+ *
3136
+ * The only difference is the value's static type: the plugin declares
3137
+ * `ImageGenConfig` (an interface, so no index signature) while the form takes a
3138
+ * plain record. They are the same object at runtime; widening here keeps the
3139
+ * plugin's own interface precise instead of adding an index signature to it.
3140
+ */
3141
+ function asConfigFormHandle(scope) {
3142
+ let cachedFrom;
3143
+ let cached;
3144
+ const project = (snapshot) => ({
3145
+ status: snapshot.status,
3146
+ value: snapshot.value,
3147
+ writable: snapshot.writable,
3148
+ revision: snapshot.revision
3149
+ });
3150
+ return {
3151
+ getSnapshot() {
3152
+ const snapshot = scope.getSnapshot();
3153
+ if (snapshot !== cachedFrom) {
3154
+ cachedFrom = snapshot;
3155
+ cached = project(snapshot);
3156
+ }
3157
+ return cached;
3158
+ },
3159
+ subscribe(listener) {
3160
+ return scope.subscribe(listener);
3161
+ },
3162
+ mutate(ops, expectedRevision) {
3163
+ return scope.mutate(ops, expectedRevision);
3164
+ }
3165
+ };
3166
+ }
3175
3167
  /** Bridges the imagegen scope onto the card's staged forms. */
3176
3168
  var ImageGenSettingsCardController = class {
3177
3169
  scope;
3178
3170
  form;
3179
3171
  channelsForm;
3172
+ /**
3173
+ * The two face values that must keep their identity across `inject()` calls.
3174
+ *
3175
+ * The slot calls `inject()` on every render. Building either of these fresh
3176
+ * there changes the prop identity the renderer subscribed with, which
3177
+ * schedules another render, which calls `inject()` again — React reports that
3178
+ * as error #185 (`Maximum update depth exceeded`) and the slot renders as an
3179
+ * error node with no controls under it.
3180
+ */
3181
+ cardStore;
3182
+ schemaMirror;
3180
3183
  /** @param scope - the bound bridge scope for the dsh-imagegen namespace. */
3181
3184
  constructor(scope) {
3182
3185
  this.scope = scope;
3183
- this.form = new CardForm(scope, [
3184
- booleanField("enabled"),
3185
- booleanField("announceToAgent"),
3186
- booleanField("allowAgentImageGeneration"),
3187
- textField("promptApiUrl"),
3188
- secretField("promptApiKey"),
3189
- textField("promptModel")
3190
- ], { secretSettled: (field) => this.scope.getSecretSetSnapshot(field) });
3186
+ this.form = new CardForm(scope, [secretField("promptApiKey")], { secretSettled: (field) => this.scope.getSecretSetSnapshot(field) });
3191
3187
  this.channelsForm = new ChannelsForm(scope);
3188
+ this.schemaMirror = createSchemaMirror(scope);
3189
+ this.cardStore = this.form.bind(() => this.projection());
3190
+ this.channelsForm.subscribe(() => {
3191
+ this.cardStore.set(this.projection());
3192
+ });
3192
3193
  }
3193
3194
  projection() {
3194
3195
  const shell = this.form.shell();
@@ -3196,12 +3197,7 @@ window.__ModuleLoader__.load({
3196
3197
  ...shell,
3197
3198
  dirty: shell.dirty || this.channelsForm.snapshot().dirty,
3198
3199
  channels: this.channelsForm.snapshot(),
3199
- enabled: this.form.field("enabled"),
3200
- announceToAgent: this.form.field("announceToAgent"),
3201
- allowAgentImageGeneration: this.form.field("allowAgentImageGeneration"),
3202
- promptApiUrl: this.form.field("promptApiUrl"),
3203
- promptApiKey: this.form.field("promptApiKey"),
3204
- promptModel: this.form.field("promptModel")
3200
+ promptApiKey: this.form.field("promptApiKey")
3205
3201
  };
3206
3202
  }
3207
3203
  /**
@@ -3209,13 +3205,11 @@ window.__ModuleLoader__.load({
3209
3205
  * @returns the card's snapshot and the form/channel actions.
3210
3206
  */
3211
3207
  inject() {
3212
- const cardStore = this.form.bind(() => this.projection());
3213
- this.channelsForm.subscribe(() => {
3214
- cardStore.set(this.projection());
3215
- });
3216
3208
  return {
3217
- hooks: { imageGenSettingsCard: cardStore },
3209
+ hooks: { imageGenSettingsCard: this.cardStore },
3218
3210
  channels: this.channelsForm.actions(),
3211
+ settingsScope: this.scope,
3212
+ schemaMirror: this.schemaMirror,
3219
3213
  ...this.form.actions()
3220
3214
  };
3221
3215
  }
@@ -3238,6 +3232,8 @@ window.__ModuleLoader__.load({
3238
3232
  const t = tt;
3239
3233
  useImageGenLanguageTick();
3240
3234
  const state = props.useImageGenSettingsCard((snapshot) => snapshot);
3235
+ const formHandle = (0, react.useMemo)(() => asConfigFormHandle(props.settingsScope), [props.settingsScope]);
3236
+ const liveModel = props.settingsScope.getSnapshot().value?.promptModel ?? "";
3241
3237
  const [open, setOpen] = (0, react.useState)(false);
3242
3238
  const [promptModels, setPromptModels] = (0, react.useState)([]);
3243
3239
  const [loadingPromptModels, setLoadingPromptModels] = (0, react.useState)(false);
@@ -3246,7 +3242,6 @@ window.__ModuleLoader__.load({
3246
3242
  const [manualPromptModel, setManualPromptModel] = (0, react.useState)("");
3247
3243
  const [enhancementOpen, setEnhancementOpen] = (0, react.useState)(false);
3248
3244
  const [promptApiOpen, setPromptApiOpen] = (0, react.useState)(false);
3249
- const [moreOpen, setMoreOpen] = (0, react.useState)(false);
3250
3245
  const [editingId, setEditingId] = (0, react.useState)(null);
3251
3246
  const [presetPickerOpen, setPresetPickerOpen] = (0, react.useState)(false);
3252
3247
  const [presets, setPresets] = (0, react.useState)([]);
@@ -3254,7 +3249,7 @@ window.__ModuleLoader__.load({
3254
3249
  const [confirmDeleteId, setConfirmDeleteId] = (0, react.useState)(null);
3255
3250
  if (!state.available) return null;
3256
3251
  const title = t("settings.title");
3257
- const blocked = !state.dirty || state.invalid || state.saving || state.channels.saving;
3252
+ !state.dirty || state.invalid || state.saving || state.channels.saving;
3258
3253
  const disabled = !state.writable;
3259
3254
  const fieldProps = {
3260
3255
  overriddenLabel: t("settings.overridden"),
@@ -3330,441 +3325,341 @@ window.__ModuleLoader__.load({
3330
3325
  }),
3331
3326
  open ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3332
3327
  className: settings_card_module_css_default.body,
3333
- children: [
3334
- !state.writable ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3335
- className: settings_card_module_css_default.readOnly,
3336
- role: "status",
3337
- children: t("settings.readOnly")
3338
- }) : null,
3339
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
3340
- className: settings_card_module_css_default.channelSection,
3341
- "aria-label": t("channels.title"),
3328
+ children: [!state.writable ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3329
+ className: settings_card_module_css_default.readOnly,
3330
+ role: "status",
3331
+ children: t("settings.readOnly")
3332
+ }) : null, /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3333
+ className: settings_card_module_css_default.schemaSection,
3334
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_logictan_dsh_plugins_shared_client_client.ConfigForm, {
3335
+ namespace: IMAGEGEN_SETTINGS_NAMESPACE,
3336
+ form: formHandle,
3337
+ describe: props.schemaMirror,
3338
+ title: t("settings.scalarsTitle"),
3342
3339
  children: [
3343
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3344
- className: settings_card_module_css_default.sectionHeader,
3345
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
3346
- className: settings_card_module_css_default.sectionTitle,
3347
- children: t("channels.title")
3348
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3349
- className: settings_card_module_css_default.sectionHint,
3350
- children: t("channels.hint")
3351
- })] })
3352
- }),
3353
- channels.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3354
- className: settings_card_module_css_default.channelEmpty,
3355
- children: t("channels.empty")
3356
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
3357
- className: settings_card_module_css_default.channelList,
3358
- children: channels.map((channel) => {
3359
- const keyHeld = state.channels.keySet[channel.id] === true;
3360
- const ready = keyHeld && channel.models.length > 0;
3361
- const isDefault = channel.id === state.channels.defaultChannelId;
3362
- if (confirmDeleteId === channel.id) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
3363
- className: settings_card_module_css_default.channelRow,
3364
- "data-action": true,
3365
- children: [
3366
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3367
- className: settings_card_module_css_default.deleteConfirmText,
3368
- children: t("channels.deleteConfirmTitle", { name: channel.name || t("channels.untitled") })
3369
- }),
3370
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3371
- type: "button",
3372
- className: settings_card_module_css_default.channelDanger,
3340
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
3341
+ className: settings_card_module_css_default.channelSection,
3342
+ "aria-label": t("channels.title"),
3343
+ children: [
3344
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3345
+ className: settings_card_module_css_default.sectionHeader,
3346
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
3347
+ className: settings_card_module_css_default.sectionTitle,
3348
+ children: t("channels.title")
3349
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3350
+ className: settings_card_module_css_default.sectionHint,
3351
+ children: t("channels.hint")
3352
+ })] })
3353
+ }),
3354
+ channels.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3355
+ className: settings_card_module_css_default.channelEmpty,
3356
+ children: t("channels.empty")
3357
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
3358
+ className: settings_card_module_css_default.channelList,
3359
+ children: channels.map((channel) => {
3360
+ const keyHeld = state.channels.keySet[channel.id] === true;
3361
+ const ready = keyHeld && channel.models.length > 0;
3362
+ const isDefault = channel.id === state.channels.defaultChannelId;
3363
+ if (confirmDeleteId === channel.id) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
3364
+ className: settings_card_module_css_default.channelRow,
3365
+ "data-action": true,
3366
+ children: [
3367
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3368
+ className: settings_card_module_css_default.deleteConfirmText,
3369
+ children: t("channels.deleteConfirmTitle", { name: channel.name || t("channels.untitled") })
3370
+ }),
3371
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_logictan_dsh_plugins_shared_client_client.Button, {
3372
+ variant: "danger",
3373
+ size: "sm",
3374
+ disabled,
3375
+ onClick: () => {
3376
+ props.channels.setChannels(channels.filter((candidate) => candidate.id !== channel.id));
3377
+ if (isDefault && channels.length > 1) {
3378
+ const next = channels.find((candidate) => candidate.id !== channel.id);
3379
+ if (next !== void 0) props.channels.setDefaultChannel(next.id);
3380
+ }
3381
+ setConfirmDeleteId(null);
3382
+ if (editingId === channel.id) setEditingId(null);
3383
+ },
3384
+ children: t("channels.confirm")
3385
+ }),
3386
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_logictan_dsh_plugins_shared_client_client.Button, {
3387
+ variant: "ghost",
3388
+ size: "sm",
3389
+ disabled,
3390
+ onClick: () => {
3391
+ setConfirmDeleteId(null);
3392
+ },
3393
+ children: t("channels.cancel")
3394
+ })
3395
+ ]
3396
+ }, channel.id);
3397
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
3398
+ className: settings_card_module_css_default.channelRow,
3399
+ children: [
3400
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_logictan_dsh_plugins_shared_client_client.StatusDot, {
3401
+ kind: ready ? "ok" : "warn",
3402
+ title: t(ready ? "channels.statusReady" : "channels.statusIncomplete")
3403
+ }),
3404
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
3405
+ type: "button",
3406
+ className: settings_card_module_css_default.channelMain,
3407
+ disabled,
3408
+ onClick: () => {
3409
+ setEditingId(channel.id);
3410
+ },
3411
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3412
+ className: settings_card_module_css_default.channelName,
3413
+ children: isDefault ? `★ ${channel.name || t("channels.untitled")}` : channel.name || t("channels.untitled")
3414
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3415
+ className: settings_card_module_css_default.channelMeta,
3416
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_logictan_dsh_plugins_shared_client_client.Tag, {
3417
+ kind: !keyHeld || channel.models.length === 0 ? "warn" : "ok",
3418
+ children: [
3419
+ keyHeld ? t("channels.keySet") : t("channels.keyMissing"),
3420
+ " · ",
3421
+ channel.models.length > 0 ? t("channels.modelCount", { n: channel.models.length }) : t("channels.noModels")
3422
+ ]
3423
+ })
3424
+ })]
3425
+ }),
3426
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_logictan_dsh_plugins_shared_client_client.Button, {
3427
+ variant: "ghost",
3428
+ size: "sm",
3429
+ onClick: () => {
3430
+ setEditingId(channel.id);
3431
+ },
3432
+ children: t("channels.edit")
3433
+ }),
3434
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_logictan_dsh_plugins_shared_client_client.Button, {
3435
+ variant: "danger",
3436
+ size: "sm",
3437
+ onClick: () => {
3438
+ setConfirmDeleteId(channel.id);
3439
+ },
3440
+ children: t("channels.delete")
3441
+ })
3442
+ ]
3443
+ }, channel.id);
3444
+ })
3445
+ }),
3446
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3447
+ className: settings_card_module_css_default.channelControls,
3448
+ children: [open && presetPickerOpen ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PresetPicker, {
3449
+ t,
3450
+ presets,
3451
+ error: presetError,
3452
+ disabled: state.writable === false,
3453
+ onLoad: () => {
3454
+ setPresetError(null);
3455
+ fetch(PRESETS_API, { method: "POST" }).then(async (response) => {
3456
+ const body = await response.json();
3457
+ if (!response.ok || body.ok !== true || body.presets === void 0) throw new Error(body.message ?? `HTTP ${response.status}`);
3458
+ setPresets(body.presets);
3459
+ }).catch((error) => {
3460
+ setPresetError(error instanceof Error ? error.message : String(error));
3461
+ });
3462
+ },
3463
+ onPick: (preset) => {
3464
+ const draft = newChannelDraft(preset);
3465
+ props.channels.setChannels([...channels, draft]);
3466
+ setPresetPickerOpen(false);
3467
+ setEditingId(draft.id);
3468
+ },
3469
+ onCustom: () => {
3470
+ const draft = newChannelDraft(void 0);
3471
+ props.channels.setChannels([...channels, draft]);
3472
+ setPresetPickerOpen(false);
3473
+ setEditingId(draft.id);
3474
+ },
3475
+ onClose: () => {
3476
+ setPresetPickerOpen(false);
3477
+ }
3478
+ }) : null, /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3479
+ className: settings_card_module_css_default.channelAddRow,
3480
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_logictan_dsh_plugins_shared_client_client.Button, {
3481
+ variant: "secondary",
3482
+ size: "sm",
3373
3483
  disabled,
3374
3484
  onClick: () => {
3375
- props.channels.setChannels(channels.filter((candidate) => candidate.id !== channel.id));
3376
- if (isDefault && channels.length > 1) {
3377
- const next = channels.find((candidate) => candidate.id !== channel.id);
3378
- if (next !== void 0) props.channels.setDefaultChannel(next.id);
3379
- }
3380
- setConfirmDeleteId(null);
3381
- if (editingId === channel.id) setEditingId(null);
3485
+ setPresetError(null);
3486
+ setPresetPickerOpen(true);
3382
3487
  },
3383
- children: t("channels.confirm")
3384
- }),
3385
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3386
- type: "button",
3387
- className: settings_card_module_css_default.channelAction,
3488
+ children: ["+ ", t("channels.addProvider")]
3489
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_logictan_dsh_plugins_shared_client_client.Button, {
3490
+ variant: "secondary",
3491
+ size: "sm",
3388
3492
  disabled,
3389
3493
  onClick: () => {
3390
- setConfirmDeleteId(null);
3494
+ addCustomChannel(channels, props.channels, setEditingId);
3391
3495
  },
3392
- children: t("channels.cancel")
3393
- })
3394
- ]
3395
- }, channel.id);
3396
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
3397
- className: settings_card_module_css_default.channelRow,
3398
- children: [
3399
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3400
- className: ready ? settings_card_module_css_default.channelDotReady : settings_card_module_css_default.channelDotWarn,
3401
- "aria-hidden": "true",
3402
- title: t(ready ? "channels.statusReady" : "channels.statusIncomplete")
3403
- }),
3404
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
3496
+ children: ["+ ", t("channels.addCustom")]
3497
+ })]
3498
+ })]
3499
+ })
3500
+ ]
3501
+ }),
3502
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
3503
+ type: "button",
3504
+ className: settings_card_module_css_default.disclosure,
3505
+ "aria-expanded": enhancementOpen,
3506
+ onClick: () => {
3507
+ setEnhancementOpen((open) => !open);
3508
+ },
3509
+ children: [
3510
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("settings.promptEnhanceTitle") }),
3511
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("settings.optional") }),
3512
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3513
+ "aria-hidden": "true",
3514
+ children: enhancementOpen ? "⌃" : "⌄"
3515
+ })
3516
+ ]
3517
+ }),
3518
+ enhancementOpen ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
3519
+ className: settings_card_module_css_default.optionalContent,
3520
+ "aria-label": t("settings.promptEnhanceTitle"),
3521
+ children: [
3522
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3523
+ className: settings_card_module_css_default.sectionHint,
3524
+ children: t("settings.promptEnhanceHint")
3525
+ }),
3526
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3527
+ className: settings_card_module_css_default.sectionHeader,
3528
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
3529
+ className: settings_card_module_css_default.sectionTitle,
3530
+ children: t("settings.promptModel")
3531
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3532
+ className: settings_card_module_css_default.sectionHint,
3533
+ children: t("settings.promptModelDetectionHint")
3534
+ })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_logictan_dsh_plugins_shared_client_client.Button, {
3535
+ variant: "secondary",
3536
+ size: "sm",
3537
+ loading: loadingPromptModels,
3538
+ disabled: disabled || loadingPromptModels,
3539
+ onClick: () => {
3540
+ setLoadingPromptModels(true);
3541
+ setPromptModelsError(null);
3542
+ fetch(PROMPT_ENHANCE_API.models, { method: "POST" }).then(async (response) => {
3543
+ const body = await response.json();
3544
+ if (!response.ok || body.ok !== true) throw new Error(body.message ?? `HTTP ${response.status}`);
3545
+ setPromptModels(body.models ?? []);
3546
+ }).catch((error) => {
3547
+ setPromptModelsError(error instanceof Error ? error.message : String(error));
3548
+ }).finally(() => {
3549
+ setLoadingPromptModels(false);
3550
+ });
3551
+ },
3552
+ children: loadingPromptModels ? t("settings.promptModelsLoading") : t("settings.promptModelsFetch")
3553
+ })]
3554
+ }),
3555
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3556
+ className: settings_card_module_css_default.modelSummary,
3557
+ children: [liveModel.trim() !== "" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3558
+ className: settings_card_module_css_default.modelChip,
3559
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: liveModel }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3405
3560
  type: "button",
3406
- className: settings_card_module_css_default.channelMain,
3407
3561
  disabled,
3562
+ "aria-label": `${t("settings.removeModel")}: ${liveModel}`,
3408
3563
  onClick: () => {
3409
- setEditingId(channel.id);
3564
+ props.settingsScope.set("promptModel", "");
3410
3565
  },
3411
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3412
- className: settings_card_module_css_default.channelName,
3413
- children: isDefault ? `★ ${channel.name || t("channels.untitled")}` : channel.name || t("channels.untitled")
3414
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3415
- className: settings_card_module_css_default.channelMeta,
3416
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3417
- className: settings_card_module_css_default.channelBadge,
3418
- "data-warn": !keyHeld || channel.models.length === 0 ? "" : void 0,
3419
- children: [
3420
- keyHeld ? t("channels.keySet") : t("channels.keyMissing"),
3421
- " · ",
3422
- channel.models.length > 0 ? t("channels.modelCount", { n: channel.models.length }) : t("channels.noModels")
3423
- ]
3424
- })
3425
- })]
3426
- }),
3427
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3428
- type: "button",
3429
- className: settings_card_module_css_default.channelAction,
3430
- onClick: () => {
3431
- setEditingId(channel.id);
3432
- },
3433
- children: t("channels.edit")
3434
- }),
3435
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3436
- type: "button",
3437
- className: settings_card_module_css_default.channelAction,
3438
- "data-danger": true,
3439
- onClick: () => {
3440
- setConfirmDeleteId(channel.id);
3441
- },
3442
- children: t("channels.delete")
3443
- })
3444
- ]
3445
- }, channel.id);
3446
- })
3447
- }),
3448
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3449
- className: settings_card_module_css_default.channelControls,
3450
- children: [open && presetPickerOpen ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PresetPicker, {
3451
- t,
3452
- presets,
3453
- error: presetError,
3454
- disabled: state.writable === false,
3455
- onLoad: () => {
3456
- setPresetError(null);
3457
- fetch(PRESETS_API, { method: "POST" }).then(async (response) => {
3458
- const body = await response.json();
3459
- if (!response.ok || body.ok !== true || body.presets === void 0) throw new Error(body.message ?? `HTTP ${response.status}`);
3460
- setPresets(body.presets);
3461
- }).catch((error) => {
3462
- setPresetError(error instanceof Error ? error.message : String(error));
3463
- });
3464
- },
3465
- onPick: (preset) => {
3466
- const draft = newChannelDraft(preset);
3467
- props.channels.setChannels([...channels, draft]);
3468
- setPresetPickerOpen(false);
3469
- setEditingId(draft.id);
3470
- },
3471
- onCustom: () => {
3472
- const draft = newChannelDraft(void 0);
3473
- props.channels.setChannels([...channels, draft]);
3474
- setPresetPickerOpen(false);
3475
- setEditingId(draft.id);
3476
- },
3477
- onClose: () => {
3478
- setPresetPickerOpen(false);
3479
- }
3480
- }) : null, /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3481
- className: settings_card_module_css_default.channelAddRow,
3482
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
3483
- type: "button",
3484
- className: settings_card_module_css_default.channelAdd,
3485
- disabled,
3486
- onClick: () => {
3487
- setPresetError(null);
3488
- setPresetPickerOpen(true);
3489
- },
3490
- children: ["+ ", t("channels.addProvider")]
3491
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
3492
- type: "button",
3493
- className: settings_card_module_css_default.channelAdd,
3494
- disabled,
3495
- onClick: () => {
3496
- addCustomChannel(channels, props.channels, setEditingId);
3497
- },
3498
- children: ["+ ", t("channels.addCustom")]
3499
- })]
3500
- })]
3501
- })
3502
- ]
3503
- }),
3504
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
3505
- type: "button",
3506
- className: settings_card_module_css_default.disclosure,
3507
- "aria-expanded": enhancementOpen,
3508
- onClick: () => {
3509
- setEnhancementOpen((open) => !open);
3510
- },
3511
- children: [
3512
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("settings.promptEnhanceTitle") }),
3513
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("settings.optional") }),
3514
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3515
- "aria-hidden": "true",
3516
- children: enhancementOpen ? "⌃" : "⌄"
3517
- })
3518
- ]
3519
- }),
3520
- enhancementOpen ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
3521
- className: settings_card_module_css_default.optionalContent,
3522
- "aria-label": t("settings.promptEnhanceTitle"),
3523
- children: [
3524
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3525
- className: settings_card_module_css_default.sectionHint,
3526
- children: t("settings.promptEnhanceHint")
3527
- }),
3528
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3529
- className: settings_card_module_css_default.sectionHeader,
3530
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
3531
- className: settings_card_module_css_default.sectionTitle,
3532
- children: t("settings.promptModel")
3533
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3534
- className: settings_card_module_css_default.sectionHint,
3535
- children: t("settings.promptModelDetectionHint")
3536
- })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3537
- type: "button",
3538
- className: settings_card_module_css_default.modelFetch,
3539
- disabled: disabled || loadingPromptModels,
3540
- onClick: () => {
3541
- setLoadingPromptModels(true);
3542
- setPromptModelsError(null);
3543
- fetch(PROMPT_ENHANCE_API.models, { method: "POST" }).then(async (response) => {
3544
- const body = await response.json();
3545
- if (!response.ok || body.ok !== true) throw new Error(body.message ?? `HTTP ${response.status}`);
3546
- setPromptModels(body.models ?? []);
3547
- }).catch((error) => {
3548
- setPromptModelsError(error instanceof Error ? error.message : String(error));
3549
- }).finally(() => {
3550
- setLoadingPromptModels(false);
3551
- });
3552
- },
3553
- children: loadingPromptModels ? t("settings.promptModelsLoading") : t("settings.promptModelsFetch")
3554
- })]
3555
- }),
3556
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3557
- className: settings_card_module_css_default.modelSummary,
3558
- children: [state.promptModel.text.trim() !== "" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3559
- className: settings_card_module_css_default.modelChip,
3560
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: state.promptModel.text }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3566
+ children: "×"
3567
+ })]
3568
+ }) : null, /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_logictan_dsh_plugins_shared_client_client.Button, {
3569
+ variant: "secondary",
3570
+ size: "sm",
3571
+ disabled,
3572
+ onClick: () => {
3573
+ setManualPromptModelOpen((open) => !open);
3574
+ setEnhancementOpen(true);
3575
+ },
3576
+ children: manualPromptModelOpen ? t("settings.cancelAddModel") : t("settings.addModel")
3577
+ })]
3578
+ }),
3579
+ manualPromptModelOpen ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3580
+ className: settings_card_module_css_default.manualModelRow,
3581
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_logictan_dsh_plugins_shared_client_client.TextField, {
3582
+ value: manualPromptModel,
3583
+ placeholder: t("settings.addPromptModelPlaceholder"),
3584
+ disabled,
3585
+ onValueChange: setManualPromptModel
3586
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_logictan_dsh_plugins_shared_client_client.Button, {
3587
+ variant: "secondary",
3588
+ size: "sm",
3589
+ disabled: disabled || manualPromptModel.trim() === "",
3590
+ onClick: () => {
3591
+ props.settingsScope.set("promptModel", manualPromptModel);
3592
+ setManualPromptModel("");
3593
+ },
3594
+ children: t("settings.addModelConfirm")
3595
+ })]
3596
+ }) : null,
3597
+ promptModels.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3598
+ className: settings_card_module_css_default.modelCandidateList,
3599
+ role: "radiogroup",
3600
+ "aria-label": t("settings.promptModelsCandidates"),
3601
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3602
+ className: settings_card_module_css_default.modelCandidateLabel,
3603
+ children: t("settings.promptModelsCandidates")
3604
+ }), promptModels.map((candidate) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3605
+ type: "button",
3606
+ role: "radio",
3607
+ className: settings_card_module_css_default.modelCandidate,
3608
+ "aria-checked": liveModel === candidate,
3609
+ "data-selected": liveModel === candidate ? "" : void 0,
3610
+ disabled,
3611
+ onClick: () => {
3612
+ props.settingsScope.set("promptModel", candidate);
3613
+ },
3614
+ children: candidate
3615
+ }, candidate))]
3616
+ }) : null,
3617
+ promptModelsError !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3618
+ className: settings_card_module_css_default.failed,
3619
+ role: "status",
3620
+ children: promptModelsError
3621
+ }) : null,
3622
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
3561
3623
  type: "button",
3562
- disabled,
3563
- "aria-label": `${t("settings.removeModel")}: ${state.promptModel.text}`,
3624
+ className: settings_card_module_css_default.inlineDisclosure,
3625
+ "aria-expanded": promptApiOpen,
3564
3626
  onClick: () => {
3565
- props.edit("promptModel", "");
3627
+ setPromptApiOpen((open) => !open);
3566
3628
  },
3567
- children: "×"
3568
- })]
3569
- }) : null, /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3570
- type: "button",
3571
- className: settings_card_module_css_default.addModel,
3572
- disabled,
3573
- onClick: () => {
3574
- setManualPromptModelOpen((open) => !open);
3575
- setEnhancementOpen(true);
3576
- },
3577
- children: manualPromptModelOpen ? t("settings.cancelAddModel") : t("settings.addModel")
3578
- })]
3579
- }),
3580
- manualPromptModelOpen ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3581
- className: settings_card_module_css_default.manualModelRow,
3582
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
3583
- className: settings_card_module_css_default.input,
3584
- value: manualPromptModel,
3585
- placeholder: t("settings.addPromptModelPlaceholder"),
3586
- disabled,
3587
- onChange: (event) => {
3588
- setManualPromptModel(event.target.value);
3589
- }
3590
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3591
- type: "button",
3592
- className: settings_card_module_css_default.addModel,
3593
- disabled: disabled || manualPromptModel.trim() === "",
3594
- onClick: () => {
3595
- props.edit("promptModel", manualPromptModel);
3596
- setManualPromptModel("");
3597
- },
3598
- children: t("settings.addModelConfirm")
3599
- })]
3600
- }) : null,
3601
- promptModels.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3602
- className: settings_card_module_css_default.modelCandidateList,
3603
- role: "radiogroup",
3604
- "aria-label": t("settings.promptModelsCandidates"),
3605
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3606
- className: settings_card_module_css_default.modelCandidateLabel,
3607
- children: t("settings.promptModelsCandidates")
3608
- }), promptModels.map((candidate) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3609
- type: "button",
3610
- role: "radio",
3611
- className: settings_card_module_css_default.modelCandidate,
3612
- "aria-checked": state.promptModel.text === candidate,
3613
- "data-selected": state.promptModel.text === candidate ? "" : void 0,
3614
- disabled,
3615
- onClick: () => {
3616
- props.edit("promptModel", candidate);
3617
- },
3618
- children: candidate
3619
- }, candidate))]
3620
- }) : null,
3621
- promptModelsError !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3622
- className: settings_card_module_css_default.failed,
3623
- role: "status",
3624
- children: promptModelsError
3629
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("settings.promptApiAdvanced") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3630
+ "aria-hidden": "true",
3631
+ children: promptApiOpen ? "⌃" : "⌄"
3632
+ })]
3633
+ }),
3634
+ promptApiOpen ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3635
+ className: settings_card_module_css_default.optionalContent,
3636
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ValueField, {
3637
+ id: "dsh-imagegen-settings-prompt-apikey",
3638
+ label: t("settings.promptApiKey"),
3639
+ hint: t("settings.promptApiKeyHint"),
3640
+ placeholder: "sk-…",
3641
+ secret: true,
3642
+ ...fieldProps,
3643
+ ...state.promptApiKey,
3644
+ overridden: false,
3645
+ onEdit: (text) => {
3646
+ props.edit("promptApiKey", text);
3647
+ },
3648
+ onReset: () => {
3649
+ props.resetField("promptApiKey");
3650
+ }
3651
+ })
3652
+ }) : null
3653
+ ]
3625
3654
  }) : null,
3626
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
3627
- type: "button",
3628
- className: settings_card_module_css_default.inlineDisclosure,
3629
- "aria-expanded": promptApiOpen,
3630
- onClick: () => {
3631
- setPromptApiOpen((open) => !open);
3632
- },
3633
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("settings.promptApiAdvanced") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3634
- "aria-hidden": "true",
3635
- children: promptApiOpen ? "⌃" : "⌄"
3636
- })]
3637
- }),
3638
- promptApiOpen ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3639
- className: settings_card_module_css_default.optionalContent,
3640
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ValueField, {
3641
- id: "dsh-imagegen-settings-prompt-apiurl",
3642
- label: t("settings.promptApiUrl"),
3643
- hint: t("settings.promptApiUrlHint"),
3644
- placeholder: "https://api.openai.com/v1",
3645
- ...fieldProps,
3646
- ...state.promptApiUrl,
3647
- onEdit: (text) => {
3648
- props.edit("promptApiUrl", text);
3649
- },
3650
- onReset: () => {
3651
- props.resetField("promptApiUrl");
3652
- }
3653
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ValueField, {
3654
- id: "dsh-imagegen-settings-prompt-apikey",
3655
- label: t("settings.promptApiKey"),
3656
- hint: t("settings.promptApiKeyHint"),
3657
- placeholder: "sk-…",
3658
- secret: true,
3659
- ...fieldProps,
3660
- ...state.promptApiKey,
3661
- overridden: false,
3662
- onEdit: (text) => {
3663
- props.edit("promptApiKey", text);
3664
- },
3665
- onReset: () => {
3666
- props.resetField("promptApiKey");
3667
- }
3668
- })]
3669
- }) : null
3670
- ]
3671
- }) : null,
3672
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
3673
- type: "button",
3674
- className: settings_card_module_css_default.disclosure,
3675
- "aria-expanded": moreOpen,
3676
- onClick: () => {
3677
- setMoreOpen((open) => !open);
3678
- },
3679
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("settings.moreOptions") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3680
- "aria-hidden": "true",
3681
- children: moreOpen ? "⌃" : "⌄"
3682
- })]
3683
- }),
3684
- moreOpen ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3685
- className: settings_card_module_css_default.optionalContent,
3686
- children: [
3687
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BooleanField, {
3688
- id: "dsh-imagegen-settings-enabled",
3689
- label: t("settings.enabled"),
3690
- hint: t("settings.enabledHint"),
3691
- inheritLabel: t("settings.inherit"),
3692
- onLabel: t("settings.on"),
3693
- offLabel: t("settings.off"),
3694
- ...fieldProps,
3695
- ...state.enabled,
3696
- onEdit: (text) => {
3697
- props.edit("enabled", text);
3698
- },
3699
- onReset: () => {
3700
- props.resetField("enabled");
3701
- }
3702
- }),
3703
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BooleanField, {
3704
- id: "dsh-imagegen-settings-announce",
3705
- label: t("settings.announceToAgent"),
3706
- hint: t("settings.announceToAgentHint"),
3707
- inheritLabel: t("settings.inherit"),
3708
- onLabel: t("settings.on"),
3709
- offLabel: t("settings.off"),
3710
- ...fieldProps,
3711
- ...state.announceToAgent,
3712
- onEdit: (text) => {
3713
- props.edit("announceToAgent", text);
3714
- },
3715
- onReset: () => {
3716
- props.resetField("announceToAgent");
3717
- }
3718
- }),
3719
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BooleanField, {
3720
- id: "dsh-imagegen-settings-agent-generation",
3721
- label: t("settings.allowAgentImageGeneration"),
3722
- hint: t("settings.allowAgentImageGenerationHint"),
3723
- inheritLabel: t("settings.inherit"),
3724
- onLabel: t("settings.on"),
3725
- offLabel: t("settings.off"),
3726
- ...fieldProps,
3727
- ...state.allowAgentImageGeneration,
3728
- onEdit: (text) => {
3729
- props.edit("enabled", text);
3730
- },
3731
- onReset: () => {
3732
- props.resetField("enabled");
3733
- }
3734
- })
3735
- ]
3736
- }) : null,
3737
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3738
- className: settings_card_module_css_default.footer,
3739
- children: [
3740
3655
  state.failed || state.channels.failed ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3741
3656
  className: settings_card_module_css_default.failed,
3742
3657
  role: "status",
3743
3658
  children: t("settings.saveFailed")
3744
- }) : null,
3745
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3746
- type: "button",
3747
- className: settings_card_module_css_default.discard,
3748
- disabled: !state.dirty || state.saving || state.channels.saving,
3749
- onClick: () => {
3750
- props.discard();
3751
- props.channels.discard();
3752
- },
3753
- children: t("settings.discard")
3754
- }),
3755
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3756
- type: "button",
3757
- className: settings_card_module_css_default.save,
3758
- disabled: blocked,
3759
- onClick: () => {
3760
- props.channels.commit();
3761
- props.save();
3762
- },
3763
- children: t(!state.saving && !state.channels.saving ? "settings.save" : "settings.saving")
3764
- })
3659
+ }) : null
3765
3660
  ]
3766
3661
  })
3767
- ]
3662
+ })]
3768
3663
  }) : null,
3769
3664
  open && editing !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChannelEditor, {
3770
3665
  t,
@@ -4000,14 +3895,13 @@ window.__ModuleLoader__.load({
4000
3895
  className: settings_card_module_css_default.label,
4001
3896
  htmlFor: "dsh-imagegen-channel-name",
4002
3897
  children: t("channels.displayName")
4003
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
3898
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_logictan_dsh_plugins_shared_client_client.TextField, {
4004
3899
  id: "dsh-imagegen-channel-name",
4005
- className: settings_card_module_css_default.input,
4006
3900
  value: channel.name,
4007
3901
  placeholder: t("channels.untitled"),
4008
3902
  disabled: !props.writable,
4009
- onChange: (event) => {
4010
- props.onPatch({ name: event.target.value });
3903
+ onValueChange: (next) => {
3904
+ props.onPatch({ name: next });
4011
3905
  }
4012
3906
  })]
4013
3907
  }),
@@ -4017,14 +3911,13 @@ window.__ModuleLoader__.load({
4017
3911
  className: settings_card_module_css_default.label,
4018
3912
  htmlFor: "dsh-imagegen-channel-url",
4019
3913
  children: t("channels.apiUrl")
4020
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
3914
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_logictan_dsh_plugins_shared_client_client.TextField, {
4021
3915
  id: "dsh-imagegen-channel-url",
4022
- className: settings_card_module_css_default.input,
4023
3916
  value: channel.apiUrl,
4024
3917
  placeholder: "https://api.example.com/v1",
4025
3918
  disabled: !props.writable,
4026
- onChange: (event) => {
4027
- props.onPatch({ apiUrl: event.target.value });
3919
+ onValueChange: (next) => {
3920
+ props.onPatch({ apiUrl: next });
4028
3921
  }
4029
3922
  })]
4030
3923
  }),
@@ -4046,18 +3939,17 @@ window.__ModuleLoader__.load({
4046
3939
  },
4047
3940
  children: t("channels.keyClear")
4048
3941
  }) : null]
4049
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
3942
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_logictan_dsh_plugins_shared_client_client.SecretField, {
4050
3943
  id: "dsh-imagegen-channel-key",
4051
- className: settings_card_module_css_default.input,
4052
- type: "password",
4053
3944
  autoComplete: "off",
4054
3945
  value: keyDraft,
3946
+ configured: props.keyHeld,
4055
3947
  placeholder: props.keyHeld ? t("channels.keyReplaceHint") : t("channels.keyMissingHint"),
4056
3948
  disabled: !props.writable,
4057
- onChange: (event) => {
4058
- const value = event.target.value;
4059
- setKeyDraft(value);
4060
- props.onSetKey(value === "" ? void 0 : value);
3949
+ onValueChange: (value) => {
3950
+ const next = value;
3951
+ setKeyDraft(next);
3952
+ props.onSetKey(next === "" ? void 0 : next);
4061
3953
  }
4062
3954
  })]
4063
3955
  }),
@@ -4067,9 +3959,10 @@ window.__ModuleLoader__.load({
4067
3959
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h4", {
4068
3960
  className: settings_card_module_css_default.label,
4069
3961
  children: t("channels.modelCatalogTitle")
4070
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
4071
- type: "button",
4072
- className: settings_card_module_css_default.modelFetch,
3962
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_logictan_dsh_plugins_shared_client_client.Button, {
3963
+ variant: "secondary",
3964
+ size: "sm",
3965
+ loading: detecting,
4073
3966
  disabled: !props.writable || detecting,
4074
3967
  onClick: detect,
4075
3968
  children: detecting ? t("channels.detecting") : t("channels.detect")
@@ -4097,16 +3990,15 @@ window.__ModuleLoader__.load({
4097
3990
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4098
3991
  className: settings_card_module_css_default.modelRowInputs,
4099
3992
  children: [
4100
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
4101
- className: settings_card_module_css_default.input,
3993
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_logictan_dsh_plugins_shared_client_client.TextField, {
4102
3994
  value: model.alias,
4103
3995
  "aria-label": t("channels.modelAliasLabel"),
4104
3996
  disabled: !props.writable,
4105
- onChange: (event) => {
3997
+ onValueChange: (text) => {
4106
3998
  const next = [...channel.models];
4107
3999
  next[index] = {
4108
4000
  ...model,
4109
- alias: event.target.value
4001
+ alias: text
4110
4002
  };
4111
4003
  props.onSetModels(next);
4112
4004
  }
@@ -4115,16 +4007,15 @@ window.__ModuleLoader__.load({
4115
4007
  className: settings_card_module_css_default.modelArrow,
4116
4008
  children: "→"
4117
4009
  }),
4118
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
4119
- className: settings_card_module_css_default.input,
4010
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_logictan_dsh_plugins_shared_client_client.TextField, {
4120
4011
  value: model.id,
4121
4012
  "aria-label": t("channels.modelIdLabel"),
4122
4013
  disabled: !props.writable,
4123
- onChange: (event) => {
4014
+ onValueChange: (text) => {
4124
4015
  const next = [...channel.models];
4125
4016
  next[index] = {
4126
4017
  ...model,
4127
- id: event.target.value
4018
+ id: text
4128
4019
  };
4129
4020
  props.onSetModels(next);
4130
4021
  }
@@ -4132,8 +4023,9 @@ window.__ModuleLoader__.load({
4132
4023
  ]
4133
4024
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4134
4025
  className: settings_card_module_css_default.modelRowBadges,
4135
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
4136
- className: settings_card_module_css_default.modelBadge,
4026
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_logictan_dsh_plugins_shared_client_client.Tag, {
4027
+ mono: true,
4028
+ kind: entry.known ? "idle" : "warn",
4137
4029
  children: [entry.labelZh, entry.known ? "" : ` · ${t("channels.unknownProtocol")}`]
4138
4030
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
4139
4031
  type: "button",
@@ -4153,47 +4045,41 @@ window.__ModuleLoader__.load({
4153
4045
  className: settings_card_module_css_default.editorTools,
4154
4046
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4155
4047
  className: settings_card_module_css_default.manualModelRow,
4156
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
4157
- className: settings_card_module_css_default.input,
4048
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_logictan_dsh_plugins_shared_client_client.TextField, {
4158
4049
  value: manualId,
4159
4050
  placeholder: t("channels.manualAddPlaceholder"),
4160
4051
  disabled: !props.writable,
4161
- onChange: (event) => {
4162
- setManualId(event.target.value);
4163
- },
4052
+ onValueChange: setManualId,
4164
4053
  onKeyDown: (event) => {
4165
4054
  if (event.key === "Enter") {
4166
4055
  event.preventDefault();
4167
4056
  addManual();
4168
4057
  }
4169
4058
  }
4170
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
4171
- type: "button",
4172
- className: settings_card_module_css_default.addModel,
4059
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_logictan_dsh_plugins_shared_client_client.Button, {
4060
+ variant: "secondary",
4061
+ size: "sm",
4173
4062
  disabled: !props.writable || manualId.trim() === "",
4174
4063
  onClick: addManual,
4175
4064
  children: t("channels.addModelConfirm")
4176
4065
  })]
4177
4066
  }), props.otherChannels.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4178
4067
  className: settings_card_module_css_default.manualModelRow,
4179
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
4180
- className: settings_card_module_css_default.modelChoices,
4068
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_logictan_dsh_plugins_shared_client_client.Select, {
4181
4069
  value: copyFrom,
4182
- disabled: !props.writable,
4183
- onChange: (event) => {
4184
- setCopyFrom(event.target.value);
4185
- },
4186
- "aria-label": t("channels.copyFrom"),
4187
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
4070
+ options: [{
4188
4071
  value: "",
4189
- children: t("channels.copyFrom")
4190
- }), props.otherChannels.map((other) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
4072
+ label: t("channels.copyFrom")
4073
+ }, ...props.otherChannels.map((other) => ({
4191
4074
  value: other.id,
4192
- children: other.name || t("channels.untitled")
4193
- }, other.id))]
4194
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
4195
- type: "button",
4196
- className: settings_card_module_css_default.addModel,
4075
+ label: other.name || t("channels.untitled")
4076
+ }))],
4077
+ disabled: !props.writable,
4078
+ onChange: setCopyFrom,
4079
+ label: t("channels.copyFrom")
4080
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_logictan_dsh_plugins_shared_client_client.Button, {
4081
+ variant: "secondary",
4082
+ size: "sm",
4197
4083
  disabled: !props.writable || copyFrom === "",
4198
4084
  onClick: copyFromChannel,
4199
4085
  children: t("channels.copyApply")
@@ -4208,32 +4094,29 @@ window.__ModuleLoader__.load({
4208
4094
  }), candidates.map((candidate) => {
4209
4095
  const selected = channel.models.some((model) => model.alias === candidate);
4210
4096
  const entry = describeModel(candidate);
4211
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
4097
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4212
4098
  className: settings_card_module_css_default.modelCandidate,
4213
4099
  "data-selected": selected ? "" : void 0,
4214
- children: [
4215
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
4216
- type: "checkbox",
4217
- checked: selected,
4218
- disabled: !props.writable,
4219
- onChange: () => {
4220
- const merged = selected ? channel.models.filter((model) => model.alias !== candidate) : [...channel.models, {
4221
- alias: candidate,
4222
- id: candidate
4223
- }];
4224
- props.onSetModels(merged);
4225
- }
4226
- }),
4227
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: candidate }),
4228
- !entry.known ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4229
- className: settings_card_module_css_default.modelBadge,
4230
- "data-warn": true,
4231
- children: t("channels.unknownProtocol")
4232
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4233
- className: settings_card_module_css_default.modelBadge,
4234
- children: entry.labelZh
4235
- })
4236
- ]
4100
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_logictan_dsh_plugins_shared_client_client.Checkbox, {
4101
+ checked: selected,
4102
+ disabled: !props.writable,
4103
+ onCheckedChange: () => {
4104
+ const merged = selected ? channel.models.filter((model) => model.alias !== candidate) : [...channel.models, {
4105
+ alias: candidate,
4106
+ id: candidate
4107
+ }];
4108
+ props.onSetModels(merged);
4109
+ },
4110
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: candidate })
4111
+ }), !entry.known ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_logictan_dsh_plugins_shared_client_client.Tag, {
4112
+ mono: true,
4113
+ kind: "warn",
4114
+ children: t("channels.unknownProtocol")
4115
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_logictan_dsh_plugins_shared_client_client.Tag, {
4116
+ mono: true,
4117
+ kind: "idle",
4118
+ children: entry.labelZh
4119
+ })]
4237
4120
  }, candidate);
4238
4121
  })]
4239
4122
  }) : null,
@@ -4241,9 +4124,8 @@ window.__ModuleLoader__.load({
4241
4124
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4242
4125
  className: settings_card_module_css_default.editorFooter,
4243
4126
  children: [
4244
- props.isDefault ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4245
- className: settings_card_module_css_default.channelBadge,
4246
- "data-default": true,
4127
+ props.isDefault ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_logictan_dsh_plugins_shared_client_client.Tag, {
4128
+ kind: "info",
4247
4129
  children: t("channels.defaultLabel")
4248
4130
  }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
4249
4131
  type: "button",
@@ -4253,23 +4135,22 @@ window.__ModuleLoader__.load({
4253
4135
  children: t("channels.setDefault")
4254
4136
  }),
4255
4137
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: settings_card_module_css_default.spacer }),
4256
- removeOpen ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
4257
- type: "button",
4258
- className: settings_card_module_css_default.channelDanger,
4138
+ removeOpen ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_logictan_dsh_plugins_shared_client_client.Button, {
4139
+ variant: "danger",
4140
+ size: "sm",
4259
4141
  disabled: !props.writable,
4260
4142
  onClick: props.onRemove,
4261
4143
  children: t("channels.confirm")
4262
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
4263
- type: "button",
4264
- className: settings_card_module_css_default.channelAction,
4144
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_logictan_dsh_plugins_shared_client_client.Button, {
4145
+ variant: "ghost",
4146
+ size: "sm",
4265
4147
  onClick: () => {
4266
4148
  setRemoveOpen(false);
4267
4149
  },
4268
4150
  children: t("channels.cancel")
4269
- })] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
4270
- type: "button",
4271
- className: settings_card_module_css_default.channelAction,
4272
- "data-danger": true,
4151
+ })] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_logictan_dsh_plugins_shared_client_client.Button, {
4152
+ variant: "danger",
4153
+ size: "sm",
4273
4154
  onClick: () => {
4274
4155
  setRemoveOpen(true);
4275
4156
  },
@@ -4296,8 +4177,9 @@ window.__ModuleLoader__.load({
4296
4177
  }),
4297
4178
  props.overridden ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
4298
4179
  className: settings_card_module_css_default.badges,
4299
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4300
- className: settings_card_module_css_default.badge,
4180
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_logictan_dsh_plugins_shared_client_client.Tag, {
4181
+ mono: true,
4182
+ kind: "info",
4301
4183
  children: props.overriddenLabel
4302
4184
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
4303
4185
  type: "button",
@@ -4316,77 +4198,26 @@ window.__ModuleLoader__.load({
4316
4198
  }) : null
4317
4199
  ]
4318
4200
  }),
4319
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
4201
+ props.secret === true ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_logictan_dsh_plugins_shared_client_client.SecretField, {
4320
4202
  id: props.id,
4321
- className: props.invalid ? settings_card_module_css_default.inputInvalid : settings_card_module_css_default.input,
4322
- type: props.secret === true ? "password" : "text",
4323
- autoComplete: props.secret === true ? "off" : void 0,
4324
- ...props.invalid ? { "aria-invalid": true } : {},
4203
+ autoComplete: "off",
4325
4204
  value: props.text,
4326
4205
  placeholder: props.placeholder ?? "",
4327
4206
  disabled: props.disabled,
4328
- onChange: (event) => {
4329
- props.onEdit(event.target.value);
4330
- }
4331
- }),
4332
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
4333
- className: props.invalid ? settings_card_module_css_default.invalid : settings_card_module_css_default.hint,
4334
- children: props.invalid ? props.invalidLabel : props.hint
4335
- })
4336
- ]
4337
- });
4338
- }
4339
- /** A staged boolean field: 继承 / 开 / 关. */
4340
- function BooleanField(props) {
4341
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4342
- className: settings_card_module_css_default.field,
4343
- children: [
4344
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4345
- className: settings_card_module_css_default.head,
4346
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
4347
- className: settings_card_module_css_default.label,
4348
- htmlFor: props.id,
4349
- children: props.label
4350
- }), props.overridden ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
4351
- className: settings_card_module_css_default.badges,
4352
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4353
- className: settings_card_module_css_default.badge,
4354
- children: props.overriddenLabel
4355
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
4356
- type: "button",
4357
- className: settings_card_module_css_default.reset,
4358
- disabled: props.disabled,
4359
- onClick: props.onReset,
4360
- children: props.resetLabel
4361
- })]
4362
- }) : null]
4363
- }),
4364
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
4207
+ invalid: props.invalid,
4208
+ configured: props.canClear,
4209
+ onValueChange: props.onEdit
4210
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_logictan_dsh_plugins_shared_client_client.TextField, {
4365
4211
  id: props.id,
4366
- className: settings_card_module_css_default.select,
4367
4212
  value: props.text,
4213
+ placeholder: props.placeholder ?? "",
4368
4214
  disabled: props.disabled,
4369
- onChange: (event) => {
4370
- props.onEdit(event.target.value);
4371
- },
4372
- children: [
4373
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
4374
- value: "",
4375
- children: props.inheritLabel
4376
- }),
4377
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
4378
- value: "true",
4379
- children: props.onLabel
4380
- }),
4381
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
4382
- value: "false",
4383
- children: props.offLabel
4384
- })
4385
- ]
4215
+ invalid: props.invalid,
4216
+ onValueChange: props.onEdit
4386
4217
  }),
4387
4218
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
4388
- className: settings_card_module_css_default.hint,
4389
- children: props.hint
4219
+ className: props.invalid ? settings_card_module_css_default.invalid : settings_card_module_css_default.hint,
4220
+ children: props.invalid ? props.invalidLabel : props.hint
4390
4221
  })
4391
4222
  ]
4392
4223
  });
@@ -4456,7 +4287,8 @@ window.__ModuleLoader__.load({
4456
4287
  user: void 0,
4457
4288
  revision: void 0,
4458
4289
  writable: false,
4459
- mode: "host"
4290
+ mode: "host",
4291
+ schema: void 0
4460
4292
  });
4461
4293
  this.keySet = (0, _deepseek_ai_dsh_client_store.createSnapshotStore)(false);
4462
4294
  this.secretSets = (0, _deepseek_ai_dsh_client_store.createSnapshotStore)({});
@@ -4488,26 +4320,39 @@ window.__ModuleLoader__.load({
4488
4320
  return this.enqueue(() => this.read());
4489
4321
  }
4490
4322
  set(field, value) {
4491
- return this.enqueue(() => this.writeOps([{
4492
- op: "set",
4493
- path: [field],
4494
- value
4495
- }]));
4323
+ return this.enqueue(async () => {
4324
+ await this.writeOps([{
4325
+ op: "set",
4326
+ path: [field],
4327
+ value
4328
+ }]);
4329
+ });
4496
4330
  }
4497
4331
  unset(field) {
4498
- return this.enqueue(() => this.writeOps([{
4499
- op: "unset",
4500
- path: [field]
4501
- }]));
4332
+ return this.enqueue(async () => {
4333
+ await this.writeOps([{
4334
+ op: "unset",
4335
+ path: [field]
4336
+ }]);
4337
+ });
4502
4338
  }
4339
+ /**
4340
+ * Apply path ops, resolving whether the write was accepted.
4341
+ *
4342
+ * The boolean is load-bearing for the shared form: it keeps the user's draft
4343
+ * on a refusal, so a rejected edit cannot look applied. A `void` here would
4344
+ * make every refusal silently read as success.
4345
+ */
4503
4346
  mutate(ops, expectedRevision) {
4504
- return this.enqueue(() => this.writeOps([...ops], expectedRevision));
4347
+ return this.enqueueWrite(() => this.writeOps([...ops], expectedRevision));
4505
4348
  }
4506
4349
  /** Apply several path ops in one revision-fenced mutate call (atomic save).
4507
4350
  * Path ops may address plain-object fields (e.g. `channelSecrets.<id>`),
4508
4351
  * but never navigate *inside* arrays — write array fields wholesale. */
4509
4352
  mutateOps(ops) {
4510
- return this.enqueue(() => this.writeOps(ops));
4353
+ return this.enqueue(async () => {
4354
+ await this.writeOps(ops);
4355
+ });
4511
4356
  }
4512
4357
  async dispose() {
4513
4358
  this.disposed = true;
@@ -4522,6 +4367,22 @@ window.__ModuleLoader__.load({
4522
4367
  this.tail = task.catch(() => {});
4523
4368
  return task;
4524
4369
  }
4370
+ /**
4371
+ * Queue a write that reports whether it was accepted.
4372
+ *
4373
+ * Separate from `enqueue` because that one is also used for reads, whose
4374
+ * caller has nothing to decide on. Serializing through the same `tail` keeps
4375
+ * one ordering for every request on this scope.
4376
+ */
4377
+ enqueueWrite(operation) {
4378
+ if (this.disposed) return Promise.resolve(false);
4379
+ const task = this.tail.then(async () => {
4380
+ if (this.disposed) return false;
4381
+ return operation();
4382
+ });
4383
+ this.tail = task.then(() => {}, () => {});
4384
+ return task;
4385
+ }
4525
4386
  async read() {
4526
4387
  let response;
4527
4388
  try {
@@ -4562,13 +4423,14 @@ window.__ModuleLoader__.load({
4562
4423
  });
4563
4424
  } catch {
4564
4425
  await this.read();
4565
- return;
4426
+ return false;
4566
4427
  }
4567
4428
  if (!response.result.ok || this.disposed) {
4568
4429
  await this.read();
4569
- return;
4430
+ return false;
4570
4431
  }
4571
4432
  this.accept(response.result.value, void 0);
4433
+ return true;
4572
4434
  }
4573
4435
  accept(view, writable) {
4574
4436
  this.store.update((draft) => {
@@ -4578,6 +4440,7 @@ window.__ModuleLoader__.load({
4578
4440
  if (writable !== void 0) draft.writable = writable;
4579
4441
  draft.status = "ready";
4580
4442
  draft.value = view.value;
4443
+ draft.schema = view.schema;
4581
4444
  });
4582
4445
  const secretSets = Object.fromEntries((view.secrets ?? []).map((secret) => [secret.path.join("."), secret.set]));
4583
4446
  this.keySet.set(Object.values(secretSets).some(Boolean));
@@ -4607,16 +4470,16 @@ window.__ModuleLoader__.load({
4607
4470
  document.head.appendChild(tag);
4608
4471
  }
4609
4472
  var image_toolview_module_css_default = {
4610
- "root": "UtJPoq_root",
4611
- "header": "UtJPoq_header",
4612
- "icon": "UtJPoq_icon",
4613
- "error": "UtJPoq_error",
4614
- "status": "UtJPoq_status",
4615
- "message": "UtJPoq_message",
4616
4473
  "images": "UtJPoq_images",
4617
4474
  "imageLink": "UtJPoq_imageLink",
4618
4475
  "image": "UtJPoq_image",
4619
- "loading": "UtJPoq_loading"
4476
+ "icon": "UtJPoq_icon",
4477
+ "message": "UtJPoq_message",
4478
+ "header": "UtJPoq_header",
4479
+ "loading": "UtJPoq_loading",
4480
+ "error": "UtJPoq_error",
4481
+ "root": "UtJPoq_root",
4482
+ "status": "UtJPoq_status"
4620
4483
  };
4621
4484
  //#endregion
4622
4485
  //#region src/client/image-toolview.tsx