dsh-audiogen 0.1.0 → 0.3.0

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
@@ -18,6 +18,8 @@ window.__ModuleLoader__.load({
18
18
  const GENERATE_API = "/api/dsh-audiogen/generate";
19
19
  /** Host-mediated built-in provider catalog (channels the user can instantiate). */
20
20
  const PRESETS_API = "/api/dsh-audiogen/presets";
21
+ /** Host-mediated model/voice discovery endpoint. */
22
+ const MODEL_API = { discover: "/api/dsh-audiogen/models/discover" };
21
23
  /** Host-persisted generation history routes. */
22
24
  const HISTORY_API = {
23
25
  list: "/api/dsh-audiogen/history/list",
@@ -91,7 +93,8 @@ window.__ModuleLoader__.load({
91
93
  "mode.tts": "文本转语音",
92
94
  "mode.music": "音乐生成",
93
95
  "mode.sfx": "音效生成",
94
- "prompt.placeholder": "输入要朗读的文本,或描述想生成的音乐 / 音效…",
96
+ "mode.voiceDesign": "音色设计",
97
+ "prompt.placeholder": "输入文本、音乐/音效描述,或音色设计描述…",
95
98
  "prompt.required": "请输入文本或提示词",
96
99
  "model.label": "模型 / 音色",
97
100
  "voice.label": "音色",
@@ -140,7 +143,7 @@ window.__ModuleLoader__.load({
140
143
  "channel.apiKey": "API 密钥",
141
144
  "channel.apiKeyHint": "留空则保持当前密钥;输入新值可更换。",
142
145
  "channel.models": "模型 / 音色(每行一个:别名=上游ID)",
143
- "channel.modelsHint": "例如 tts-1=tts-1 或 Rachel=21m00Tcm4TlvDq8ikWAM",
146
+ "channel.modelsHint": "每行格式:别名=上游ID,可加 @分类(tts/music/sfx/voice_design/voice_clone);例如 tts-1=tts-1 @tts 或 Rachel=21m00Tcm4TlvDq8ikWAM @tts",
144
147
  "channel.default": "设为默认",
145
148
  "channel.cancel": "取消",
146
149
  "channel.save": "保存渠道",
@@ -154,7 +157,8 @@ window.__ModuleLoader__.load({
154
157
  "mode.tts": "Text to speech",
155
158
  "mode.music": "Music",
156
159
  "mode.sfx": "Sound effects",
157
- "prompt.placeholder": "Text to speak, or a description of the music / sound effect…",
160
+ "mode.voiceDesign": "Voice design",
161
+ "prompt.placeholder": "Text to speak, or a music/SFX/voice-design description…",
158
162
  "prompt.required": "Prompt or text is required",
159
163
  "model.label": "Model / voice",
160
164
  "voice.label": "Voice",
@@ -203,7 +207,7 @@ window.__ModuleLoader__.load({
203
207
  "channel.apiKey": "API key",
204
208
  "channel.apiKeyHint": "Leave blank to keep the current key.",
205
209
  "channel.models": "Models / voices (one per line: alias=upstreamId)",
206
- "channel.modelsHint": "e.g. tts-1=tts-1 or Rachel=21m00Tcm4TlvDq8ikWAM",
210
+ "channel.modelsHint": "One per line: alias=upstreamId, optional @category (tts/music/sfx/voice_design/voice_clone); e.g. tts-1=tts-1 @tts or Rachel=21m00Tcm4TlvDq8ikWAM @tts",
207
211
  "channel.default": "Set default",
208
212
  "channel.cancel": "Cancel",
209
213
  "channel.save": "Save channel",
@@ -438,9 +442,17 @@ window.__ModuleLoader__.load({
438
442
  const defaultId = config?.defaultChannelId !== void 0 && channels.some((channel) => channel.id === config.defaultChannelId) ? config.defaultChannelId : channels[0].id;
439
443
  const ordered = [defaultId, ...channels.filter((channel) => channel.id !== defaultId).map((channel) => channel.id)];
440
444
  const models = [];
445
+ const seen = /* @__PURE__ */ new Set();
441
446
  for (const id of ordered) {
442
447
  const channel = channels.find((candidate) => candidate.id === id);
443
- for (const model of channel.models) if (model.alias !== "" && !models.includes(model.alias)) models.push(model.alias);
448
+ for (const model of channel.models) {
449
+ if (model.alias === "" || seen.has(model.alias)) continue;
450
+ seen.add(model.alias);
451
+ models.push({
452
+ alias: model.alias,
453
+ ...model.category === void 0 ? {} : { category: model.category }
454
+ });
455
+ }
444
456
  }
445
457
  return models.length > 0 ? {
446
458
  models,
@@ -462,38 +474,40 @@ window.__ModuleLoader__.load({
462
474
  document.head.appendChild(tag);
463
475
  }
464
476
  var audio_panel_module_css_default = {
465
- "download": "Oo1fpq_download",
477
+ "label": "Oo1fpq_label",
466
478
  "input": "Oo1fpq_input",
467
- "history": "Oo1fpq_history",
468
- "result": "Oo1fpq_result",
469
- "historyPrompt": "Oo1fpq_historyPrompt",
470
- "audioList": "Oo1fpq_audioList",
471
- "form": "Oo1fpq_form",
472
- "textarea": "Oo1fpq_textarea",
473
- "historyMeta": "Oo1fpq_historyMeta",
474
- "title": "Oo1fpq_title",
475
- "hint": "Oo1fpq_hint",
476
- "historyAudio": "Oo1fpq_historyAudio",
479
+ "panel": "Oo1fpq_panel",
477
480
  "historyTitle": "Oo1fpq_historyTitle",
478
- "header": "Oo1fpq_header",
479
- "audio": "Oo1fpq_audio",
480
- "label": "Oo1fpq_label",
481
- "empty": "Oo1fpq_empty",
481
+ "historyMeta": "Oo1fpq_historyMeta",
482
+ "historyEmpty": "Oo1fpq_historyEmpty",
482
483
  "generate": "Oo1fpq_generate",
483
- "audioCard": "Oo1fpq_audioCard",
484
+ "audioList": "Oo1fpq_audioList",
485
+ "hint": "Oo1fpq_hint",
486
+ "error": "Oo1fpq_error",
487
+ "download": "Oo1fpq_download",
488
+ "result": "Oo1fpq_result",
484
489
  "layout": "Oo1fpq_layout",
485
- "select": "Oo1fpq_select",
486
- "historyEmpty": "Oo1fpq_historyEmpty",
490
+ "history": "Oo1fpq_history",
487
491
  "historyItem": "Oo1fpq_historyItem",
488
- "error": "Oo1fpq_error",
492
+ "modeRow": "Oo1fpq_modeRow",
489
493
  "modeButton": "Oo1fpq_modeButton",
490
- "panel": "Oo1fpq_panel",
491
- "modeRow": "Oo1fpq_modeRow"
494
+ "historyAudio": "Oo1fpq_historyAudio",
495
+ "header": "Oo1fpq_header",
496
+ "textarea": "Oo1fpq_textarea",
497
+ "form": "Oo1fpq_form",
498
+ "title": "Oo1fpq_title",
499
+ "audioCard": "Oo1fpq_audioCard",
500
+ "empty": "Oo1fpq_empty",
501
+ "audio": "Oo1fpq_audio",
502
+ "historyPrompt": "Oo1fpq_historyPrompt",
503
+ "select": "Oo1fpq_select"
492
504
  };
493
505
  //#endregion
494
506
  //#region src/client/AudioGenPanel.tsx
495
507
  /**
496
508
  * The AI 音频 panel: a compact audio-generation studio.
509
+ * TTS / music / SFX / voice design are separated; each mode only lists
510
+ * compatible models and shows its own parameters.
497
511
  */
498
512
  function useConfig(scope) {
499
513
  const [value, setValue] = (0, react.useState)(scope.getSnapshot().value);
@@ -533,10 +547,11 @@ window.__ModuleLoader__.load({
533
547
  const channels = config?.channels ?? [];
534
548
  const connected = enabled && channels.some((channel) => {
535
549
  const keyHeld = scope.getSecretSetSnapshot(`channelSecrets.${channel.id}`);
536
- return channel.apiUrl.trim() !== "" && keyHeld && channel.models.length > 0;
550
+ return channel.apiUrl.trim() !== "" && keyHeld && (channel.models.length > 0 || channel.preset === "minimax");
537
551
  });
538
552
  const [mode, setMode] = (0, react.useState)("tts");
539
553
  const [prompt, setPrompt] = (0, react.useState)("");
554
+ const [previewText, setPreviewText] = (0, react.useState)("");
540
555
  const [model, setModel] = (0, react.useState)("");
541
556
  const [voice, setVoice] = (0, react.useState)("");
542
557
  const [speed, setSpeed] = (0, react.useState)("");
@@ -546,9 +561,13 @@ window.__ModuleLoader__.load({
546
561
  const [error, setError] = (0, react.useState)(null);
547
562
  const [outputs, setOutputs] = (0, react.useState)([]);
548
563
  const { entries, reload, clear } = useHistory();
564
+ const visibleModels = (0, react.useMemo)(() => {
565
+ if (mode === "voice_design") return [];
566
+ return modelOptions.models.filter((entry) => entry.category === void 0 || entry.category === "tts" && mode === "tts" || entry.category === mode).map((entry) => entry.alias);
567
+ }, [modelOptions.models, mode]);
549
568
  (0, react.useEffect)(() => {
550
- if (modelOptions.models.length > 0 && !modelOptions.models.includes(model)) setModel(modelOptions.models[0]);
551
- }, [modelOptions.models, model]);
569
+ if (visibleModels.length > 0 && !visibleModels.includes(model)) setModel(visibleModels[0]);
570
+ }, [visibleModels, model]);
552
571
  const submit = async () => {
553
572
  if (prompt.trim() === "") {
554
573
  setError(tt("prompt.required"));
@@ -559,8 +578,9 @@ window.__ModuleLoader__.load({
559
578
  try {
560
579
  const response = await api.generate({
561
580
  mode,
562
- model: (model || modelOptions.models[0]) ?? "",
581
+ model: (model || visibleModels[0]) ?? "",
563
582
  prompt: prompt.trim(),
583
+ ...previewText.trim() !== "" ? { previewText: previewText.trim() } : {},
564
584
  ...voice.trim() !== "" ? { voice: voice.trim() } : {},
565
585
  ...speed.trim() !== "" ? { speed: Number(speed) } : {},
566
586
  ...duration.trim() !== "" ? { duration: Number(duration) } : {},
@@ -581,8 +601,10 @@ window.__ModuleLoader__.load({
581
601
  const modeLabel = (0, react.useMemo)(() => {
582
602
  if (mode === "tts") return tt("mode.tts");
583
603
  if (mode === "music") return tt("mode.music");
584
- return tt("mode.sfx");
604
+ if (mode === "sfx") return tt("mode.sfx");
605
+ return tt("mode.voiceDesign");
585
606
  }, [mode]);
607
+ const needModel = mode !== "voice_design";
586
608
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
587
609
  className: audio_panel_module_css_default.panel,
588
610
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", {
@@ -605,39 +627,49 @@ window.__ModuleLoader__.load({
605
627
  children: [
606
628
  "tts",
607
629
  "music",
608
- "sfx"
630
+ "sfx",
631
+ "voice_design"
609
632
  ].map((item) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
610
633
  type: "button",
611
634
  className: audio_panel_module_css_default.modeButton,
612
635
  "data-active": mode === item ? "true" : "false",
613
636
  onClick: () => setMode(item),
614
- children: item === "tts" ? tt("mode.tts") : item === "music" ? tt("mode.music") : tt("mode.sfx")
637
+ children: item === "tts" ? tt("mode.tts") : item === "music" ? tt("mode.music") : item === "sfx" ? tt("mode.sfx") : tt("mode.voiceDesign")
615
638
  }, item))
616
639
  }),
617
640
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
618
641
  className: audio_panel_module_css_default.label,
619
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: mode === "tts" ? "文本" : "提示词" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
642
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: mode === "voice_design" ? "音色描述" : mode === "tts" ? "文本" : "提示词" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
620
643
  className: audio_panel_module_css_default.textarea,
621
644
  value: prompt,
622
645
  onChange: (event) => setPrompt(event.target.value),
623
646
  placeholder: tt("prompt.placeholder")
624
647
  })]
625
648
  }),
626
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
649
+ mode === "voice_design" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
650
+ className: audio_panel_module_css_default.label,
651
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "试听文本" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
652
+ className: audio_panel_module_css_default.input,
653
+ value: previewText,
654
+ onChange: (event) => setPreviewText(event.target.value),
655
+ placeholder: "你好,这是新设计的音色试听。"
656
+ })]
657
+ }) : null,
658
+ needModel ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
627
659
  className: audio_panel_module_css_default.label,
628
660
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: tt("model.label") }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
629
661
  className: audio_panel_module_css_default.select,
630
662
  value: model,
631
663
  onChange: (event) => setModel(event.target.value),
632
- children: [modelOptions.models.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
664
+ children: [visibleModels.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
633
665
  value: "",
634
- children: "(请在设置中添加)"
635
- }) : null, modelOptions.models.map((item) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
666
+ children: "(当前模式暂无可用模型)"
667
+ }) : null, visibleModels.map((item) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
636
668
  value: item,
637
669
  children: item
638
670
  }, item))]
639
671
  })]
640
- }),
672
+ }) : null,
641
673
  mode === "tts" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
642
674
  className: audio_panel_module_css_default.label,
643
675
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: tt("voice.label") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
@@ -647,7 +679,7 @@ window.__ModuleLoader__.load({
647
679
  placeholder: "alloy / 自定义音色"
648
680
  })]
649
681
  }) : null,
650
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
682
+ mode === "tts" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
651
683
  className: audio_panel_module_css_default.label,
652
684
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: tt("speed.label") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
653
685
  className: audio_panel_module_css_default.input,
@@ -659,8 +691,8 @@ window.__ModuleLoader__.load({
659
691
  onChange: (event) => setSpeed(event.target.value),
660
692
  placeholder: "1.0"
661
693
  })]
662
- }),
663
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
694
+ }) : null,
695
+ mode === "music" || mode === "sfx" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
664
696
  className: audio_panel_module_css_default.label,
665
697
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: tt("duration.label") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
666
698
  className: audio_panel_module_css_default.input,
@@ -672,8 +704,8 @@ window.__ModuleLoader__.load({
672
704
  onChange: (event) => setDuration(event.target.value),
673
705
  placeholder: "30"
674
706
  })]
675
- }),
676
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
707
+ }) : null,
708
+ needModel ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
677
709
  className: audio_panel_module_css_default.label,
678
710
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: tt("format.label") }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
679
711
  className: audio_panel_module_css_default.select,
@@ -702,7 +734,7 @@ window.__ModuleLoader__.load({
702
734
  })
703
735
  ]
704
736
  })]
705
- }),
737
+ }) : null,
706
738
  !connected && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
707
739
  className: audio_panel_module_css_default.hint,
708
740
  children: tt("config.missing")
@@ -710,7 +742,7 @@ window.__ModuleLoader__.load({
710
742
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
711
743
  type: "button",
712
744
  className: audio_panel_module_css_default.generate,
713
- disabled: loading || !connected,
745
+ disabled: loading || !connected || needModel && visibleModels.length === 0,
714
746
  onClick: () => void submit(),
715
747
  children: loading ? tt("generating") : tt("generate")
716
748
  })
@@ -731,17 +763,24 @@ window.__ModuleLoader__.load({
731
763
  className: audio_panel_module_css_default.audioList,
732
764
  children: outputs.map((audio, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
733
765
  className: audio_panel_module_css_default.audioCard,
734
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("audio", {
735
- className: audio_panel_module_css_default.audio,
736
- controls: true,
737
- preload: "metadata",
738
- src: dataUrlOf(audio)
739
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
740
- className: audio_panel_module_css_default.download,
741
- href: dataUrlOf(audio),
742
- download: `generated-${index + 1}.${audio.mime.split("/")[1]?.replace("mpeg", "mp3") ?? "mp3"}`,
743
- children: "下载"
744
- })]
766
+ children: [
767
+ audio.voiceId !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
768
+ className: audio_panel_module_css_default.hint,
769
+ children: ["新音色 ID:", audio.voiceId]
770
+ }) : null,
771
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("audio", {
772
+ className: audio_panel_module_css_default.audio,
773
+ controls: true,
774
+ preload: "metadata",
775
+ src: dataUrlOf(audio)
776
+ }),
777
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
778
+ className: audio_panel_module_css_default.download,
779
+ href: dataUrlOf(audio),
780
+ download: `generated-${index + 1}.${audio.mime.split("/")[1]?.replace("mpeg", "mp3") ?? "mp3"}`,
781
+ children: "下载"
782
+ })
783
+ ]
745
784
  }, audio.id))
746
785
  })] })]
747
786
  }),
@@ -808,167 +847,167 @@ window.__ModuleLoader__.load({
808
847
  document.head.appendChild(tag);
809
848
  }
810
849
  var panel_module_css_default = {
811
- "galleryBadge": "rwa6qG_galleryBadge",
812
- "taskTrayChevron": "rwa6qG_taskTrayChevron",
813
- "referenceImage": "rwa6qG_referenceImage",
814
- "galleryClear": "rwa6qG_galleryClear",
815
- "canvasEmptyIcon": "rwa6qG_canvasEmptyIcon",
816
- "lightboxScaleFrame": "rwa6qG_lightboxScaleFrame",
817
- "lightboxNav": "rwa6qG_lightboxNav",
818
- "reference": "rwa6qG_reference",
819
- "modelLabel": "rwa6qG_modelLabel",
820
- "optionRow": "rwa6qG_optionRow",
850
+ "referenceActions": "rwa6qG_referenceActions",
851
+ "taskRows": "rwa6qG_taskRows",
852
+ "canvasError": "rwa6qG_canvasError",
853
+ "galleryRatioList": "rwa6qG_galleryRatioList",
854
+ "historyTitle": "rwa6qG_historyTitle",
855
+ "studio": "rwa6qG_studio",
856
+ "taskRow": "rwa6qG_taskRow",
821
857
  "templatesButton": "rwa6qG_templatesButton",
822
- "view": "rwa6qG_view",
823
- "gallerySelectMode": "rwa6qG_gallerySelectMode",
824
- "configScroll": "rwa6qG_configScroll",
825
- "modePill": "rwa6qG_modePill",
826
- "galleryTagFilter": "rwa6qG_galleryTagFilter",
827
- "galleryRemove": "rwa6qG_galleryRemove",
828
858
  "gallerySearch": "rwa6qG_gallerySearch",
829
- "connectionStatus": "rwa6qG_connectionStatus",
830
- "bigSpinner": "rwa6qG_bigSpinner",
831
- "referenceActions": "rwa6qG_referenceActions",
832
- "lightboxImage": "rwa6qG_lightboxImage",
833
- "historyActions": "rwa6qG_historyActions",
834
- "galleryViewToggle": "rwa6qG_galleryViewToggle",
835
- "connectionDot": "rwa6qG_connectionDot",
836
- "githubLink": "rwa6qG_githubLink",
837
- "updateActions": "rwa6qG_updateActions",
838
- "panel": "rwa6qG_panel",
839
- "grid": "rwa6qG_grid",
840
- "galleryMasonry": "rwa6qG_galleryMasonry",
841
- "updateBanner": "rwa6qG_updateBanner",
842
- "entry": "rwa6qG_entry",
843
859
  "taskTray": "rwa6qG_taskTray",
844
- "galleryBulkButton": "rwa6qG_galleryBulkButton",
845
- "canvasHistoryTag": "rwa6qG_canvasHistoryTag",
846
- "promptCount": "rwa6qG_promptCount",
847
- "lightboxFigure": "rwa6qG_lightboxFigure",
848
- "taskStatus": "rwa6qG_taskStatus",
849
- "lightboxCaption": "rwa6qG_lightboxCaption",
850
- "canvasMeta": "rwa6qG_canvasMeta",
851
- "compareModelChoices": "rwa6qG_compareModelChoices",
852
- "comparisonFullscreenGrid": "rwa6qG_comparisonFullscreenGrid",
853
- "historyPrompt": "rwa6qG_historyPrompt",
854
- "panelTitle": "rwa6qG_panelTitle",
855
- "historyMain": "rwa6qG_historyMain",
856
- "studio": "rwa6qG_studio",
860
+ "updateActions": "rwa6qG_updateActions",
861
+ "paramHint": "rwa6qG_paramHint",
862
+ "connectionDot": "rwa6qG_connectionDot",
857
863
  "panelHeading": "rwa6qG_panelHeading",
858
- "prompt": "rwa6qG_prompt",
859
- "dshImageGenSpin": "rwa6qG_dshImageGenSpin",
860
- "taskTrayClose": "rwa6qG_taskTrayClose",
861
- "lightboxActions": "rwa6qG_lightboxActions",
862
- "gallerySelectionClear": "rwa6qG_gallerySelectionClear",
864
+ "historyClear": "rwa6qG_historyClear",
865
+ "panelHeader": "rwa6qG_panelHeader",
866
+ "modePill": "rwa6qG_modePill",
867
+ "historyInfo": "rwa6qG_historyInfo",
868
+ "canvasState": "rwa6qG_canvasState",
869
+ "canvasStateTitle": "rwa6qG_canvasStateTitle",
870
+ "card": "rwa6qG_card",
871
+ "dshImageGenToastIn": "rwa6qG_dshImageGenToastIn",
872
+ "configGuideBody": "rwa6qG_configGuideBody",
873
+ "modelMenuItem": "rwa6qG_modelMenuItem",
874
+ "galleryRatio": "rwa6qG_galleryRatio",
875
+ "galleryTagFilterList": "rwa6qG_galleryTagFilterList",
876
+ "comparisonImageButton": "rwa6qG_comparisonImageButton",
877
+ "comparisonFullscreenGrid": "rwa6qG_comparisonFullscreenGrid",
878
+ "promptFooter": "rwa6qG_promptFooter",
879
+ "galleryFilter": "rwa6qG_galleryFilter",
863
880
  "gallerySelect": "rwa6qG_gallerySelect",
864
- "galleryCardInfo": "rwa6qG_galleryCardInfo",
865
- "galleryCount": "rwa6qG_galleryCount",
866
- "galleryTagInput": "rwa6qG_galleryTagInput",
867
- "config": "rwa6qG_config",
868
- "galleryFilterCount": "rwa6qG_galleryFilterCount",
869
- "galleryRatioList": "rwa6qG_galleryRatioList",
870
- "configGuide": "rwa6qG_configGuide",
881
+ "galleryMasonry": "rwa6qG_galleryMasonry",
871
882
  "historyFilters": "rwa6qG_historyFilters",
883
+ "history": "rwa6qG_history",
884
+ "uploadIcon": "rwa6qG_uploadIcon",
885
+ "historyAction": "rwa6qG_historyAction",
886
+ "lightboxCopy": "rwa6qG_lightboxCopy",
887
+ "comparisonBoard": "rwa6qG_comparisonBoard",
888
+ "historyEmpty": "rwa6qG_historyEmpty",
889
+ "galleryTagFilter": "rwa6qG_galleryTagFilter",
890
+ "image": "rwa6qG_image",
891
+ "canvasStateHint": "rwa6qG_canvasStateHint",
892
+ "galleryAdd": "rwa6qG_galleryAdd",
893
+ "config": "rwa6qG_config",
894
+ "lightboxActions": "rwa6qG_lightboxActions",
872
895
  "galleryTags": "rwa6qG_galleryTags",
873
- "modelMenuItem": "rwa6qG_modelMenuItem",
874
- "uploadHint": "rwa6qG_uploadHint",
875
- "gallerySort": "rwa6qG_gallerySort",
876
- "galleryImage": "rwa6qG_galleryImage",
877
- "taskRows": "rwa6qG_taskRows",
878
- "taskTrayHeader": "rwa6qG_taskTrayHeader",
879
- "paramHint": "rwa6qG_paramHint",
880
- "imageCard": "rwa6qG_imageCard",
896
+ "generateButton": "rwa6qG_generateButton",
897
+ "panelTitle": "rwa6qG_panelTitle",
898
+ "historyThumbPlaceholder": "rwa6qG_historyThumbPlaceholder",
899
+ "historyMain": "rwa6qG_historyMain",
900
+ "canvasMeta": "rwa6qG_canvasMeta",
881
901
  "download": "rwa6qG_download",
882
- "historyHeader": "rwa6qG_historyHeader",
883
- "taskPrompt": "rwa6qG_taskPrompt",
884
- "canvasError": "rwa6qG_canvasError",
885
- "modeRow": "rwa6qG_modeRow",
886
- "paramGroup": "rwa6qG_paramGroup",
887
- "galleryFilter": "rwa6qG_galleryFilter",
888
- "galleryTagFilterList": "rwa6qG_galleryTagFilterList",
889
- "lightboxEdit": "rwa6qG_lightboxEdit",
890
- "history": "rwa6qG_history",
891
- "historyClear": "rwa6qG_historyClear",
892
- "generateInner": "rwa6qG_generateInner",
893
- "lightboxMeta": "rwa6qG_lightboxMeta",
894
- "galleryFilterHeading": "rwa6qG_galleryFilterHeading",
902
+ "prompt": "rwa6qG_prompt",
895
903
  "entryLabel": "rwa6qG_entryLabel",
904
+ "galleryToast": "rwa6qG_galleryToast",
905
+ "optionPill": "rwa6qG_optionPill",
906
+ "lightboxScaleFrame": "rwa6qG_lightboxScaleFrame",
907
+ "galleryHeading": "rwa6qG_galleryHeading",
908
+ "compareControl": "rwa6qG_compareControl",
909
+ "imageCaption": "rwa6qG_imageCaption",
910
+ "promptCount": "rwa6qG_promptCount",
911
+ "lightboxStage": "rwa6qG_lightboxStage",
912
+ "updateRelease": "rwa6qG_updateRelease",
913
+ "lightboxDownload": "rwa6qG_lightboxDownload",
914
+ "gallerySelectMode": "rwa6qG_gallerySelectMode",
896
915
  "compareToggle": "rwa6qG_compareToggle",
897
- "uploadIcon": "rwa6qG_uploadIcon",
916
+ "grid": "rwa6qG_grid",
917
+ "zoomHint": "rwa6qG_zoomHint",
918
+ "modelSelect": "rwa6qG_modelSelect",
919
+ "modelMenu": "rwa6qG_modelMenu",
920
+ "lightboxFigure": "rwa6qG_lightboxFigure",
921
+ "lightboxTools": "rwa6qG_lightboxTools",
922
+ "compareModelChoices": "rwa6qG_compareModelChoices",
923
+ "gallerySelectionClear": "rwa6qG_gallerySelectionClear",
924
+ "lightboxMeta": "rwa6qG_lightboxMeta",
925
+ "taskPrompt": "rwa6qG_taskPrompt",
926
+ "modelWrap": "rwa6qG_modelWrap",
927
+ "updateBanner": "rwa6qG_updateBanner",
928
+ "configGuide": "rwa6qG_configGuide",
929
+ "modelLabel": "rwa6qG_modelLabel",
930
+ "historyMeta": "rwa6qG_historyMeta",
931
+ "galleryBulkButton": "rwa6qG_galleryBulkButton",
932
+ "generateInner": "rwa6qG_generateInner",
933
+ "lightboxImage": "rwa6qG_lightboxImage",
934
+ "lightboxClose": "rwa6qG_lightboxClose",
935
+ "entryIcon": "rwa6qG_entryIcon",
936
+ "historyHeader": "rwa6qG_historyHeader",
937
+ "view": "rwa6qG_view",
938
+ "galleryWorkspace": "rwa6qG_galleryWorkspace",
898
939
  "galleryAvatar": "rwa6qG_galleryAvatar",
899
- "galleryImageButton": "rwa6qG_galleryImageButton",
900
- "modelMenuList": "rwa6qG_modelMenuList",
901
- "historyThumb": "rwa6qG_historyThumb",
902
- "lightboxZoomLevel": "rwa6qG_lightboxZoomLevel",
940
+ "taskTrayChevron": "rwa6qG_taskTrayChevron",
903
941
  "canvas": "rwa6qG_canvas",
904
- "taskRow": "rwa6qG_taskRow",
905
- "canvasState": "rwa6qG_canvasState",
906
- "canvasStateTitle": "rwa6qG_canvasStateTitle",
907
- "canvasStateHint": "rwa6qG_canvasStateHint",
908
- "galleryToast": "rwa6qG_galleryToast",
909
- "galleryRatio": "rwa6qG_galleryRatio",
910
- "historyInfo": "rwa6qG_historyInfo",
911
- "card": "rwa6qG_card",
912
- "enhanceButton": "rwa6qG_enhanceButton",
913
- "updateText": "rwa6qG_updateText",
914
- "historyThumbPlaceholder": "rwa6qG_historyThumbPlaceholder",
915
- "galleryHeading": "rwa6qG_galleryHeading",
942
+ "lightboxEdit": "rwa6qG_lightboxEdit",
943
+ "taskTrayCount": "rwa6qG_taskTrayCount",
944
+ "taskTrayToggle": "rwa6qG_taskTrayToggle",
945
+ "galleryCardInfo": "rwa6qG_galleryCardInfo",
946
+ "imageCard": "rwa6qG_imageCard",
947
+ "galleryCount": "rwa6qG_galleryCount",
948
+ "galleryTagEdit": "rwa6qG_galleryTagEdit",
949
+ "historySearch": "rwa6qG_historySearch",
950
+ "historyActions": "rwa6qG_historyActions",
951
+ "lightboxZoomLevel": "rwa6qG_lightboxZoomLevel",
952
+ "reference": "rwa6qG_reference",
953
+ "historyPrompt": "rwa6qG_historyPrompt",
954
+ "galleryFilterNote": "rwa6qG_galleryFilterNote",
955
+ "taskTrayHeader": "rwa6qG_taskTrayHeader",
956
+ "galleryImage": "rwa6qG_galleryImage",
957
+ "comparisonFullscreen": "rwa6qG_comparisonFullscreen",
958
+ "galleryClear": "rwa6qG_galleryClear",
959
+ "footer": "rwa6qG_footer",
960
+ "canvasHistoryTag": "rwa6qG_canvasHistoryTag",
961
+ "uploadBox": "rwa6qG_uploadBox",
962
+ "hiddenFile": "rwa6qG_hiddenFile",
963
+ "dshImageGenSpin": "rwa6qG_dshImageGenSpin",
964
+ "optionRow": "rwa6qG_optionRow",
965
+ "comparisonGrid": "rwa6qG_comparisonGrid",
966
+ "galleryRemove": "rwa6qG_galleryRemove",
967
+ "panel": "rwa6qG_panel",
968
+ "updateText": "rwa6qG_updateText",
969
+ "lightboxNav": "rwa6qG_lightboxNav",
970
+ "galleryFilterHeading": "rwa6qG_galleryFilterHeading",
971
+ "paramLabel": "rwa6qG_paramLabel",
972
+ "taskTrayClose": "rwa6qG_taskTrayClose",
973
+ "gallerySort": "rwa6qG_gallerySort",
916
974
  "galleryTagEditor": "rwa6qG_galleryTagEditor",
917
- "modelSelect": "rwa6qG_modelSelect",
918
- "promptFooter": "rwa6qG_promptFooter",
919
- "zoomHint": "rwa6qG_zoomHint",
920
- "lightboxClose": "rwa6qG_lightboxClose",
921
- "historyMeta": "rwa6qG_historyMeta",
922
- "galleryWorkspace": "rwa6qG_galleryWorkspace",
923
- "footer": "rwa6qG_footer",
924
- "updateRelease": "rwa6qG_updateRelease",
925
- "optionPill": "rwa6qG_optionPill",
975
+ "lightboxCaptionRow": "rwa6qG_lightboxCaptionRow",
926
976
  "historyList": "rwa6qG_historyList",
927
- "generateButton": "rwa6qG_generateButton",
977
+ "galleryTagInput": "rwa6qG_galleryTagInput",
978
+ "lightboxIndex": "rwa6qG_lightboxIndex",
979
+ "galleryFilterCount": "rwa6qG_galleryFilterCount",
928
980
  "galleryFilterDivider": "rwa6qG_galleryFilterDivider",
929
- "galleryFilters": "rwa6qG_galleryFilters",
930
- "historyEmpty": "rwa6qG_historyEmpty",
931
- "canvasBody": "rwa6qG_canvasBody",
932
- "galleryToolbar": "rwa6qG_galleryToolbar",
933
- "historyTitle": "rwa6qG_historyTitle",
934
- "image": "rwa6qG_image",
981
+ "enhanceButton": "rwa6qG_enhanceButton",
982
+ "historyItem": "rwa6qG_historyItem",
983
+ "uploadHint": "rwa6qG_uploadHint",
984
+ "connectionStatus": "rwa6qG_connectionStatus",
985
+ "modeRow": "rwa6qG_modeRow",
986
+ "modelMenuList": "rwa6qG_modelMenuList",
987
+ "spinner": "rwa6qG_spinner",
988
+ "lightbox": "rwa6qG_lightbox",
989
+ "githubLink": "rwa6qG_githubLink",
935
990
  "lightboxTool": "rwa6qG_lightboxTool",
991
+ "historyThumb": "rwa6qG_historyThumb",
992
+ "canvasEmptyIcon": "rwa6qG_canvasEmptyIcon",
993
+ "lightboxCaption": "rwa6qG_lightboxCaption",
994
+ "bigSpinner": "rwa6qG_bigSpinner",
995
+ "optionGrid": "rwa6qG_optionGrid",
996
+ "taskStatus": "rwa6qG_taskStatus",
997
+ "configScroll": "rwa6qG_configScroll",
936
998
  "gallerySelectionBar": "rwa6qG_gallerySelectionBar",
999
+ "galleryImageButton": "rwa6qG_galleryImageButton",
937
1000
  "galleryCard": "rwa6qG_galleryCard",
938
- "entryIcon": "rwa6qG_entryIcon",
939
- "lightbox": "rwa6qG_lightbox",
940
- "optionGrid": "rwa6qG_optionGrid",
941
- "lightboxTools": "rwa6qG_lightboxTools",
942
- "lightboxIndex": "rwa6qG_lightboxIndex",
943
- "panelHeader": "rwa6qG_panelHeader",
944
- "spinner": "rwa6qG_spinner",
945
- "lightboxStage": "rwa6qG_lightboxStage",
946
- "galleryFilterNote": "rwa6qG_galleryFilterNote",
947
- "dshImageGenToastIn": "rwa6qG_dshImageGenToastIn",
948
- "comparisonGrid": "rwa6qG_comparisonGrid",
949
- "historyItem": "rwa6qG_historyItem",
950
- "lightboxCaptionRow": "rwa6qG_lightboxCaptionRow",
951
- "modelMenu": "rwa6qG_modelMenu",
952
- "paramLabel": "rwa6qG_paramLabel",
953
- "taskTrayToggle": "rwa6qG_taskTrayToggle",
954
- "uploadBox": "rwa6qG_uploadBox",
955
- "configGuideBody": "rwa6qG_configGuideBody",
956
- "hiddenFile": "rwa6qG_hiddenFile",
957
- "lightboxCopy": "rwa6qG_lightboxCopy",
958
- "galleryAdd": "rwa6qG_galleryAdd",
959
- "imageCaption": "rwa6qG_imageCaption",
960
- "historySearch": "rwa6qG_historySearch",
961
- "lightboxDownload": "rwa6qG_lightboxDownload",
1001
+ "referenceImage": "rwa6qG_referenceImage",
1002
+ "entry": "rwa6qG_entry",
1003
+ "galleryFilters": "rwa6qG_galleryFilters",
962
1004
  "galleryToolbarActions": "rwa6qG_galleryToolbarActions",
963
- "taskTrayCount": "rwa6qG_taskTrayCount",
964
- "comparisonFullscreen": "rwa6qG_comparisonFullscreen",
965
- "galleryTagEdit": "rwa6qG_galleryTagEdit",
966
- "comparisonImageButton": "rwa6qG_comparisonImageButton",
967
- "compareControl": "rwa6qG_compareControl",
968
- "historyAction": "rwa6qG_historyAction",
969
- "comparisonBoard": "rwa6qG_comparisonBoard",
970
- "modelWrap": "rwa6qG_modelWrap",
971
- "galleryCardFooter": "rwa6qG_galleryCardFooter"
1005
+ "canvasBody": "rwa6qG_canvasBody",
1006
+ "galleryBadge": "rwa6qG_galleryBadge",
1007
+ "paramGroup": "rwa6qG_paramGroup",
1008
+ "galleryCardFooter": "rwa6qG_galleryCardFooter",
1009
+ "galleryToolbar": "rwa6qG_galleryToolbar",
1010
+ "galleryViewToggle": "rwa6qG_galleryViewToggle"
972
1011
  };
973
1012
  //#endregion
974
1013
  //#region src/client/mount.tsx
@@ -1408,7 +1447,8 @@ window.__ModuleLoader__.load({
1408
1447
  function stripChannel(channel) {
1409
1448
  const models = channel.models.map((model) => ({
1410
1449
  alias: model.alias.trim(),
1411
- id: model.id.trim() === "" ? model.alias.trim() : model.id.trim()
1450
+ id: model.id.trim() === "" ? model.alias.trim() : model.id.trim(),
1451
+ ...model.category === void 0 ? {} : { category: model.category }
1412
1452
  })).filter((model) => model.alias !== "");
1413
1453
  return {
1414
1454
  id: channel.id,
@@ -1624,97 +1664,97 @@ window.__ModuleLoader__.load({
1624
1664
  document.head.appendChild(tag);
1625
1665
  }
1626
1666
  var settings_card_module_css_default = {
1627
- "channelDotWarn": "zmjoSq_channelDotWarn",
1628
- "badge": "zmjoSq_badge",
1629
- "invalid": "zmjoSq_invalid",
1630
- "footer": "zmjoSq_footer",
1667
+ "label": "zmjoSq_label",
1668
+ "optionalContent": "zmjoSq_optionalContent",
1631
1669
  "channelAdd": "zmjoSq_channelAdd",
1632
- "editorClose": "zmjoSq_editorClose",
1633
1670
  "modelRowRemove": "zmjoSq_modelRowRemove",
1634
- "inlineDisclosure": "zmjoSq_inlineDisclosure",
1635
- "channelName": "zmjoSq_channelName",
1636
- "field": "zmjoSq_field",
1637
- "reset": "zmjoSq_reset",
1638
- "chevronOpen": "zmjoSq_chevronOpen",
1639
- "textarea": "zmjoSq_textarea",
1671
+ "description": "zmjoSq_description",
1672
+ "head": "zmjoSq_head",
1673
+ "modelCandidateList": "zmjoSq_modelCandidateList",
1674
+ "presetHint": "zmjoSq_presetHint",
1675
+ "select": "zmjoSq_select",
1640
1676
  "notExposed": "zmjoSq_notExposed",
1677
+ "sectionHint": "zmjoSq_sectionHint",
1678
+ "editorFooter": "zmjoSq_editorFooter",
1679
+ "modelRowBadges": "zmjoSq_modelRowBadges",
1680
+ "modelFetchRow": "zmjoSq_modelFetchRow",
1681
+ "editorPanel": "zmjoSq_editorPanel",
1682
+ "disclosure": "zmjoSq_disclosure",
1641
1683
  "sectionHeader": "zmjoSq_sectionHeader",
1642
- "optionalContent": "zmjoSq_optionalContent",
1684
+ "save": "zmjoSq_save",
1685
+ "channelSection": "zmjoSq_channelSection",
1686
+ "manualModelRow": "zmjoSq_manualModelRow",
1687
+ "modelSection": "zmjoSq_modelSection",
1688
+ "field": "zmjoSq_field",
1689
+ "deleteConfirmText": "zmjoSq_deleteConfirmText",
1690
+ "modelSummary": "zmjoSq_modelSummary",
1643
1691
  "channelAddRow": "zmjoSq_channelAddRow",
1692
+ "channelMeta": "zmjoSq_channelMeta",
1693
+ "editorTools": "zmjoSq_editorTools",
1694
+ "hint": "zmjoSq_hint",
1695
+ "editorClose": "zmjoSq_editorClose",
1696
+ "modelFetch": "zmjoSq_modelFetch",
1697
+ "sectionTitle": "zmjoSq_sectionTitle",
1644
1698
  "channelEmpty": "zmjoSq_channelEmpty",
1645
- "channelDanger": "zmjoSq_channelDanger",
1646
- "editorField": "zmjoSq_editorField",
1647
- "chevron": "zmjoSq_chevron",
1648
- "sectionHint": "zmjoSq_sectionHint",
1649
- "modelCandidateList": "zmjoSq_modelCandidateList",
1650
- "save": "zmjoSq_save",
1651
- "header": "zmjoSq_header",
1652
- "addModel": "zmjoSq_addModel",
1653
- "name": "zmjoSq_name",
1654
- "discard": "zmjoSq_discard",
1655
- "editorHeader": "zmjoSq_editorHeader",
1699
+ "readOnly": "zmjoSq_readOnly",
1700
+ "channelAction": "zmjoSq_channelAction",
1701
+ "failed": "zmjoSq_failed",
1702
+ "channelControls": "zmjoSq_channelControls",
1703
+ "presetRow": "zmjoSq_presetRow",
1704
+ "headText": "zmjoSq_headText",
1705
+ "versionRow": "zmjoSq_versionRow",
1706
+ "modelCandidate": "zmjoSq_modelCandidate",
1707
+ "channelDotReady": "zmjoSq_channelDotReady",
1708
+ "channelDotWarn": "zmjoSq_channelDotWarn",
1709
+ "footer": "zmjoSq_footer",
1710
+ "channelHost": "zmjoSq_channelHost",
1711
+ "channelRow": "zmjoSq_channelRow",
1656
1712
  "channelMain": "zmjoSq_channelMain",
1657
- "detectOk": "zmjoSq_detectOk",
1713
+ "editorField": "zmjoSq_editorField",
1714
+ "modelRows": "zmjoSq_modelRows",
1658
1715
  "presetMeta": "zmjoSq_presetMeta",
1659
- "channelBadge": "zmjoSq_channelBadge",
1660
- "channelMeta": "zmjoSq_channelMeta",
1716
+ "reset": "zmjoSq_reset",
1717
+ "name": "zmjoSq_name",
1661
1718
  "versionValue": "zmjoSq_versionValue",
1662
- "label": "zmjoSq_label",
1663
- "presetRow": "zmjoSq_presetRow",
1664
- "modelSummary": "zmjoSq_modelSummary",
1665
- "input": "zmjoSq_input",
1666
- "readOnly": "zmjoSq_readOnly",
1719
+ "badges": "zmjoSq_badges",
1720
+ "badge": "zmjoSq_badge",
1721
+ "channelName": "zmjoSq_channelName",
1722
+ "editorSectionHeader": "zmjoSq_editorSectionHeader",
1723
+ "presetName": "zmjoSq_presetName",
1724
+ "pending": "zmjoSq_pending",
1725
+ "invalid": "zmjoSq_invalid",
1726
+ "modelChip": "zmjoSq_modelChip",
1727
+ "header": "zmjoSq_header",
1728
+ "modelRow": "zmjoSq_modelRow",
1667
1729
  "channelList": "zmjoSq_channelList",
1668
- "channelSection": "zmjoSq_channelSection",
1669
- "modelFetchRow": "zmjoSq_modelFetchRow",
1670
- "body": "zmjoSq_body",
1730
+ "inputInvalid": "zmjoSq_inputInvalid",
1731
+ "versionLabel": "zmjoSq_versionLabel",
1732
+ "editorBackdrop": "zmjoSq_editorBackdrop",
1733
+ "chevron": "zmjoSq_chevron",
1671
1734
  "card": "zmjoSq_card",
1672
- "head": "zmjoSq_head",
1673
- "modelRows": "zmjoSq_modelRows",
1674
- "presetInlineHeader": "zmjoSq_presetInlineHeader",
1735
+ "chevronOpen": "zmjoSq_chevronOpen",
1736
+ "editorHeader": "zmjoSq_editorHeader",
1737
+ "modelCandidateLabel": "zmjoSq_modelCandidateLabel",
1738
+ "sectionDivider": "zmjoSq_sectionDivider",
1739
+ "addModel": "zmjoSq_addModel",
1740
+ "channelBadge": "zmjoSq_channelBadge",
1741
+ "editorDivider": "zmjoSq_editorDivider",
1742
+ "input": "zmjoSq_input",
1675
1743
  "modelArrow": "zmjoSq_modelArrow",
1676
- "presetList": "zmjoSq_presetList",
1677
- "versionRow": "zmjoSq_versionRow",
1678
- "failed": "zmjoSq_failed",
1679
- "description": "zmjoSq_description",
1680
- "modelRow": "zmjoSq_modelRow",
1681
- "inputInvalid": "zmjoSq_inputInvalid",
1744
+ "textarea": "zmjoSq_textarea",
1745
+ "presetInlineHeader": "zmjoSq_presetInlineHeader",
1682
1746
  "modelRowInputs": "zmjoSq_modelRowInputs",
1683
- "channelAction": "zmjoSq_channelAction",
1684
- "channelDotReady": "zmjoSq_channelDotReady",
1685
- "editorSectionHeader": "zmjoSq_editorSectionHeader",
1686
- "modelCandidateLabel": "zmjoSq_modelCandidateLabel",
1687
- "modelChip": "zmjoSq_modelChip",
1688
- "editorFooter": "zmjoSq_editorFooter",
1689
- "presetHint": "zmjoSq_presetHint",
1690
- "sectionTitle": "zmjoSq_sectionTitle",
1691
- "versionLabel": "zmjoSq_versionLabel",
1692
- "hint": "zmjoSq_hint",
1693
- "badges": "zmjoSq_badges",
1747
+ "presetInline": "zmjoSq_presetInline",
1748
+ "presetList": "zmjoSq_presetList",
1749
+ "discard": "zmjoSq_discard",
1750
+ "channelDanger": "zmjoSq_channelDanger",
1751
+ "spacer": "zmjoSq_spacer",
1694
1752
  "textareaInvalid": "zmjoSq_textareaInvalid",
1695
- "sectionDivider": "zmjoSq_sectionDivider",
1696
- "modelCandidate": "zmjoSq_modelCandidate",
1697
- "modelRowBadges": "zmjoSq_modelRowBadges",
1698
- "channelHost": "zmjoSq_channelHost",
1699
- "pending": "zmjoSq_pending",
1700
- "disclosure": "zmjoSq_disclosure",
1753
+ "inlineDisclosure": "zmjoSq_inlineDisclosure",
1754
+ "body": "zmjoSq_body",
1701
1755
  "modelChoices": "zmjoSq_modelChoices",
1702
- "presetName": "zmjoSq_presetName",
1703
- "headText": "zmjoSq_headText",
1704
- "spacer": "zmjoSq_spacer",
1705
- "manualModelRow": "zmjoSq_manualModelRow",
1706
- "editorTools": "zmjoSq_editorTools",
1707
- "editorBackdrop": "zmjoSq_editorBackdrop",
1708
- "channelRow": "zmjoSq_channelRow",
1709
1756
  "modelBadge": "zmjoSq_modelBadge",
1710
- "channelControls": "zmjoSq_channelControls",
1711
- "presetInline": "zmjoSq_presetInline",
1712
- "modelFetch": "zmjoSq_modelFetch",
1713
- "select": "zmjoSq_select",
1714
- "deleteConfirmText": "zmjoSq_deleteConfirmText",
1715
- "editorPanel": "zmjoSq_editorPanel",
1716
- "editorDivider": "zmjoSq_editorDivider",
1717
- "modelSection": "zmjoSq_modelSection"
1757
+ "detectOk": "zmjoSq_detectOk"
1718
1758
  };
1719
1759
  //#endregion
1720
1760
  //#region src/client/SettingsCard.tsx
@@ -1781,18 +1821,20 @@ window.__ModuleLoader__.load({
1781
1821
  };
1782
1822
  }
1783
1823
  function modelsToText(models) {
1784
- return models.map((model) => `${model.alias}=${model.id}`).join("\n");
1824
+ return models.map((model) => `${model.alias}=${model.id}${model.category === void 0 ? "" : ` @${model.category}`}`).join("\n");
1785
1825
  }
1786
1826
  function textToModels(text) {
1787
1827
  return text.split(/\n|,/).map((line) => line.trim()).filter(Boolean).map((line) => {
1788
- const eq = line.indexOf("=");
1789
- if (eq < 0) return {
1790
- alias: line,
1791
- id: line
1792
- };
1828
+ const at = line.lastIndexOf(" @");
1829
+ const category = at >= 0 ? line.slice(at + 2).trim() : void 0;
1830
+ const body = at >= 0 ? line.slice(0, at).trim() : line;
1831
+ const eq = body.indexOf("=");
1832
+ const alias = eq >= 0 ? body.slice(0, eq).trim() : body.trim();
1833
+ const id = eq >= 0 ? body.slice(eq + 1).trim() : alias;
1793
1834
  return {
1794
- alias: line.slice(0, eq).trim(),
1795
- id: line.slice(eq + 1).trim()
1835
+ alias,
1836
+ id: id === "" ? alias : id,
1837
+ ...category === void 0 || category === "" ? {} : { category }
1796
1838
  };
1797
1839
  }).filter((model) => model.alias !== "");
1798
1840
  }
@@ -1805,6 +1847,8 @@ window.__ModuleLoader__.load({
1805
1847
  const [presets, setPresets] = (0, react.useState)([]);
1806
1848
  const [presetError, setPresetError] = (0, react.useState)(null);
1807
1849
  const [confirmDeleteId, setConfirmDeleteId] = (0, react.useState)(null);
1850
+ const [discovering, setDiscovering] = (0, react.useState)(false);
1851
+ const [discoverError, setDiscoverError] = (0, react.useState)(null);
1808
1852
  const [editName, setEditName] = (0, react.useState)("");
1809
1853
  const [editUrl, setEditUrl] = (0, react.useState)("");
1810
1854
  const [editKey, setEditKey] = (0, react.useState)("");
@@ -1839,6 +1883,30 @@ window.__ModuleLoader__.load({
1839
1883
  if (editDefault) props.channels.setDefaultChannel(editingId);
1840
1884
  setEditingId(null);
1841
1885
  };
1886
+ const discoverModels = async () => {
1887
+ if (editingId === null) return;
1888
+ setDiscovering(true);
1889
+ setDiscoverError(null);
1890
+ try {
1891
+ channels.find((channel) => channel.id === editingId);
1892
+ const response = await fetch(MODEL_API.discover, {
1893
+ method: "POST",
1894
+ headers: { "content-type": "application/json" },
1895
+ body: JSON.stringify({
1896
+ channelId: editingId,
1897
+ ...editUrl.trim() !== "" ? { apiUrl: editUrl.trim() } : {},
1898
+ ...editKey.trim() !== "" ? { apiKey: editKey.trim() } : {}
1899
+ })
1900
+ });
1901
+ const body = await response.json();
1902
+ if (body.ok !== true || body.models === void 0) throw new Error(body.message ?? `HTTP ${response.status}`);
1903
+ setEditModels(modelsToText([...body.models, ...textToModels(editModels).filter((existingModel) => !body.models.some((model) => model.id === existingModel.id))]));
1904
+ } catch (error) {
1905
+ setDiscoverError(error instanceof Error ? error.message : String(error));
1906
+ } finally {
1907
+ setDiscovering(false);
1908
+ }
1909
+ };
1842
1910
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
1843
1911
  className: settings_card_module_css_default.card,
1844
1912
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
@@ -2141,7 +2209,21 @@ window.__ModuleLoader__.load({
2141
2209
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2142
2210
  className: settings_card_module_css_default.sectionHint,
2143
2211
  children: t("channel.modelsHint")
2144
- })
2212
+ }),
2213
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2214
+ className: settings_card_module_css_default.channelAddRow,
2215
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2216
+ type: "button",
2217
+ className: settings_card_module_css_default.channelAdd,
2218
+ disabled: discovering || !state.writable,
2219
+ onClick: () => void discoverModels(),
2220
+ children: discovering ? "获取中…" : "获取可用模型"
2221
+ })
2222
+ }),
2223
+ discoverError !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2224
+ className: settings_card_module_css_default.failed,
2225
+ children: discoverError
2226
+ }) : null
2145
2227
  ]
2146
2228
  }),
2147
2229
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
@@ -2262,17 +2344,17 @@ window.__ModuleLoader__.load({
2262
2344
  document.head.appendChild(tag);
2263
2345
  }
2264
2346
  var audio_toolview_module_css_default = {
2265
- "error": "_7K1QKa_error",
2266
- "audio": "_7K1QKa_audio",
2347
+ "message": "_7K1QKa_message",
2348
+ "audios": "_7K1QKa_audios",
2267
2349
  "download": "_7K1QKa_download",
2350
+ "icon": "_7K1QKa_icon",
2351
+ "error": "_7K1QKa_error",
2352
+ "status": "_7K1QKa_status",
2353
+ "header": "_7K1QKa_header",
2268
2354
  "audioRow": "_7K1QKa_audioRow",
2269
2355
  "empty": "_7K1QKa_empty",
2270
- "status": "_7K1QKa_status",
2271
- "audios": "_7K1QKa_audios",
2272
2356
  "root": "_7K1QKa_root",
2273
- "icon": "_7K1QKa_icon",
2274
- "header": "_7K1QKa_header",
2275
- "message": "_7K1QKa_message"
2357
+ "audio": "_7K1QKa_audio"
2276
2358
  };
2277
2359
  //#endregion
2278
2360
  //#region src/client/audio-toolview.tsx