dsh-audiogen 0.2.0 → 0.3.2

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
@@ -93,7 +93,8 @@ window.__ModuleLoader__.load({
93
93
  "mode.tts": "文本转语音",
94
94
  "mode.music": "音乐生成",
95
95
  "mode.sfx": "音效生成",
96
- "prompt.placeholder": "输入要朗读的文本,或描述想生成的音乐 / 音效…",
96
+ "mode.voiceDesign": "音色设计",
97
+ "prompt.placeholder": "输入文本、音乐/音效描述,或音色设计描述…",
97
98
  "prompt.required": "请输入文本或提示词",
98
99
  "model.label": "模型 / 音色",
99
100
  "voice.label": "音色",
@@ -124,8 +125,10 @@ window.__ModuleLoader__.load({
124
125
  "channels.title": "音频渠道",
125
126
  "channels.hint": "每个渠道是一个独立的音频厂商/API 端点,可配置多个。",
126
127
  "channels.empty": "还没有渠道。",
127
- "channels.addProvider": "+ 添加预置厂商",
128
- "channels.addCustom": "+ 添加自定义渠道",
128
+ "channels.addProvider": "+ 添加提供方",
129
+ "channels.addProviderLoading": "加载提供方…",
130
+ "channels.addProviderFailed": "提供方目录加载失败,请点击重试。",
131
+ "channels.addCustom": "+ 添加自定义提供方",
129
132
  "channels.edit": "编辑",
130
133
  "channels.delete": "删除",
131
134
  "channels.confirm": "确认删除",
@@ -137,17 +140,49 @@ window.__ModuleLoader__.load({
137
140
  "channels.statusReady": "可用",
138
141
  "channels.statusIncomplete": "未完成",
139
142
  "channels.untitled": "未命名渠道",
143
+ "channel.title": "渠道设置",
144
+ "channel.editTitle": "编辑渠道",
145
+ "channel.provider": "提供方",
146
+ "channel.providerCustom": "自定义渠道",
147
+ "channel.providerCustomHint": "任意 OpenAI 兼容 TTS 或通用音频 POST 接口",
148
+ "channel.site": "官网",
140
149
  "channel.name": "名称",
150
+ "channel.namePlaceholder": "渠道名称(如:MiniMax 主渠道)",
141
151
  "channel.apiUrl": "API 地址",
152
+ "channel.apiUrlPlaceholder": "提供方默认地址",
153
+ "channel.apiUrlHint": "留空使用提供方默认地址。",
142
154
  "channel.apiKey": "API 密钥",
143
- "channel.apiKeyHint": "留空则保持当前密钥;输入新值可更换。",
144
- "channel.models": "模型 / 音色(每行一个:别名=上游ID)",
145
- "channel.modelsHint": "每行格式:别名=上游ID,可加 @分类(tts/music/sfx/voice_design/voice_clone);例如 tts-1=tts-1 @tts 或 Rachel=21m00Tcm4TlvDq8ikWAM @tts",
146
- "channel.default": "设为默认",
155
+ "channel.apiKeyHint": "输入 API 密钥后即可使用该渠道。",
156
+ "channel.apiKeyStoredHint": "已保存密钥;留空保持不变,输入新值可更换。",
157
+ "channel.clearKey": "清除密钥",
158
+ "channel.customSettings": "自定义设置",
159
+ "channel.modelsTitle": "模型 / 音色目录",
160
+ "channel.modelsCount": "{n} 个模型/音色",
161
+ "channel.modelsNone": "未添加",
162
+ "channel.modelsEmpty": "尚未添加模型/音色:面板与 Agent 将无可选模型;保存后仍可直接输入目录外的 ID 进行生成。",
163
+ "channel.modelAlias": "显示名称",
164
+ "channel.modelId": "上游 ID",
165
+ "channel.modelCategory": "分类",
166
+ "channel.category.auto": "自动",
167
+ "channel.category.tts": "语音",
168
+ "channel.category.music": "音乐",
169
+ "channel.category.sfx": "音效",
170
+ "channel.category.voice_design": "音色设计",
171
+ "channel.category.voice_clone": "音色克隆",
172
+ "channel.addModel": "添加模型",
173
+ "channel.removeModel": "移除",
174
+ "channel.fetchModels": "获取可用模型",
175
+ "channel.fetchingModels": "获取中…",
176
+ "channel.discoverNeedsUrlKey": "填写 API 地址与密钥后可获取模型",
177
+ "channel.fetchEmpty": "未发现音频相关模型。",
178
+ "channel.discoverSource": "来源:{source}",
179
+ "channel.candidates": "发现 {n} 个可用模型/音色",
180
+ "channel.selectAll": "全选",
181
+ "channel.clearSelection": "清空",
182
+ "channel.adoptSelected": "添加所选({n})",
183
+ "channel.default": "设为默认渠道",
147
184
  "channel.cancel": "取消",
148
- "channel.save": "保存渠道",
149
- "presets.title": "预置厂商",
150
- "presets.custom": "自定义渠道"
185
+ "channel.save": "保存渠道"
151
186
  };
152
187
  const en = {
153
188
  "entry.label": "AI Audio",
@@ -156,7 +191,8 @@ window.__ModuleLoader__.load({
156
191
  "mode.tts": "Text to speech",
157
192
  "mode.music": "Music",
158
193
  "mode.sfx": "Sound effects",
159
- "prompt.placeholder": "Text to speak, or a description of the music / sound effect…",
194
+ "mode.voiceDesign": "Voice design",
195
+ "prompt.placeholder": "Text to speak, or a music/SFX/voice-design description…",
160
196
  "prompt.required": "Prompt or text is required",
161
197
  "model.label": "Model / voice",
162
198
  "voice.label": "Voice",
@@ -187,8 +223,10 @@ window.__ModuleLoader__.load({
187
223
  "channels.title": "Audio channels",
188
224
  "channels.hint": "Each channel is an independent audio vendor/API endpoint.",
189
225
  "channels.empty": "No channels yet.",
190
- "channels.addProvider": "+ Add preset vendor",
191
- "channels.addCustom": "+ Add custom channel",
226
+ "channels.addProvider": "+ Add provider",
227
+ "channels.addProviderLoading": "Loading providers…",
228
+ "channels.addProviderFailed": "Failed to load the provider catalog. Click to retry.",
229
+ "channels.addCustom": "+ Add custom provider",
192
230
  "channels.edit": "Edit",
193
231
  "channels.delete": "Delete",
194
232
  "channels.confirm": "Confirm delete",
@@ -200,17 +238,49 @@ window.__ModuleLoader__.load({
200
238
  "channels.statusReady": "Ready",
201
239
  "channels.statusIncomplete": "Incomplete",
202
240
  "channels.untitled": "Untitled channel",
241
+ "channel.title": "Channel settings",
242
+ "channel.editTitle": "Edit channel",
243
+ "channel.provider": "Provider",
244
+ "channel.providerCustom": "Custom provider",
245
+ "channel.providerCustomHint": "Any OpenAI-compatible TTS or generic audio POST endpoint",
246
+ "channel.site": "Website",
203
247
  "channel.name": "Name",
248
+ "channel.namePlaceholder": "Channel name (e.g. MiniMax main)",
204
249
  "channel.apiUrl": "API URL",
250
+ "channel.apiUrlPlaceholder": "Provider default",
251
+ "channel.apiUrlHint": "Leave blank to use the provider default.",
205
252
  "channel.apiKey": "API key",
206
- "channel.apiKeyHint": "Leave blank to keep the current key.",
207
- "channel.models": "Models / voices (one per line: alias=upstreamId)",
208
- "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",
209
- "channel.default": "Set default",
253
+ "channel.apiKeyHint": "Enter the API key to use this channel.",
254
+ "channel.apiKeyStoredHint": "A key is stored; leave blank to keep it, or enter a new one.",
255
+ "channel.clearKey": "Clear key",
256
+ "channel.customSettings": "Custom settings",
257
+ "channel.modelsTitle": "Model / voice catalog",
258
+ "channel.modelsCount": "{n} model(s)/voice(s)",
259
+ "channel.modelsNone": "None",
260
+ "channel.modelsEmpty": "No models yet: the panel and agents will have nothing to pick. You can still send an ID outside the catalog after saving.",
261
+ "channel.modelAlias": "Display name",
262
+ "channel.modelId": "Upstream ID",
263
+ "channel.modelCategory": "Category",
264
+ "channel.category.auto": "Auto",
265
+ "channel.category.tts": "Speech",
266
+ "channel.category.music": "Music",
267
+ "channel.category.sfx": "SFX",
268
+ "channel.category.voice_design": "Voice design",
269
+ "channel.category.voice_clone": "Voice clone",
270
+ "channel.addModel": "Add model",
271
+ "channel.removeModel": "Remove",
272
+ "channel.fetchModels": "Fetch available models",
273
+ "channel.fetchingModels": "Fetching…",
274
+ "channel.discoverNeedsUrlKey": "Fill in the API URL and key to fetch models",
275
+ "channel.fetchEmpty": "No audio-related models found.",
276
+ "channel.discoverSource": "Source: {source}",
277
+ "channel.candidates": "{n} available model(s)/voice(s) found",
278
+ "channel.selectAll": "Select all",
279
+ "channel.clearSelection": "Clear",
280
+ "channel.adoptSelected": "Add selected ({n})",
281
+ "channel.default": "Set as default channel",
210
282
  "channel.cancel": "Cancel",
211
- "channel.save": "Save channel",
212
- "presets.title": "Preset vendors",
213
- "presets.custom": "Custom channel"
283
+ "channel.save": "Save channel"
214
284
  };
215
285
  //#endregion
216
286
  //#region src/client/helpers.ts
@@ -462,7 +532,7 @@ window.__ModuleLoader__.load({
462
532
  }
463
533
  //#endregion
464
534
  //#region \0dsh-css:/Users/shimingming/Projects_code/dsh-audiogen/src/client/audio-panel.module.css.mjs
465
- const css$3 = ".Oo1fpq_panel{background:var(--dsw-alias-bg-base,#f7f7f8);height:100%;color:var(--dsw-alias-label-primary,#1f2328);font-family:var(--dsw-font-family,system-ui, sans-serif);flex-direction:column;gap:12px;padding:14px 16px;display:flex;overflow:hidden}.Oo1fpq_header{justify-content:space-between;align-items:center;display:flex}.Oo1fpq_title{margin:0;font-size:16px;font-weight:700}.Oo1fpq_layout{flex:1;gap:14px;min-height:0;display:flex}.Oo1fpq_form{flex-direction:column;flex:none;gap:12px;width:300px;min-width:260px;max-width:340px;display:flex;overflow-y:auto}.Oo1fpq_result{border:1px solid var(--dsw-alias-border-l1,#e5e7eb);background:var(--dsw-alias-bg-layer-1,#fff);border-radius:12px;flex-direction:column;flex:1;min-width:0;padding:14px;display:flex;overflow-y:auto}.Oo1fpq_label{color:var(--dsw-alias-label-secondary,#6b7280);flex-direction:column;gap:5px;font-size:12px;font-weight:600;display:flex}.Oo1fpq_textarea,.Oo1fpq_input,.Oo1fpq_select{border:1px solid var(--dsw-alias-border-l2,#d1d5db);background:var(--dsw-alias-bg-layer-3,#fff);width:100%;min-height:36px;color:var(--dsw-alias-label-primary,#1f2328);font:inherit;border-radius:8px;outline:none;padding:7px 10px;font-size:13px}.Oo1fpq_textarea{resize:vertical;min-height:110px}.Oo1fpq_modeRow{gap:6px;display:flex}.Oo1fpq_modeButton{border:1px solid var(--dsw-alias-border-l2,#d1d5db);font:inherit;cursor:pointer;background:0 0;border-radius:8px;flex:1;padding:7px 8px;font-size:12px}.Oo1fpq_modeButton[data-active=true]{border-color:var(--dsw-alias-brand-primary,#2563eb);color:var(--dsw-alias-brand-primary,#2563eb);font-weight:600}.Oo1fpq_generate{background:var(--dsw-alias-label-primary,#1f2328);color:var(--dsw-alias-bg-layer-3,#fff);font:inherit;cursor:pointer;border:0;border-radius:10px;padding:9px 14px;font-size:13px}.Oo1fpq_generate:disabled{opacity:.5;cursor:default}.Oo1fpq_empty,.Oo1fpq_error,.Oo1fpq_hint{color:var(--dsw-alias-label-secondary,#6b7280);font-size:13px}.Oo1fpq_error{color:#b91c1c}.Oo1fpq_audioList{gap:10px;margin-top:8px;display:grid}.Oo1fpq_audioCard{border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:10px;flex-direction:column;gap:6px;padding:10px;display:flex}.Oo1fpq_audio{width:100%;height:36px}.Oo1fpq_download{color:#2563eb;font-size:12px;text-decoration:none}.Oo1fpq_history{border-left:1px solid var(--dsw-alias-border-l1,#e5e7eb);flex:none;width:260px;padding-left:12px;overflow-y:auto}.Oo1fpq_historyTitle{font-size:13px;font-weight:700}.Oo1fpq_historyEmpty{color:var(--dsw-alias-label-tertiary,#9ca3af);font-size:12px}.Oo1fpq_historyItem{border-bottom:1px solid var(--dsw-alias-border-l1,#e5e7eb);padding:8px 0}.Oo1fpq_historyPrompt{text-overflow:ellipsis;white-space:nowrap;font-size:12px;overflow:hidden}.Oo1fpq_historyMeta{color:var(--dsw-alias-label-tertiary,#9ca3af);font-size:11px}.Oo1fpq_historyAudio{width:100%;height:30px;margin-top:4px}";
535
+ const css$3 = ".Oo1fpq_panel{background:var(--dsw-alias-bg-base,#f7f7f8);height:100%;color:var(--dsw-alias-label-primary,#1f2328);font-family:var(--dsw-font-family,system-ui, sans-serif);flex-direction:column;gap:12px;padding:14px 16px;display:flex;overflow:hidden}.Oo1fpq_header{justify-content:space-between;align-items:center;display:flex}.Oo1fpq_title{margin:0;font-size:16px;font-weight:700}.Oo1fpq_layout{flex:1;gap:14px;min-height:0;display:flex}.Oo1fpq_form{flex-direction:column;flex:none;gap:12px;width:300px;min-width:260px;max-width:340px;display:flex;overflow-y:auto}.Oo1fpq_result{border:1px solid var(--dsw-alias-border-l1,#e5e7eb);background:var(--dsw-alias-bg-layer-1,#fff);border-radius:12px;flex-direction:column;flex:1;min-width:0;padding:14px;display:flex;overflow-y:auto}.Oo1fpq_label{color:var(--dsw-alias-label-secondary,#6b7280);flex-direction:column;gap:5px;font-size:12px;font-weight:600;display:flex}.Oo1fpq_textarea,.Oo1fpq_input,.Oo1fpq_select{border:1px solid var(--dsw-alias-border-l2,#d1d5db);background:var(--dsw-alias-bg-layer-3,#fff);width:100%;min-height:36px;color:var(--dsw-alias-label-primary,#1f2328);font:inherit;border-radius:8px;outline:none;padding:7px 10px;font-size:13px}.Oo1fpq_textarea{resize:vertical;min-height:110px}.Oo1fpq_modeRow{gap:6px;display:flex}.Oo1fpq_modeButton{border:1px solid var(--dsw-alias-border-l2,#d1d5db);font:inherit;cursor:pointer;background:0 0;border-radius:8px;flex:1;padding:7px 8px;font-size:12px}.Oo1fpq_modeButton[data-active=true]{border-color:var(--dsw-alias-brand-primary,#2563eb);color:var(--dsw-alias-brand-primary,#2563eb);font-weight:600}.Oo1fpq_generate{background:var(--dsw-alias-label-primary,#1f2328);color:var(--dsw-alias-bg-layer-3,#fff);font:inherit;cursor:pointer;border:0;border-radius:10px;padding:9px 14px;font-size:13px}.Oo1fpq_generate:disabled{opacity:.5;cursor:default}.Oo1fpq_empty,.Oo1fpq_error,.Oo1fpq_hint{color:var(--dsw-alias-label-secondary,#6b7280);font-size:13px}.Oo1fpq_error{color:#b91c1c}.Oo1fpq_audioList{gap:10px;margin-top:8px;display:grid}.Oo1fpq_audioCard{border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:10px;flex-direction:column;gap:6px;padding:10px;display:flex}.Oo1fpq_audio{width:100%;height:36px}.Oo1fpq_download{color:#2563eb;font-size:12px;text-decoration:none}.Oo1fpq_history{border-left:1px solid var(--dsw-alias-border-l1,#e5e7eb);flex:none;width:260px;padding-left:12px;overflow-y:auto}.Oo1fpq_historyTitle{font-size:13px;font-weight:700}.Oo1fpq_historyEmpty{color:var(--dsw-alias-label-tertiary,#9ca3af);font-size:12px}.Oo1fpq_historyItem{border-bottom:1px solid var(--dsw-alias-border-l1,#e5e7eb);padding:8px 0}.Oo1fpq_historyPrompt{text-overflow:ellipsis;white-space:nowrap;font-size:12px;overflow:hidden}.Oo1fpq_historyMeta{color:var(--dsw-alias-label-tertiary,#9ca3af);font-size:11px}.Oo1fpq_historyAudio{width:100%;height:30px;margin-top:4px}.Oo1fpq_advanced{border:1px dashed var(--dsw-alias-border-l2,#d1d5db);border-radius:8px;flex-direction:column;gap:8px;padding:8px 10px;display:flex}.Oo1fpq_advanced summary{cursor:pointer;color:var(--dsw-alias-label-secondary,#6b7280);font-size:12px;font-weight:600}.Oo1fpq_row{align-items:flex-end;gap:8px;display:flex}.Oo1fpq_row .Oo1fpq_label{flex:1}.Oo1fpq_checkbox{color:var(--dsw-alias-label-secondary,#6b7280);cursor:pointer;align-items:center;gap:6px;font-size:12px;font-weight:600;display:flex}";
466
536
  const tagId$3 = "dsh-audiogen/audio-panel.module.css";
467
537
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$3) + "]") === null) {
468
538
  const tag = document.createElement("style");
@@ -472,38 +542,43 @@ window.__ModuleLoader__.load({
472
542
  document.head.appendChild(tag);
473
543
  }
474
544
  var audio_panel_module_css_default = {
475
- "historyItem": "Oo1fpq_historyItem",
476
- "form": "Oo1fpq_form",
545
+ "audioList": "Oo1fpq_audioList",
546
+ "hint": "Oo1fpq_hint",
547
+ "historyEmpty": "Oo1fpq_historyEmpty",
548
+ "row": "Oo1fpq_row",
477
549
  "label": "Oo1fpq_label",
550
+ "layout": "Oo1fpq_layout",
478
551
  "textarea": "Oo1fpq_textarea",
479
- "header": "Oo1fpq_header",
480
- "empty": "Oo1fpq_empty",
481
- "audio": "Oo1fpq_audio",
482
552
  "result": "Oo1fpq_result",
483
553
  "input": "Oo1fpq_input",
484
- "panel": "Oo1fpq_panel",
485
- "modeButton": "Oo1fpq_modeButton",
486
- "hint": "Oo1fpq_hint",
487
- "audioList": "Oo1fpq_audioList",
488
- "history": "Oo1fpq_history",
489
554
  "historyTitle": "Oo1fpq_historyTitle",
555
+ "download": "Oo1fpq_download",
556
+ "checkbox": "Oo1fpq_checkbox",
557
+ "header": "Oo1fpq_header",
558
+ "empty": "Oo1fpq_empty",
559
+ "generate": "Oo1fpq_generate",
490
560
  "title": "Oo1fpq_title",
561
+ "audio": "Oo1fpq_audio",
562
+ "modeRow": "Oo1fpq_modeRow",
491
563
  "select": "Oo1fpq_select",
564
+ "historyAudio": "Oo1fpq_historyAudio",
565
+ "historyItem": "Oo1fpq_historyItem",
492
566
  "error": "Oo1fpq_error",
493
- "historyEmpty": "Oo1fpq_historyEmpty",
494
- "audioCard": "Oo1fpq_audioCard",
495
- "layout": "Oo1fpq_layout",
496
- "modeRow": "Oo1fpq_modeRow",
567
+ "panel": "Oo1fpq_panel",
497
568
  "historyMeta": "Oo1fpq_historyMeta",
498
- "generate": "Oo1fpq_generate",
499
- "historyAudio": "Oo1fpq_historyAudio",
500
- "download": "Oo1fpq_download",
501
- "historyPrompt": "Oo1fpq_historyPrompt"
569
+ "modeButton": "Oo1fpq_modeButton",
570
+ "advanced": "Oo1fpq_advanced",
571
+ "audioCard": "Oo1fpq_audioCard",
572
+ "historyPrompt": "Oo1fpq_historyPrompt",
573
+ "form": "Oo1fpq_form",
574
+ "history": "Oo1fpq_history"
502
575
  };
503
576
  //#endregion
504
577
  //#region src/client/AudioGenPanel.tsx
505
578
  /**
506
579
  * The AI 音频 panel: a compact audio-generation studio.
580
+ * TTS / music / SFX / voice design are separated; each mode only lists
581
+ * compatible models and shows its own parameters.
507
582
  */
508
583
  function useConfig(scope) {
509
584
  const [value, setValue] = (0, react.useState)(scope.getSnapshot().value);
@@ -543,20 +618,36 @@ window.__ModuleLoader__.load({
543
618
  const channels = config?.channels ?? [];
544
619
  const connected = enabled && channels.some((channel) => {
545
620
  const keyHeld = scope.getSecretSetSnapshot(`channelSecrets.${channel.id}`);
546
- return channel.apiUrl.trim() !== "" && keyHeld && channel.models.length > 0;
621
+ return channel.apiUrl.trim() !== "" && keyHeld && (channel.models.length > 0 || channel.preset === "minimax");
547
622
  });
548
623
  const [mode, setMode] = (0, react.useState)("tts");
549
624
  const [prompt, setPrompt] = (0, react.useState)("");
625
+ const [previewText, setPreviewText] = (0, react.useState)("");
550
626
  const [model, setModel] = (0, react.useState)("");
551
627
  const [voice, setVoice] = (0, react.useState)("");
552
628
  const [speed, setSpeed] = (0, react.useState)("");
553
629
  const [duration, setDuration] = (0, react.useState)("");
554
630
  const [format, setFormat] = (0, react.useState)("mp3");
631
+ const [emotion, setEmotion] = (0, react.useState)("");
632
+ const [vol, setVol] = (0, react.useState)("");
633
+ const [pitch, setPitch] = (0, react.useState)("");
634
+ const [toneText, setToneText] = (0, react.useState)("");
635
+ const [sampleRate, setSampleRate] = (0, react.useState)("");
636
+ const [bitrate, setBitrate] = (0, react.useState)("");
637
+ const [audioChannel, setAudioChannel] = (0, react.useState)("");
638
+ const [subtitle, setSubtitle] = (0, react.useState)(false);
555
639
  const [loading, setLoading] = (0, react.useState)(false);
556
640
  const [error, setError] = (0, react.useState)(null);
557
641
  const [outputs, setOutputs] = (0, react.useState)([]);
558
642
  const { entries, reload, clear } = useHistory();
559
- const visibleModels = (0, react.useMemo)(() => modelOptions.models.filter((entry) => entry.category === void 0 || entry.category === "tts" && mode === "tts" || entry.category === mode).map((entry) => entry.alias), [modelOptions.models, mode]);
643
+ const isMiniMaxChannel = (0, react.useMemo)(() => {
644
+ const target = channels.find((candidate) => candidate.id === modelOptions.defaultChannelId) ?? channels[0];
645
+ return target !== void 0 && (target.preset === "minimax" || /minimax/i.test(target.apiUrl));
646
+ }, [channels, modelOptions.defaultChannelId]);
647
+ const visibleModels = (0, react.useMemo)(() => {
648
+ if (mode === "voice_design") return [];
649
+ return modelOptions.models.filter((entry) => entry.category === void 0 || entry.category === "tts" && mode === "tts" || entry.category === mode).map((entry) => entry.alias);
650
+ }, [modelOptions.models, mode]);
560
651
  (0, react.useEffect)(() => {
561
652
  if (visibleModels.length > 0 && !visibleModels.includes(model)) setModel(visibleModels[0]);
562
653
  }, [visibleModels, model]);
@@ -572,10 +663,19 @@ window.__ModuleLoader__.load({
572
663
  mode,
573
664
  model: (model || visibleModels[0]) ?? "",
574
665
  prompt: prompt.trim(),
666
+ ...previewText.trim() !== "" ? { previewText: previewText.trim() } : {},
575
667
  ...voice.trim() !== "" ? { voice: voice.trim() } : {},
576
668
  ...speed.trim() !== "" ? { speed: Number(speed) } : {},
577
669
  ...duration.trim() !== "" ? { duration: Number(duration) } : {},
578
- ...format.trim() !== "" ? { format: format.trim() } : {}
670
+ ...format.trim() !== "" ? { format: format.trim() } : {},
671
+ ...emotion.trim() !== "" ? { emotion: emotion.trim() } : {},
672
+ ...vol.trim() !== "" ? { vol: Number(vol) } : {},
673
+ ...pitch.trim() !== "" ? { pitch: Number(pitch) } : {},
674
+ ...toneText.trim() !== "" ? { pronunciationTone: toneText.split("\n").map((item) => item.trim()).filter((item) => item !== "") } : {},
675
+ ...sampleRate.trim() !== "" ? { sampleRate: Number(sampleRate) } : {},
676
+ ...bitrate.trim() !== "" ? { bitrate: Number(bitrate) } : {},
677
+ ...audioChannel.trim() !== "" ? { audioChannel: Number(audioChannel) } : {},
678
+ ...subtitle ? { subtitleEnable: true } : {}
579
679
  });
580
680
  if (!response.ok) {
581
681
  setError(response.message ?? "生成失败");
@@ -592,8 +692,10 @@ window.__ModuleLoader__.load({
592
692
  const modeLabel = (0, react.useMemo)(() => {
593
693
  if (mode === "tts") return tt("mode.tts");
594
694
  if (mode === "music") return tt("mode.music");
595
- return tt("mode.sfx");
695
+ if (mode === "sfx") return tt("mode.sfx");
696
+ return tt("mode.voiceDesign");
596
697
  }, [mode]);
698
+ const needModel = mode !== "voice_design";
597
699
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
598
700
  className: audio_panel_module_css_default.panel,
599
701
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", {
@@ -616,25 +718,35 @@ window.__ModuleLoader__.load({
616
718
  children: [
617
719
  "tts",
618
720
  "music",
619
- "sfx"
721
+ "sfx",
722
+ "voice_design"
620
723
  ].map((item) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
621
724
  type: "button",
622
725
  className: audio_panel_module_css_default.modeButton,
623
726
  "data-active": mode === item ? "true" : "false",
624
727
  onClick: () => setMode(item),
625
- children: item === "tts" ? tt("mode.tts") : item === "music" ? tt("mode.music") : tt("mode.sfx")
728
+ children: item === "tts" ? tt("mode.tts") : item === "music" ? tt("mode.music") : item === "sfx" ? tt("mode.sfx") : tt("mode.voiceDesign")
626
729
  }, item))
627
730
  }),
628
731
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
629
732
  className: audio_panel_module_css_default.label,
630
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: mode === "tts" ? "文本" : "提示词" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
733
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: mode === "voice_design" ? "音色描述" : mode === "tts" ? "文本" : "提示词" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
631
734
  className: audio_panel_module_css_default.textarea,
632
735
  value: prompt,
633
736
  onChange: (event) => setPrompt(event.target.value),
634
737
  placeholder: tt("prompt.placeholder")
635
738
  })]
636
739
  }),
637
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
740
+ mode === "voice_design" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
741
+ className: audio_panel_module_css_default.label,
742
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "试听文本" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
743
+ className: audio_panel_module_css_default.input,
744
+ value: previewText,
745
+ onChange: (event) => setPreviewText(event.target.value),
746
+ placeholder: "你好,这是新设计的音色试听。"
747
+ })]
748
+ }) : null,
749
+ needModel ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
638
750
  className: audio_panel_module_css_default.label,
639
751
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: tt("model.label") }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
640
752
  className: audio_panel_module_css_default.select,
@@ -648,17 +760,17 @@ window.__ModuleLoader__.load({
648
760
  children: item
649
761
  }, item))]
650
762
  })]
651
- }),
763
+ }) : null,
652
764
  mode === "tts" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
653
765
  className: audio_panel_module_css_default.label,
654
766
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: tt("voice.label") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
655
767
  className: audio_panel_module_css_default.input,
656
768
  value: voice,
657
769
  onChange: (event) => setVoice(event.target.value),
658
- placeholder: "alloy / 自定义音色"
770
+ placeholder: isMiniMaxChannel ? "male-qn-qingse / female-shaonv" : "alloy / 自定义音色"
659
771
  })]
660
772
  }) : null,
661
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
773
+ mode === "tts" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
662
774
  className: audio_panel_module_css_default.label,
663
775
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: tt("speed.label") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
664
776
  className: audio_panel_module_css_default.input,
@@ -670,8 +782,120 @@ window.__ModuleLoader__.load({
670
782
  onChange: (event) => setSpeed(event.target.value),
671
783
  placeholder: "1.0"
672
784
  })]
673
- }),
674
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
785
+ }) : null,
786
+ mode === "tts" && isMiniMaxChannel ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
787
+ className: audio_panel_module_css_default.advanced,
788
+ children: [
789
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("summary", { children: "MiniMax 高级参数" }),
790
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
791
+ className: audio_panel_module_css_default.label,
792
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "情绪 emotion" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
793
+ className: audio_panel_module_css_default.input,
794
+ value: emotion,
795
+ onChange: (event) => setEmotion(event.target.value),
796
+ placeholder: "happy / sad / angry / nervous…"
797
+ })]
798
+ }),
799
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
800
+ className: audio_panel_module_css_default.row,
801
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
802
+ className: audio_panel_module_css_default.label,
803
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "音量 vol (0-10)" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
804
+ className: audio_panel_module_css_default.input,
805
+ type: "number",
806
+ min: "0",
807
+ max: "10",
808
+ step: "0.5",
809
+ value: vol,
810
+ onChange: (event) => setVol(event.target.value),
811
+ placeholder: "1"
812
+ })]
813
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
814
+ className: audio_panel_module_css_default.label,
815
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "音调 pitch (-12~12)" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
816
+ className: audio_panel_module_css_default.input,
817
+ type: "number",
818
+ min: "-12",
819
+ max: "12",
820
+ value: pitch,
821
+ onChange: (event) => setPitch(event.target.value),
822
+ placeholder: "0"
823
+ })]
824
+ })]
825
+ }),
826
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
827
+ className: audio_panel_module_css_default.row,
828
+ children: [
829
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
830
+ className: audio_panel_module_css_default.label,
831
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "采样率" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
832
+ className: audio_panel_module_css_default.input,
833
+ type: "number",
834
+ min: "16000",
835
+ max: "48000",
836
+ step: "8000",
837
+ value: sampleRate,
838
+ onChange: (event) => setSampleRate(event.target.value),
839
+ placeholder: "32000"
840
+ })]
841
+ }),
842
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
843
+ className: audio_panel_module_css_default.label,
844
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "码率 bps" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
845
+ className: audio_panel_module_css_default.input,
846
+ type: "number",
847
+ min: "64000",
848
+ max: "320000",
849
+ step: "8000",
850
+ value: bitrate,
851
+ onChange: (event) => setBitrate(event.target.value),
852
+ placeholder: "128000"
853
+ })]
854
+ }),
855
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
856
+ className: audio_panel_module_css_default.label,
857
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "声道" }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
858
+ className: audio_panel_module_css_default.select,
859
+ value: audioChannel,
860
+ onChange: (event) => setAudioChannel(event.target.value),
861
+ children: [
862
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
863
+ value: "",
864
+ children: "默认(1)"
865
+ }),
866
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
867
+ value: "1",
868
+ children: "1"
869
+ }),
870
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
871
+ value: "2",
872
+ children: "2"
873
+ })
874
+ ]
875
+ })]
876
+ })
877
+ ]
878
+ }),
879
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
880
+ className: audio_panel_module_css_default.label,
881
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "发音词典(每行一条:\"文字/读音\")" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
882
+ className: audio_panel_module_css_default.textarea,
883
+ value: toneText,
884
+ onChange: (event) => setToneText(event.target.value),
885
+ placeholder: "处理/(chu3)(li3)\n危险/dangerous"
886
+ })]
887
+ }),
888
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
889
+ className: audio_panel_module_css_default.checkbox,
890
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
891
+ type: "checkbox",
892
+ checked: subtitle,
893
+ onChange: (event) => setSubtitle(event.target.checked)
894
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "生成字幕 subtitle_enable" })]
895
+ })
896
+ ]
897
+ }) : null,
898
+ mode === "music" || mode === "sfx" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
675
899
  className: audio_panel_module_css_default.label,
676
900
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: tt("duration.label") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
677
901
  className: audio_panel_module_css_default.input,
@@ -683,8 +907,8 @@ window.__ModuleLoader__.load({
683
907
  onChange: (event) => setDuration(event.target.value),
684
908
  placeholder: "30"
685
909
  })]
686
- }),
687
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
910
+ }) : null,
911
+ needModel ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
688
912
  className: audio_panel_module_css_default.label,
689
913
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: tt("format.label") }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
690
914
  className: audio_panel_module_css_default.select,
@@ -713,7 +937,7 @@ window.__ModuleLoader__.load({
713
937
  })
714
938
  ]
715
939
  })]
716
- }),
940
+ }) : null,
717
941
  !connected && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
718
942
  className: audio_panel_module_css_default.hint,
719
943
  children: tt("config.missing")
@@ -721,7 +945,7 @@ window.__ModuleLoader__.load({
721
945
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
722
946
  type: "button",
723
947
  className: audio_panel_module_css_default.generate,
724
- disabled: loading || !connected || visibleModels.length === 0,
948
+ disabled: loading || !connected || needModel && visibleModels.length === 0,
725
949
  onClick: () => void submit(),
726
950
  children: loading ? tt("generating") : tt("generate")
727
951
  })
@@ -742,17 +966,24 @@ window.__ModuleLoader__.load({
742
966
  className: audio_panel_module_css_default.audioList,
743
967
  children: outputs.map((audio, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
744
968
  className: audio_panel_module_css_default.audioCard,
745
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("audio", {
746
- className: audio_panel_module_css_default.audio,
747
- controls: true,
748
- preload: "metadata",
749
- src: dataUrlOf(audio)
750
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
751
- className: audio_panel_module_css_default.download,
752
- href: dataUrlOf(audio),
753
- download: `generated-${index + 1}.${audio.mime.split("/")[1]?.replace("mpeg", "mp3") ?? "mp3"}`,
754
- children: "下载"
755
- })]
969
+ children: [
970
+ audio.voiceId !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
971
+ className: audio_panel_module_css_default.hint,
972
+ children: ["新音色 ID:", audio.voiceId]
973
+ }) : null,
974
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("audio", {
975
+ className: audio_panel_module_css_default.audio,
976
+ controls: true,
977
+ preload: "metadata",
978
+ src: dataUrlOf(audio)
979
+ }),
980
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
981
+ className: audio_panel_module_css_default.download,
982
+ href: dataUrlOf(audio),
983
+ download: `generated-${index + 1}.${audio.mime.split("/")[1]?.replace("mpeg", "mp3") ?? "mp3"}`,
984
+ children: "下载"
985
+ })
986
+ ]
756
987
  }, audio.id))
757
988
  })] })]
758
989
  }),
@@ -819,167 +1050,167 @@ window.__ModuleLoader__.load({
819
1050
  document.head.appendChild(tag);
820
1051
  }
821
1052
  var panel_module_css_default = {
822
- "optionGrid": "rwa6qG_optionGrid",
823
- "lightboxCopy": "rwa6qG_lightboxCopy",
1053
+ "promptCount": "rwa6qG_promptCount",
1054
+ "generateButton": "rwa6qG_generateButton",
1055
+ "galleryImage": "rwa6qG_galleryImage",
1056
+ "entryIcon": "rwa6qG_entryIcon",
1057
+ "historyHeader": "rwa6qG_historyHeader",
1058
+ "gallerySelect": "rwa6qG_gallerySelect",
1059
+ "historyThumbPlaceholder": "rwa6qG_historyThumbPlaceholder",
1060
+ "updateBanner": "rwa6qG_updateBanner",
1061
+ "taskStatus": "rwa6qG_taskStatus",
1062
+ "configScroll": "rwa6qG_configScroll",
1063
+ "referenceActions": "rwa6qG_referenceActions",
824
1064
  "galleryBulkButton": "rwa6qG_galleryBulkButton",
1065
+ "modelMenu": "rwa6qG_modelMenu",
1066
+ "lightboxIndex": "rwa6qG_lightboxIndex",
1067
+ "lightboxTools": "rwa6qG_lightboxTools",
1068
+ "updateActions": "rwa6qG_updateActions",
825
1069
  "canvas": "rwa6qG_canvas",
826
- "historyClear": "rwa6qG_historyClear",
827
- "gallerySort": "rwa6qG_gallerySort",
828
- "lightboxActions": "rwa6qG_lightboxActions",
829
- "promptCount": "rwa6qG_promptCount",
830
- "reference": "rwa6qG_reference",
831
- "galleryWorkspace": "rwa6qG_galleryWorkspace",
832
- "galleryTagFilterList": "rwa6qG_galleryTagFilterList",
1070
+ "galleryTagFilter": "rwa6qG_galleryTagFilter",
1071
+ "galleryMasonry": "rwa6qG_galleryMasonry",
833
1072
  "gallerySearch": "rwa6qG_gallerySearch",
834
- "zoomHint": "rwa6qG_zoomHint",
835
- "paramGroup": "rwa6qG_paramGroup",
836
- "modelWrap": "rwa6qG_modelWrap",
837
- "comparisonFullscreen": "rwa6qG_comparisonFullscreen",
1073
+ "bigSpinner": "rwa6qG_bigSpinner",
1074
+ "comparisonImageButton": "rwa6qG_comparisonImageButton",
1075
+ "prompt": "rwa6qG_prompt",
1076
+ "lightboxActions": "rwa6qG_lightboxActions",
1077
+ "lightboxCopy": "rwa6qG_lightboxCopy",
838
1078
  "studio": "rwa6qG_studio",
839
- "lightboxClose": "rwa6qG_lightboxClose",
1079
+ "galleryClear": "rwa6qG_galleryClear",
1080
+ "uploadHint": "rwa6qG_uploadHint",
1081
+ "modelSelect": "rwa6qG_modelSelect",
1082
+ "historySearch": "rwa6qG_historySearch",
1083
+ "configGuide": "rwa6qG_configGuide",
1084
+ "paramGroup": "rwa6qG_paramGroup",
1085
+ "historyThumb": "rwa6qG_historyThumb",
1086
+ "uploadIcon": "rwa6qG_uploadIcon",
840
1087
  "lightboxCaptionRow": "rwa6qG_lightboxCaptionRow",
841
- "historyInfo": "rwa6qG_historyInfo",
842
- "generateInner": "rwa6qG_generateInner",
843
- "bigSpinner": "rwa6qG_bigSpinner",
844
- "galleryTagEditor": "rwa6qG_galleryTagEditor",
1088
+ "galleryFilterCount": "rwa6qG_galleryFilterCount",
1089
+ "modeRow": "rwa6qG_modeRow",
1090
+ "modelWrap": "rwa6qG_modelWrap",
1091
+ "canvasState": "rwa6qG_canvasState",
1092
+ "gallerySort": "rwa6qG_gallerySort",
1093
+ "panel": "rwa6qG_panel",
1094
+ "configGuideBody": "rwa6qG_configGuideBody",
1095
+ "modelMenuItem": "rwa6qG_modelMenuItem",
1096
+ "canvasStateHint": "rwa6qG_canvasStateHint",
1097
+ "lightboxTool": "rwa6qG_lightboxTool",
1098
+ "panelHeading": "rwa6qG_panelHeading",
845
1099
  "hiddenFile": "rwa6qG_hiddenFile",
846
- "templatesButton": "rwa6qG_templatesButton",
847
- "lightboxZoomLevel": "rwa6qG_lightboxZoomLevel",
848
- "canvasBody": "rwa6qG_canvasBody",
849
- "lightboxStage": "rwa6qG_lightboxStage",
850
- "download": "rwa6qG_download",
851
- "galleryCardFooter": "rwa6qG_galleryCardFooter",
852
- "canvasError": "rwa6qG_canvasError",
853
- "lightboxMeta": "rwa6qG_lightboxMeta",
1100
+ "zoomHint": "rwa6qG_zoomHint",
1101
+ "galleryCardInfo": "rwa6qG_galleryCardInfo",
854
1102
  "image": "rwa6qG_image",
855
- "historyList": "rwa6qG_historyList",
856
- "modelMenuItem": "rwa6qG_modelMenuItem",
857
- "optionPill": "rwa6qG_optionPill",
1103
+ "history": "rwa6qG_history",
858
1104
  "canvasMeta": "rwa6qG_canvasMeta",
1105
+ "canvasStateTitle": "rwa6qG_canvasStateTitle",
859
1106
  "galleryFilter": "rwa6qG_galleryFilter",
860
- "lightboxFigure": "rwa6qG_lightboxFigure",
861
- "compareToggle": "rwa6qG_compareToggle",
862
- "entry": "rwa6qG_entry",
863
- "paramLabel": "rwa6qG_paramLabel",
864
- "galleryClear": "rwa6qG_galleryClear",
865
- "historyMeta": "rwa6qG_historyMeta",
866
- "taskPrompt": "rwa6qG_taskPrompt",
867
- "modeRow": "rwa6qG_modeRow",
868
- "githubLink": "rwa6qG_githubLink",
869
- "lightboxCaption": "rwa6qG_lightboxCaption",
870
- "galleryFilterNote": "rwa6qG_galleryFilterNote",
871
- "galleryViewToggle": "rwa6qG_galleryViewToggle",
872
- "comparisonImageButton": "rwa6qG_comparisonImageButton",
873
- "taskTrayCount": "rwa6qG_taskTrayCount",
874
- "taskStatus": "rwa6qG_taskStatus",
875
- "view": "rwa6qG_view",
876
- "lightboxTools": "rwa6qG_lightboxTools",
877
- "comparisonBoard": "rwa6qG_comparisonBoard",
878
- "gallerySelect": "rwa6qG_gallerySelect",
879
- "canvasEmptyIcon": "rwa6qG_canvasEmptyIcon",
880
- "galleryAdd": "rwa6qG_galleryAdd",
881
- "modelSelect": "rwa6qG_modelSelect",
882
- "uploadHint": "rwa6qG_uploadHint",
883
- "galleryFilterCount": "rwa6qG_galleryFilterCount",
884
- "updateActions": "rwa6qG_updateActions",
885
- "config": "rwa6qG_config",
886
- "lightboxDownload": "rwa6qG_lightboxDownload",
887
- "lightboxNav": "rwa6qG_lightboxNav",
888
- "historyEmpty": "rwa6qG_historyEmpty",
889
1107
  "galleryToolbar": "rwa6qG_galleryToolbar",
890
- "galleryHeading": "rwa6qG_galleryHeading",
891
- "comparisonFullscreenGrid": "rwa6qG_comparisonFullscreenGrid",
892
- "taskTrayChevron": "rwa6qG_taskTrayChevron",
893
- "galleryTagEdit": "rwa6qG_galleryTagEdit",
1108
+ "config": "rwa6qG_config",
1109
+ "historyInfo": "rwa6qG_historyInfo",
894
1110
  "updateRelease": "rwa6qG_updateRelease",
895
- "updateText": "rwa6qG_updateText",
896
- "historyThumbPlaceholder": "rwa6qG_historyThumbPlaceholder",
897
- "panel": "rwa6qG_panel",
898
- "imageCard": "rwa6qG_imageCard",
899
- "galleryBadge": "rwa6qG_galleryBadge",
900
- "paramHint": "rwa6qG_paramHint",
901
- "configScroll": "rwa6qG_configScroll",
902
- "modePill": "rwa6qG_modePill",
1111
+ "lightbox": "rwa6qG_lightbox",
1112
+ "taskTrayToggle": "rwa6qG_taskTrayToggle",
1113
+ "connectionStatus": "rwa6qG_connectionStatus",
1114
+ "historyClear": "rwa6qG_historyClear",
1115
+ "modelLabel": "rwa6qG_modelLabel",
1116
+ "canvasBody": "rwa6qG_canvasBody",
1117
+ "lightboxImage": "rwa6qG_lightboxImage",
1118
+ "galleryFilters": "rwa6qG_galleryFilters",
1119
+ "galleryFilterHeading": "rwa6qG_galleryFilterHeading",
903
1120
  "historyFilters": "rwa6qG_historyFilters",
904
- "panelTitle": "rwa6qG_panelTitle",
905
- "entryLabel": "rwa6qG_entryLabel",
906
- "footer": "rwa6qG_footer",
907
- "imageCaption": "rwa6qG_imageCaption",
908
- "panelHeading": "rwa6qG_panelHeading",
909
- "compareModelChoices": "rwa6qG_compareModelChoices",
910
- "compareControl": "rwa6qG_compareControl",
911
- "historySearch": "rwa6qG_historySearch",
912
- "galleryCard": "rwa6qG_galleryCard",
1121
+ "dshImageGenSpin": "rwa6qG_dshImageGenSpin",
913
1122
  "uploadBox": "rwa6qG_uploadBox",
914
- "galleryAvatar": "rwa6qG_galleryAvatar",
915
- "taskTray": "rwa6qG_taskTray",
1123
+ "gallerySelectionBar": "rwa6qG_gallerySelectionBar",
1124
+ "comparisonBoard": "rwa6qG_comparisonBoard",
916
1125
  "historyItem": "rwa6qG_historyItem",
917
- "promptFooter": "rwa6qG_promptFooter",
918
- "canvasStateTitle": "rwa6qG_canvasStateTitle",
919
- "lightboxTool": "rwa6qG_lightboxTool",
920
- "galleryFilterDivider": "rwa6qG_galleryFilterDivider",
921
- "historyActions": "rwa6qG_historyActions",
922
- "modelMenuList": "rwa6qG_modelMenuList",
923
- "historyPrompt": "rwa6qG_historyPrompt",
924
- "taskRows": "rwa6qG_taskRows",
925
- "configGuideBody": "rwa6qG_configGuideBody",
926
- "grid": "rwa6qG_grid",
927
- "modelLabel": "rwa6qG_modelLabel",
928
- "uploadIcon": "rwa6qG_uploadIcon",
929
- "galleryToast": "rwa6qG_galleryToast",
930
- "updateBanner": "rwa6qG_updateBanner",
931
- "lightboxIndex": "rwa6qG_lightboxIndex",
932
- "lightboxEdit": "rwa6qG_lightboxEdit",
933
- "lightboxScaleFrame": "rwa6qG_lightboxScaleFrame",
934
- "enhanceButton": "rwa6qG_enhanceButton",
935
- "galleryFilterHeading": "rwa6qG_galleryFilterHeading",
936
- "referenceImage": "rwa6qG_referenceImage",
937
- "galleryRatio": "rwa6qG_galleryRatio",
938
- "galleryCount": "rwa6qG_galleryCount",
939
1126
  "galleryTags": "rwa6qG_galleryTags",
1127
+ "galleryCount": "rwa6qG_galleryCount",
1128
+ "galleryTagEditor": "rwa6qG_galleryTagEditor",
1129
+ "compareToggle": "rwa6qG_compareToggle",
1130
+ "card": "rwa6qG_card",
1131
+ "updateText": "rwa6qG_updateText",
1132
+ "paramLabel": "rwa6qG_paramLabel",
1133
+ "historyMain": "rwa6qG_historyMain",
940
1134
  "optionRow": "rwa6qG_optionRow",
941
- "taskTrayHeader": "rwa6qG_taskTrayHeader",
1135
+ "lightboxStage": "rwa6qG_lightboxStage",
1136
+ "galleryRatioList": "rwa6qG_galleryRatioList",
1137
+ "taskTray": "rwa6qG_taskTray",
1138
+ "paramHint": "rwa6qG_paramHint",
942
1139
  "galleryRemove": "rwa6qG_galleryRemove",
943
- "generateButton": "rwa6qG_generateButton",
944
- "historyTitle": "rwa6qG_historyTitle",
945
- "historyThumb": "rwa6qG_historyThumb",
946
- "gallerySelectionBar": "rwa6qG_gallerySelectionBar",
947
- "spinner": "rwa6qG_spinner",
948
- "historyHeader": "rwa6qG_historyHeader",
949
- "modelMenu": "rwa6qG_modelMenu",
950
- "history": "rwa6qG_history",
1140
+ "imageCaption": "rwa6qG_imageCaption",
1141
+ "galleryTagFilterList": "rwa6qG_galleryTagFilterList",
1142
+ "historyMeta": "rwa6qG_historyMeta",
1143
+ "lightboxZoomLevel": "rwa6qG_lightboxZoomLevel",
1144
+ "galleryHeading": "rwa6qG_galleryHeading",
1145
+ "reference": "rwa6qG_reference",
1146
+ "galleryImageButton": "rwa6qG_galleryImageButton",
1147
+ "historyList": "rwa6qG_historyList",
1148
+ "historyPrompt": "rwa6qG_historyPrompt",
1149
+ "modelMenuList": "rwa6qG_modelMenuList",
1150
+ "galleryFilterDivider": "rwa6qG_galleryFilterDivider",
1151
+ "galleryViewToggle": "rwa6qG_galleryViewToggle",
1152
+ "lightboxClose": "rwa6qG_lightboxClose",
1153
+ "galleryRatio": "rwa6qG_galleryRatio",
1154
+ "canvasEmptyIcon": "rwa6qG_canvasEmptyIcon",
951
1155
  "canvasHistoryTag": "rwa6qG_canvasHistoryTag",
952
- "galleryCardInfo": "rwa6qG_galleryCardInfo",
1156
+ "lightboxCaption": "rwa6qG_lightboxCaption",
1157
+ "lightboxMeta": "rwa6qG_lightboxMeta",
953
1158
  "historyAction": "rwa6qG_historyAction",
954
- "galleryImageButton": "rwa6qG_galleryImageButton",
955
- "taskTrayToggle": "rwa6qG_taskTrayToggle",
956
- "prompt": "rwa6qG_prompt",
957
- "comparisonGrid": "rwa6qG_comparisonGrid",
958
- "canvasState": "rwa6qG_canvasState",
959
- "galleryToolbarActions": "rwa6qG_galleryToolbarActions",
960
- "connectionStatus": "rwa6qG_connectionStatus",
961
- "entryIcon": "rwa6qG_entryIcon",
962
- "galleryImage": "rwa6qG_galleryImage",
1159
+ "enhanceButton": "rwa6qG_enhanceButton",
1160
+ "taskTrayChevron": "rwa6qG_taskTrayChevron",
1161
+ "spinner": "rwa6qG_spinner",
1162
+ "generateInner": "rwa6qG_generateInner",
963
1163
  "taskRow": "rwa6qG_taskRow",
964
- "lightboxImage": "rwa6qG_lightboxImage",
965
- "galleryRatioList": "rwa6qG_galleryRatioList",
966
- "gallerySelectionClear": "rwa6qG_gallerySelectionClear",
967
- "historyMain": "rwa6qG_historyMain",
968
- "card": "rwa6qG_card",
969
- "dshImageGenSpin": "rwa6qG_dshImageGenSpin",
970
- "dshImageGenToastIn": "rwa6qG_dshImageGenToastIn",
971
- "galleryTagFilter": "rwa6qG_galleryTagFilter",
972
- "galleryMasonry": "rwa6qG_galleryMasonry",
1164
+ "lightboxNav": "rwa6qG_lightboxNav",
1165
+ "lightboxDownload": "rwa6qG_lightboxDownload",
1166
+ "promptFooter": "rwa6qG_promptFooter",
1167
+ "grid": "rwa6qG_grid",
1168
+ "referenceImage": "rwa6qG_referenceImage",
1169
+ "imageCard": "rwa6qG_imageCard",
1170
+ "galleryToast": "rwa6qG_galleryToast",
1171
+ "galleryBadge": "rwa6qG_galleryBadge",
1172
+ "galleryCardFooter": "rwa6qG_galleryCardFooter",
1173
+ "comparisonFullscreen": "rwa6qG_comparisonFullscreen",
1174
+ "historyEmpty": "rwa6qG_historyEmpty",
1175
+ "galleryToolbarActions": "rwa6qG_galleryToolbarActions",
1176
+ "taskTrayCount": "rwa6qG_taskTrayCount",
973
1177
  "taskTrayClose": "rwa6qG_taskTrayClose",
974
- "configGuide": "rwa6qG_configGuide",
975
- "galleryFilters": "rwa6qG_galleryFilters",
1178
+ "templatesButton": "rwa6qG_templatesButton",
976
1179
  "gallerySelectMode": "rwa6qG_gallerySelectMode",
977
- "canvasStateHint": "rwa6qG_canvasStateHint",
1180
+ "githubLink": "rwa6qG_githubLink",
1181
+ "compareModelChoices": "rwa6qG_compareModelChoices",
1182
+ "entry": "rwa6qG_entry",
1183
+ "footer": "rwa6qG_footer",
1184
+ "galleryCard": "rwa6qG_galleryCard",
1185
+ "entryLabel": "rwa6qG_entryLabel",
1186
+ "optionPill": "rwa6qG_optionPill",
1187
+ "panelHeader": "rwa6qG_panelHeader",
1188
+ "galleryAvatar": "rwa6qG_galleryAvatar",
1189
+ "historyTitle": "rwa6qG_historyTitle",
978
1190
  "galleryTagInput": "rwa6qG_galleryTagInput",
979
- "lightbox": "rwa6qG_lightbox",
980
1191
  "connectionDot": "rwa6qG_connectionDot",
981
- "panelHeader": "rwa6qG_panelHeader",
982
- "referenceActions": "rwa6qG_referenceActions"
1192
+ "dshImageGenToastIn": "rwa6qG_dshImageGenToastIn",
1193
+ "modePill": "rwa6qG_modePill",
1194
+ "gallerySelectionClear": "rwa6qG_gallerySelectionClear",
1195
+ "panelTitle": "rwa6qG_panelTitle",
1196
+ "galleryWorkspace": "rwa6qG_galleryWorkspace",
1197
+ "taskTrayHeader": "rwa6qG_taskTrayHeader",
1198
+ "galleryTagEdit": "rwa6qG_galleryTagEdit",
1199
+ "galleryFilterNote": "rwa6qG_galleryFilterNote",
1200
+ "comparisonGrid": "rwa6qG_comparisonGrid",
1201
+ "lightboxEdit": "rwa6qG_lightboxEdit",
1202
+ "comparisonFullscreenGrid": "rwa6qG_comparisonFullscreenGrid",
1203
+ "lightboxScaleFrame": "rwa6qG_lightboxScaleFrame",
1204
+ "taskPrompt": "rwa6qG_taskPrompt",
1205
+ "optionGrid": "rwa6qG_optionGrid",
1206
+ "download": "rwa6qG_download",
1207
+ "lightboxFigure": "rwa6qG_lightboxFigure",
1208
+ "view": "rwa6qG_view",
1209
+ "compareControl": "rwa6qG_compareControl",
1210
+ "taskRows": "rwa6qG_taskRows",
1211
+ "historyActions": "rwa6qG_historyActions",
1212
+ "canvasError": "rwa6qG_canvasError",
1213
+ "galleryAdd": "rwa6qG_galleryAdd"
983
1214
  };
984
1215
  //#endregion
985
1216
  //#region src/client/mount.tsx
@@ -1626,7 +1857,7 @@ window.__ModuleLoader__.load({
1626
1857
  }
1627
1858
  //#endregion
1628
1859
  //#region \0dsh-css:/Users/shimingming/Projects_code/dsh-audiogen/src/client/settings-card.module.css.mjs
1629
- const css$1 = ".zmjoSq_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}.zmjoSq_card:hover{border-color:var(--dsw-alias-label-dimmed)}.zmjoSq_card:has(.zmjoSq_body){background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-label-dimmed)}.zmjoSq_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}.zmjoSq_header:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}.zmjoSq_headText{flex-direction:column;flex:1;gap:4px;min-width:0;display:flex}.zmjoSq_name{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}.zmjoSq_description{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}.zmjoSq_chevron,.zmjoSq_chevronOpen{color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .16s}.zmjoSq_chevronOpen{transform:rotate(180deg)}.zmjoSq_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}.zmjoSq_body{border-top:1px solid var(--dsw-alias-border-l2);margin:0 16px;padding-bottom:8px}.zmjoSq_versionRow{border-bottom:1px solid var(--dsw-alias-border-l2);justify-content:space-between;align-items:center;gap:12px;padding:12px 0;display:flex}.zmjoSq_versionLabel{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:500;line-height:1.5}.zmjoSq_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}.zmjoSq_field{flex-direction:column;gap:6px;padding:12px 0;display:flex}.zmjoSq_field+.zmjoSq_field{border-top:1px solid var(--dsw-alias-border-l2)}.zmjoSq_head{align-items:center;gap:8px;display:flex}.zmjoSq_label{min-width:0;color:var(--dsw-alias-label-primary);flex:1;font-size:13px;font-weight:500;line-height:1.5}.zmjoSq_badges{align-items:center;gap:8px;display:inline-flex}.zmjoSq_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}.zmjoSq_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}.zmjoSq_reset:hover:not(:disabled){color:var(--dsw-alias-label-primary)}.zmjoSq_reset:disabled{cursor:default;opacity:.5}.zmjoSq_input,.zmjoSq_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}.zmjoSq_input:focus-visible,.zmjoSq_select:focus-visible{border-color:var(--dsw-alias-brand-primary)}.zmjoSq_input:disabled,.zmjoSq_select:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}.zmjoSq_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}.zmjoSq_textarea,.zmjoSq_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}.zmjoSq_textarea{border:1px solid var(--dsw-alias-border-l2)}.zmjoSq_textareaInvalid{border:1px solid var(--dsw-alias-label-error)}.zmjoSq_textarea:focus-visible{border-color:var(--dsw-alias-brand-primary)}.zmjoSq_textarea:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}.zmjoSq_hint,.zmjoSq_invalid{margin:0;font-size:12px;line-height:1.5}.zmjoSq_hint{color:var(--dsw-alias-label-tertiary)}.zmjoSq_invalid{color:var(--dsw-alias-label-error)}.zmjoSq_readOnly,.zmjoSq_notExposed{color:var(--dsw-alias-label-tertiary);margin:12px 0 0;font-size:12px;line-height:1.5}.zmjoSq_sectionDivider{background:var(--dsw-alias-border-l2);height:1px;margin:18px 0 14px}.zmjoSq_sectionTitle{color:var(--dsw-alias-label-primary);margin:0;font-size:14px;line-height:1.4}.zmjoSq_sectionHint{color:var(--dsw-alias-label-tertiary);margin:-4px 0 2px;font-size:12px;line-height:1.5}.zmjoSq_modelSection{padding:2px 0 14px}.zmjoSq_sectionHeader{justify-content:space-between;align-items:flex-start;gap:12px;display:flex}.zmjoSq_sectionHeader .zmjoSq_sectionHint{max-width:430px}.zmjoSq_modelSummary{flex-wrap:wrap;align-items:center;gap:6px;margin-top:12px;display:flex}.zmjoSq_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}.zmjoSq_modelChip>span{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.zmjoSq_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}.zmjoSq_modelChip button:hover:not(:disabled){color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-module-platform)}.zmjoSq_modelChip button:disabled{cursor:default;opacity:.45}.zmjoSq_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}.zmjoSq_addModel:hover:not(:disabled){color:var(--dsw-alias-brand-primary);border-color:var(--dsw-alias-brand-primary)}.zmjoSq_addModel:disabled{opacity:.45;cursor:default}.zmjoSq_manualModelRow{gap:8px;margin-top:10px;display:flex}.zmjoSq_manualModelRow .zmjoSq_input{flex:1;min-width:0}.zmjoSq_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}.zmjoSq_disclosure>span:nth-child(2){color:var(--dsw-alias-label-tertiary);margin-left:auto;font-size:12px;font-weight:400}.zmjoSq_disclosure>span:last-child{color:var(--dsw-alias-label-tertiary)}.zmjoSq_disclosure:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}.zmjoSq_optionalContent{padding:0 0 8px}.zmjoSq_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}.zmjoSq_inlineDisclosure:hover{color:var(--dsw-alias-label-primary)}.zmjoSq_modelFetchRow{align-items:center;gap:8px;display:flex}.zmjoSq_modelFetch,.zmjoSq_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}.zmjoSq_modelFetch{cursor:pointer;padding:0 10px}.zmjoSq_modelFetch:hover:not(:disabled){color:var(--dsw-alias-brand-primary);border-color:var(--dsw-alias-brand-primary)}.zmjoSq_modelFetch:disabled{opacity:.5;cursor:default}.zmjoSq_modelChoices{flex:1;min-width:0;padding:0 8px}.zmjoSq_modelCandidateList{flex-wrap:wrap;gap:6px 10px;margin-top:10px;display:flex}.zmjoSq_modelCandidateLabel{width:100%;color:var(--dsw-alias-label-tertiary);font-size:12px}.zmjoSq_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}.zmjoSq_modelCandidate input{margin:0}.zmjoSq_modelCandidate[data-selected]{border-color:var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary)}.zmjoSq_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}.zmjoSq_failed{min-width:0;color:var(--dsw-alias-label-error);flex:1;margin:0;font-size:12px;line-height:1.5}.zmjoSq_discard,.zmjoSq_save{appearance:none;font:inherit;cursor:pointer;border:1px solid #0000;border-radius:8px;padding:5px 14px;font-size:13px;line-height:1.5}.zmjoSq_discard{border-color:var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);background:0 0}.zmjoSq_discard:hover:not(:disabled){color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-dimmed)}.zmjoSq_save{background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-layer-3)}.zmjoSq_discard:disabled,.zmjoSq_save:disabled{opacity:.4;cursor:default}.zmjoSq_discard:focus-visible,.zmjoSq_save:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}@media (prefers-reduced-motion:reduce){.zmjoSq_card,.zmjoSq_chevron,.zmjoSq_chevronOpen{transition:none}}.zmjoSq_channelSection{padding:6px 0 2px}.zmjoSq_channelEmpty{color:var(--dsw-alias-label-tertiary);margin:10px 0 0;font-size:12px;line-height:1.5}.zmjoSq_channelList{flex-direction:column;gap:6px;margin:10px 0 0;padding:0;list-style:none;display:flex}.zmjoSq_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}.zmjoSq_channelRow[data-action]{flex-wrap:wrap}.zmjoSq_channelDotReady,.zmjoSq_channelDotWarn{border-radius:50%;flex:none;width:9px;height:9px}.zmjoSq_channelDotReady{background:var(--dsw-color-success,#2fbf71)}.zmjoSq_channelDotWarn{background:var(--dsw-color-danger,#e5484d)}.zmjoSq_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}.zmjoSq_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}.zmjoSq_channelMeta{flex-wrap:wrap;align-items:center;gap:4px 8px;display:flex}.zmjoSq_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}.zmjoSq_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}.zmjoSq_channelBadge[data-warn]{color:var(--dsw-alias-label-error)}.zmjoSq_channelBadge[data-default]{background:var(--dsw-alias-bg-module-poped,var(--dsw-alias-bg-module-platform));color:var(--dsw-alias-brand-primary)}.zmjoSq_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}.zmjoSq_channelAction:hover:not(:disabled){color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-module-platform)}.zmjoSq_channelAction[data-danger]{color:var(--dsw-alias-label-error)}.zmjoSq_channelAction:disabled{opacity:.45;cursor:default}.zmjoSq_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}.zmjoSq_channelDanger:hover:not(:disabled){background:color-mix(in srgb, var(--dsw-alias-label-error) 12%, transparent)}.zmjoSq_channelDanger:disabled{opacity:.45;cursor:default}.zmjoSq_deleteConfirmText{min-width:0;color:var(--dsw-alias-label-error);flex:1;font-size:12px;line-height:1.5}.zmjoSq_channelAddRow{gap:8px;margin-top:10px;display:flex}.zmjoSq_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}.zmjoSq_channelAdd:hover:not(:disabled){color:var(--dsw-alias-brand-primary);border-color:var(--dsw-alias-brand-primary)}.zmjoSq_channelAdd:disabled{opacity:.45;cursor:default}.zmjoSq_spacer{flex:1}.zmjoSq_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}.zmjoSq_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}.zmjoSq_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}.zmjoSq_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}.zmjoSq_editorClose:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-module-platform)}.zmjoSq_editorField{flex-direction:column;gap:6px;padding:12px 0 0;display:flex}.zmjoSq_editorDivider{background:var(--dsw-alias-border-l2);height:1px;margin:14px 0 4px}.zmjoSq_editorSectionHeader{justify-content:space-between;align-items:center;gap:12px;padding:10px 0 4px;display:flex}.zmjoSq_editorSectionHeader .zmjoSq_label{flex:1}.zmjoSq_editorTools{flex-direction:column;gap:8px;margin-top:10px;display:flex}.zmjoSq_editorFooter{border-top:1px solid var(--dsw-alias-border-l2);align-items:center;gap:8px;padding-top:12px;display:flex}.zmjoSq_detectOk{color:var(--dsw-color-success,var(--dsw-alias-label-secondary));margin:0;font-size:12px;line-height:1.5}.zmjoSq_modelRows{flex-direction:column;gap:8px;margin:8px 0 0;padding:0;list-style:none;display:flex}.zmjoSq_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}.zmjoSq_modelRowInputs{flex:1;align-items:center;gap:6px;min-width:0;display:flex}.zmjoSq_modelRowInputs .zmjoSq_input{flex:1;min-width:0}.zmjoSq_modelArrow{color:var(--dsw-alias-label-tertiary);flex:none;font-size:12px}.zmjoSq_modelRowBadges{flex:none;align-items:center;gap:6px;display:flex}.zmjoSq_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}.zmjoSq_modelBadge[data-verified]{color:var(--dsw-color-success,var(--dsw-alias-label-secondary))}.zmjoSq_modelBadge[data-warn]{color:var(--dsw-alias-label-error)}.zmjoSq_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}.zmjoSq_modelRowRemove:hover:not(:disabled){color:var(--dsw-alias-label-error);background:var(--dsw-alias-bg-module-platform)}.zmjoSq_modelRowRemove:disabled{opacity:.45;cursor:default}.zmjoSq_modelCandidate>.zmjoSq_modelBadge{flex:none}.zmjoSq_channelControls{position:relative}.zmjoSq_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}.zmjoSq_presetInlineHeader{justify-content:space-between;align-items:flex-start;gap:12px;display:flex}.zmjoSq_presetList{flex-direction:column;gap:8px;margin-top:12px;display:flex}.zmjoSq_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}.zmjoSq_presetRow:hover:not(:disabled){border-color:var(--dsw-alias-brand-primary)}.zmjoSq_presetRow[data-custom]{border-style:dashed}.zmjoSq_presetRow:disabled{opacity:.5;cursor:default}.zmjoSq_presetName{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:600;line-height:1.4}.zmjoSq_presetMeta{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:1.5;font-family:var(--dsw-font-family-mono,monospace)}.zmjoSq_presetHint{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.5}";
1860
+ const css$1 = ".zmjoSq_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}.zmjoSq_card:hover{border-color:var(--dsw-alias-label-dimmed)}.zmjoSq_card:has(.zmjoSq_body){background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-label-dimmed)}.zmjoSq_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}.zmjoSq_header:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}.zmjoSq_headText{flex-direction:column;flex:1;gap:4px;min-width:0;display:flex}.zmjoSq_name{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}.zmjoSq_description{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}.zmjoSq_chevron,.zmjoSq_chevronOpen{color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .16s}.zmjoSq_chevronOpen{transform:rotate(180deg)}.zmjoSq_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}.zmjoSq_body{border-top:1px solid var(--dsw-alias-border-l2);margin:0 16px;padding-bottom:8px}.zmjoSq_field{flex-direction:column;gap:6px;padding:12px 0;display:flex}.zmjoSq_field+.zmjoSq_field{border-top:1px solid var(--dsw-alias-border-l2)}.zmjoSq_head{align-items:center;gap:8px;display:flex}.zmjoSq_label{min-width:0;color:var(--dsw-alias-label-primary);flex:1;font-size:13px;font-weight:500;line-height:1.5}.zmjoSq_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}.zmjoSq_reset:hover:not(:disabled){color:var(--dsw-alias-label-primary)}.zmjoSq_reset:disabled{cursor:default;opacity:.5}.zmjoSq_input,.zmjoSq_select{box-sizing:border-box;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}.zmjoSq_input:focus-visible,.zmjoSq_select:focus-visible{border-color:var(--dsw-alias-brand-primary)}.zmjoSq_input:disabled,.zmjoSq_select:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}.zmjoSq_sectionTitle{color:var(--dsw-alias-label-primary);margin:0;font-size:14px;line-height:1.4}.zmjoSq_sectionHint{color:var(--dsw-alias-label-tertiary);margin:-4px 0 2px;font-size:12px;line-height:1.5}.zmjoSq_sectionHeader{justify-content:space-between;align-items:flex-start;gap:12px;display:flex}.zmjoSq_sectionHeader .zmjoSq_sectionHint{max-width:430px}.zmjoSq_readOnly{color:var(--dsw-alias-label-tertiary);margin:12px 0 0;font-size:12px;line-height:1.5}.zmjoSq_link{color:var(--dsw-alias-brand-primary);text-decoration:none}.zmjoSq_link:hover{text-decoration:underline}.zmjoSq_channelSection{padding:6px 0 2px}.zmjoSq_channelEmpty{color:var(--dsw-alias-label-tertiary);margin:10px 0 0;font-size:12px;line-height:1.5}.zmjoSq_channelList{flex-direction:column;gap:6px;margin:10px 0 0;padding:0;list-style:none;display:flex}.zmjoSq_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}.zmjoSq_channelRow[data-action]{flex-wrap:wrap}.zmjoSq_channelDotReady,.zmjoSq_channelDotWarn{border-radius:50%;flex:none;width:9px;height:9px}.zmjoSq_channelDotReady{background:var(--dsw-color-success,#2fbf71)}.zmjoSq_channelDotWarn{background:var(--dsw-color-danger,#e5484d)}.zmjoSq_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}.zmjoSq_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}.zmjoSq_channelMeta{flex-wrap:wrap;align-items:center;gap:4px 8px;display:flex}.zmjoSq_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}.zmjoSq_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}.zmjoSq_channelBadge[data-warn]{color:var(--dsw-alias-label-error)}.zmjoSq_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}.zmjoSq_channelAction:hover:not(:disabled){color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-module-platform)}.zmjoSq_channelAction[data-danger]{color:var(--dsw-alias-label-error)}.zmjoSq_channelAction:disabled{opacity:.45;cursor:default}.zmjoSq_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}.zmjoSq_channelDanger:hover:not(:disabled){background:color-mix(in srgb, var(--dsw-alias-label-error) 12%, transparent)}.zmjoSq_channelDanger:disabled{opacity:.45;cursor:default}.zmjoSq_deleteConfirmText{min-width:0;color:var(--dsw-alias-label-error);flex:1;font-size:12px;line-height:1.5}.zmjoSq_channelAddRow{flex-wrap:wrap;gap:10px;margin-top:10px;display:flex}.zmjoSq_channelAdd{appearance:none;border:1px dashed var(--dsw-alias-border-l3,var(--dsw-alias-border-l2));min-width:180px;min-height:44px;color:var(--dsw-alias-label-secondary);font:inherit;cursor:pointer;background:0 0;border-radius:12px;flex:1 1 0;padding:0 12px;font-size:12px}.zmjoSq_channelAdd:hover:not(:disabled){color:var(--dsw-alias-brand-primary);border-color:var(--dsw-alias-brand-primary)}.zmjoSq_channelAdd:disabled{opacity:.45;cursor:default}.zmjoSq_editorWrap{margin-top:10px}.zmjoSq_channelEditor{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-module-platform);border-radius:12px;flex-direction:column;gap:2px;padding:14px 16px;display:flex}.zmjoSq_editorHeader{align-items:baseline;gap:8px;padding-bottom:4px;display:flex}.zmjoSq_editorTitle{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:600;line-height:22px}.zmjoSq_editorTag{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}.zmjoSq_customSettings{border-top:1px solid var(--dsw-alias-border-l2);margin-top:6px;padding-top:10px}.zmjoSq_customSettingsSummary{cursor:pointer;width:fit-content;color:var(--dsw-alias-label-secondary);border-radius:6px;align-items:center;gap:6px;margin-left:-4px;padding:2px 4px;font-size:12px;font-weight:500;line-height:18px;list-style:none;display:flex}.zmjoSq_customSettingsSummary::-webkit-details-marker{display:none}.zmjoSq_customSettingsSummary:before{content:\"\";border-bottom:1.5px solid;border-right:1.5px solid;width:5px;height:5px;transition:transform .12s;transform:rotate(-45deg)translate(-1px,-1px)}.zmjoSq_customSettings[open]>.zmjoSq_customSettingsSummary:before{transform:rotate(45deg)translate(-1px,-1px)}.zmjoSq_customSettingsSummary:hover{color:var(--dsw-alias-label-primary)}.zmjoSq_customSettingsSummary:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}.zmjoSq_customSettingsBody{flex-direction:column;gap:6px;padding-top:10px;display:flex}.zmjoSq_modelCatalog{border-top:1px solid var(--dsw-alias-border-l2);flex-direction:column;gap:10px;margin-top:6px;padding-top:12px;display:flex}.zmjoSq_modelCatalogHead{justify-content:space-between;align-items:flex-start;gap:12px;display:flex}.zmjoSq_modelCatalogTitle{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:500;line-height:1.5;display:block}.zmjoSq_modelCatalogMeta{color:var(--dsw-alias-label-tertiary);margin-top:1px;font-size:12px;line-height:1.5;display:block}.zmjoSq_linkButton{box-sizing:border-box;height:28px;color:var(--dsw-alias-label-tertiary);font:inherit;cursor:pointer;background:0 0;border:none;border-radius:14px;align-items:center;padding:0 10px;font-size:12px;line-height:18px;display:inline-flex}.zmjoSq_linkButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover,var(--dsw-alias-bg-module-platform));color:var(--dsw-alias-label-secondary)}.zmjoSq_linkButton:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}.zmjoSq_linkButton:disabled{opacity:.5;cursor:default}.zmjoSq_modelEmpty{border:1px dashed var(--dsw-alias-border-l3,var(--dsw-alias-border-l2));text-align:center;color:var(--dsw-alias-label-tertiary);border-radius:8px;margin:0;padding:12px;font-size:12px;line-height:18px}.zmjoSq_modelRows{flex-direction:column;gap:8px;margin:0;padding:0;list-style:none;display:flex}.zmjoSq_modelRow{grid-template-columns:minmax(0,1fr) auto minmax(0,1.2fr) auto auto;align-items:center;gap:6px;display:grid}.zmjoSq_modelInput{min-width:0;height:32px}.zmjoSq_modelArrow{color:var(--dsw-alias-label-tertiary);font-size:12px}.zmjoSq_modelCategorySelect{cursor:pointer;min-width:0;max-width:108px;height:32px;padding:0 6px}.zmjoSq_modelRowRemove{appearance:none;width:24px;height:24px;color:var(--dsw-alias-label-tertiary);font:inherit;cursor:pointer;background:0 0;border:0;border-radius:6px;flex:none;padding:0;font-size:14px;line-height:24px}.zmjoSq_modelRowRemove:hover:not(:disabled){color:var(--dsw-alias-label-error);background:var(--dsw-alias-bg-module-platform)}.zmjoSq_modelRowRemove:disabled{opacity:.45;cursor:default}.zmjoSq_modelCatalogTools{align-items:center;gap:8px;display:flex}.zmjoSq_addModel{appearance:none;border:1px solid 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}.zmjoSq_addModel:hover:not(:disabled){color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-dimmed)}.zmjoSq_addModel:disabled{opacity:.45;cursor:default}.zmjoSq_modelBadge{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-tertiary);border-radius:999px;flex:none;padding:0 7px;font-size:11px;line-height:17px}.zmjoSq_detectOk{color:var(--dsw-color-success,var(--dsw-alias-label-secondary));margin:0;font-size:12px;line-height:1.5}.zmjoSq_candidatePanel{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:10px;flex-direction:column;gap:8px;padding:10px 12px;display:flex}.zmjoSq_candidateHead{justify-content:space-between;align-items:center;gap:12px;display:flex}.zmjoSq_candidateTitle{color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:500;line-height:18px}.zmjoSq_candidateList{flex-direction:column;gap:4px;max-height:220px;margin:0;padding:0;list-style:none;display:flex;overflow-y:auto}.zmjoSq_candidate{align-items:center;display:flex}.zmjoSq_candidateLabel{min-width:0;color:var(--dsw-alias-label-secondary);cursor:pointer;align-items:center;gap:7px;padding:4px 2px;font-size:12px;line-height:1.5;display:inline-flex}.zmjoSq_candidateLabel input{margin:0}.zmjoSq_candidateLabel:has(input:disabled){opacity:.55;cursor:default}.zmjoSq_candidateId{text-overflow:ellipsis;white-space:nowrap;font-family:var(--dsw-font-family-mono,monospace);overflow:hidden}.zmjoSq_candidateActions{justify-content:flex-end;align-items:center;gap:8px;display:flex}.zmjoSq_footer,.zmjoSq_editorFooter{border-top:1px solid var(--dsw-alias-border-l2);justify-content:flex-end;align-items:center;gap:8px;padding:12px 0 4px;display:flex}.zmjoSq_editorFooter{margin-top:8px}.zmjoSq_failed{min-width:0;color:var(--dsw-alias-label-error);flex:1;margin:0;font-size:12px;line-height:1.5}.zmjoSq_discard,.zmjoSq_save{appearance:none;font:inherit;cursor:pointer;border:1px solid #0000;border-radius:8px;padding:5px 14px;font-size:13px;line-height:1.5}.zmjoSq_discard{border-color:var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);background:0 0}.zmjoSq_discard:hover:not(:disabled){color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-dimmed)}.zmjoSq_save{background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-layer-3)}.zmjoSq_discard:disabled,.zmjoSq_save:disabled{opacity:.4;cursor:default}.zmjoSq_discard:focus-visible,.zmjoSq_save:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}@media (prefers-reduced-motion:reduce){.zmjoSq_card,.zmjoSq_chevron,.zmjoSq_chevronOpen{transition:none}}";
1630
1861
  const tagId$1 = "dsh-audiogen/settings-card.module.css";
1631
1862
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
1632
1863
  const tag = document.createElement("style");
@@ -1636,97 +1867,79 @@ window.__ModuleLoader__.load({
1636
1867
  document.head.appendChild(tag);
1637
1868
  }
1638
1869
  var settings_card_module_css_default = {
1639
- "modelFetch": "zmjoSq_modelFetch",
1640
- "channelHost": "zmjoSq_channelHost",
1641
- "channelEmpty": "zmjoSq_channelEmpty",
1642
- "notExposed": "zmjoSq_notExposed",
1643
- "modelChip": "zmjoSq_modelChip",
1644
- "editorClose": "zmjoSq_editorClose",
1645
- "versionValue": "zmjoSq_versionValue",
1646
- "editorTools": "zmjoSq_editorTools",
1647
- "inlineDisclosure": "zmjoSq_inlineDisclosure",
1648
- "channelAdd": "zmjoSq_channelAdd",
1649
- "modelRow": "zmjoSq_modelRow",
1650
- "channelAddRow": "zmjoSq_channelAddRow",
1651
- "presetRow": "zmjoSq_presetRow",
1652
- "editorDivider": "zmjoSq_editorDivider",
1653
- "presetInline": "zmjoSq_presetInline",
1654
- "sectionTitle": "zmjoSq_sectionTitle",
1655
- "head": "zmjoSq_head",
1656
- "presetList": "zmjoSq_presetList",
1657
- "presetName": "zmjoSq_presetName",
1658
- "pending": "zmjoSq_pending",
1659
- "body": "zmjoSq_body",
1660
- "manualModelRow": "zmjoSq_manualModelRow",
1661
- "modelChoices": "zmjoSq_modelChoices",
1662
- "footer": "zmjoSq_footer",
1663
- "inputInvalid": "zmjoSq_inputInvalid",
1664
- "readOnly": "zmjoSq_readOnly",
1665
- "textarea": "zmjoSq_textarea",
1666
- "header": "zmjoSq_header",
1667
- "presetHint": "zmjoSq_presetHint",
1668
- "versionRow": "zmjoSq_versionRow",
1669
- "editorField": "zmjoSq_editorField",
1670
- "presetInlineHeader": "zmjoSq_presetInlineHeader",
1671
- "chevron": "zmjoSq_chevron",
1672
- "editorFooter": "zmjoSq_editorFooter",
1673
- "channelList": "zmjoSq_channelList",
1674
- "badge": "zmjoSq_badge",
1675
- "failed": "zmjoSq_failed",
1870
+ "footer": "zmjoSq_footer",
1676
1871
  "save": "zmjoSq_save",
1677
- "channelAction": "zmjoSq_channelAction",
1678
- "channelRow": "zmjoSq_channelRow",
1679
- "input": "zmjoSq_input",
1680
- "card": "zmjoSq_card",
1681
- "discard": "zmjoSq_discard",
1682
- "channelMeta": "zmjoSq_channelMeta",
1683
- "textareaInvalid": "zmjoSq_textareaInvalid",
1684
- "hint": "zmjoSq_hint",
1685
- "editorHeader": "zmjoSq_editorHeader",
1686
- "modelSection": "zmjoSq_modelSection",
1687
- "description": "zmjoSq_description",
1688
- "detectOk": "zmjoSq_detectOk",
1689
- "select": "zmjoSq_select",
1690
- "sectionHeader": "zmjoSq_sectionHeader",
1691
- "sectionDivider": "zmjoSq_sectionDivider",
1872
+ "modelCatalog": "zmjoSq_modelCatalog",
1692
1873
  "channelDotReady": "zmjoSq_channelDotReady",
1693
- "channelName": "zmjoSq_channelName",
1694
- "editorSectionHeader": "zmjoSq_editorSectionHeader",
1695
- "editorBackdrop": "zmjoSq_editorBackdrop",
1696
- "modelCandidateLabel": "zmjoSq_modelCandidateLabel",
1697
- "disclosure": "zmjoSq_disclosure",
1874
+ "candidateTitle": "zmjoSq_candidateTitle",
1875
+ "label": "zmjoSq_label",
1876
+ "candidatePanel": "zmjoSq_candidatePanel",
1877
+ "select": "zmjoSq_select",
1878
+ "editorFooter": "zmjoSq_editorFooter",
1879
+ "description": "zmjoSq_description",
1698
1880
  "channelMain": "zmjoSq_channelMain",
1699
- "modelSummary": "zmjoSq_modelSummary",
1700
- "modelRowRemove": "zmjoSq_modelRowRemove",
1701
- "channelDanger": "zmjoSq_channelDanger",
1702
- "deleteConfirmText": "zmjoSq_deleteConfirmText",
1703
- "editorPanel": "zmjoSq_editorPanel",
1704
- "modelCandidate": "zmjoSq_modelCandidate",
1705
- "spacer": "zmjoSq_spacer",
1706
- "name": "zmjoSq_name",
1707
- "modelRowInputs": "zmjoSq_modelRowInputs",
1708
- "badges": "zmjoSq_badges",
1709
- "headText": "zmjoSq_headText",
1710
- "modelRowBadges": "zmjoSq_modelRowBadges",
1711
- "versionLabel": "zmjoSq_versionLabel",
1712
- "optionalContent": "zmjoSq_optionalContent",
1713
1881
  "modelArrow": "zmjoSq_modelArrow",
1882
+ "channelAdd": "zmjoSq_channelAdd",
1883
+ "modelRows": "zmjoSq_modelRows",
1884
+ "candidateList": "zmjoSq_candidateList",
1885
+ "card": "zmjoSq_card",
1886
+ "candidate": "zmjoSq_candidate",
1887
+ "customSettingsSummary": "zmjoSq_customSettingsSummary",
1888
+ "customSettingsBody": "zmjoSq_customSettingsBody",
1889
+ "modelCatalogMeta": "zmjoSq_modelCatalogMeta",
1890
+ "modelCatalogTitle": "zmjoSq_modelCatalogTitle",
1891
+ "channelSection": "zmjoSq_channelSection",
1892
+ "detectOk": "zmjoSq_detectOk",
1714
1893
  "channelDotWarn": "zmjoSq_channelDotWarn",
1715
- "presetMeta": "zmjoSq_presetMeta",
1716
- "reset": "zmjoSq_reset",
1894
+ "body": "zmjoSq_body",
1895
+ "channelDanger": "zmjoSq_channelDanger",
1896
+ "linkButton": "zmjoSq_linkButton",
1897
+ "deleteConfirmText": "zmjoSq_deleteConfirmText",
1898
+ "editorHeader": "zmjoSq_editorHeader",
1899
+ "discard": "zmjoSq_discard",
1900
+ "editorTitle": "zmjoSq_editorTitle",
1901
+ "head": "zmjoSq_head",
1902
+ "channelHost": "zmjoSq_channelHost",
1717
1903
  "chevronOpen": "zmjoSq_chevronOpen",
1718
- "label": "zmjoSq_label",
1904
+ "modelRow": "zmjoSq_modelRow",
1905
+ "chevron": "zmjoSq_chevron",
1906
+ "sectionHeader": "zmjoSq_sectionHeader",
1907
+ "channelMeta": "zmjoSq_channelMeta",
1908
+ "failed": "zmjoSq_failed",
1909
+ "modelCatalogHead": "zmjoSq_modelCatalogHead",
1910
+ "header": "zmjoSq_header",
1911
+ "link": "zmjoSq_link",
1719
1912
  "field": "zmjoSq_field",
1720
- "modelFetchRow": "zmjoSq_modelFetchRow",
1721
- "modelCandidateList": "zmjoSq_modelCandidateList",
1722
- "sectionHint": "zmjoSq_sectionHint",
1913
+ "input": "zmjoSq_input",
1914
+ "editorWrap": "zmjoSq_editorWrap",
1915
+ "modelInput": "zmjoSq_modelInput",
1916
+ "channelAddRow": "zmjoSq_channelAddRow",
1917
+ "candidateActions": "zmjoSq_candidateActions",
1918
+ "channelList": "zmjoSq_channelList",
1919
+ "modelEmpty": "zmjoSq_modelEmpty",
1723
1920
  "addModel": "zmjoSq_addModel",
1921
+ "sectionTitle": "zmjoSq_sectionTitle",
1922
+ "name": "zmjoSq_name",
1923
+ "reset": "zmjoSq_reset",
1924
+ "candidateId": "zmjoSq_candidateId",
1925
+ "modelCatalogTools": "zmjoSq_modelCatalogTools",
1926
+ "headText": "zmjoSq_headText",
1927
+ "editorTag": "zmjoSq_editorTag",
1928
+ "candidateLabel": "zmjoSq_candidateLabel",
1929
+ "candidateHead": "zmjoSq_candidateHead",
1930
+ "readOnly": "zmjoSq_readOnly",
1931
+ "channelRow": "zmjoSq_channelRow",
1932
+ "modelCategorySelect": "zmjoSq_modelCategorySelect",
1933
+ "channelAction": "zmjoSq_channelAction",
1934
+ "modelRowRemove": "zmjoSq_modelRowRemove",
1935
+ "channelEmpty": "zmjoSq_channelEmpty",
1936
+ "pending": "zmjoSq_pending",
1724
1937
  "modelBadge": "zmjoSq_modelBadge",
1725
- "channelBadge": "zmjoSq_channelBadge",
1726
- "modelRows": "zmjoSq_modelRows",
1727
- "channelControls": "zmjoSq_channelControls",
1728
- "channelSection": "zmjoSq_channelSection",
1729
- "invalid": "zmjoSq_invalid"
1938
+ "channelName": "zmjoSq_channelName",
1939
+ "sectionHint": "zmjoSq_sectionHint",
1940
+ "channelEditor": "zmjoSq_channelEditor",
1941
+ "customSettings": "zmjoSq_customSettings",
1942
+ "channelBadge": "zmjoSq_channelBadge"
1730
1943
  };
1731
1944
  //#endregion
1732
1945
  //#region src/client/SettingsCard.tsx
@@ -1736,6 +1949,12 @@ window.__ModuleLoader__.load({
1736
1949
  * Registers into the official `settings.plugin.item` slot. It manages a list
1737
1950
  * of audio channels (each with API URL, per-channel secret, and model/voice
1738
1951
  * catalog), plus master switches.
1952
+ *
1953
+ * Channel management follows the DSH "模型" settings pattern: provider rows
1954
+ * with a status dot and 编辑/删除 actions, and two equal-width add actions
1955
+ * (「添加提供方」 / 「添加自定义提供方」) below. Both add and edit open the
1956
+ * same inline editor card — provider select, API key, 自定义设置 (API 地址)
1957
+ * and a 模型目录 with 「获取可用模型」 discovery and per-row model editing.
1739
1958
  */
1740
1959
  var AudioGenSettingsCardController = class {
1741
1960
  scope;
@@ -1775,110 +1994,580 @@ window.__ModuleLoader__.load({
1775
1994
  };
1776
1995
  }
1777
1996
  };
1778
- function newChannelDraft(preset, existing) {
1779
- const id = `ch-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`;
1780
- if (preset === void 0) return {
1781
- id,
1782
- preset: "",
1783
- name: "",
1784
- apiUrl: "",
1785
- models: []
1786
- };
1787
- return {
1788
- id,
1789
- preset: preset.id,
1790
- name: preset.name,
1791
- apiUrl: preset.apiUrl,
1792
- models: preset.models.map((model) => ({ ...model }))
1793
- };
1794
- }
1795
- function modelsToText(models) {
1796
- return models.map((model) => `${model.alias}=${model.id}${model.category === void 0 ? "" : ` @${model.category}`}`).join("\n");
1997
+ const MODEL_CATEGORIES = [
1998
+ void 0,
1999
+ "tts",
2000
+ "music",
2001
+ "sfx",
2002
+ "voice_design",
2003
+ "voice_clone"
2004
+ ];
2005
+ function newChannelId() {
2006
+ return `ch-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`;
1797
2007
  }
1798
- function textToModels(text) {
1799
- return text.split(/\n|,/).map((line) => line.trim()).filter(Boolean).map((line) => {
1800
- const at = line.lastIndexOf(" @");
1801
- const category = at >= 0 ? line.slice(at + 2).trim() : void 0;
1802
- const body = at >= 0 ? line.slice(0, at).trim() : line;
1803
- const eq = body.indexOf("=");
1804
- const alias = eq >= 0 ? body.slice(0, eq).trim() : body.trim();
1805
- const id = eq >= 0 ? body.slice(eq + 1).trim() : alias;
2008
+ /** Strip a draft before staging: empty rows removed, aliases default to ids. */
2009
+ function cleanModels(models) {
2010
+ const cleaned = models.map((model) => {
2011
+ const alias = model.alias.trim();
2012
+ const id = model.id.trim() === "" ? alias : model.id.trim();
2013
+ if (alias === "" && id === "") return void 0;
1806
2014
  return {
1807
- alias,
1808
- id: id === "" ? alias : id,
1809
- ...category === void 0 || category === "" ? {} : { category }
2015
+ alias: alias === "" ? id : alias,
2016
+ id,
2017
+ ...model.category === void 0 ? {} : { category: model.category }
1810
2018
  };
1811
- }).filter((model) => model.alias !== "");
2019
+ }).filter((model) => model !== void 0);
2020
+ return [...new Map(cleaned.map((model) => [model.alias, model])).values()];
1812
2021
  }
1813
- function AudioGenSettingsCard(props) {
1814
- const { t } = props;
1815
- const state = props.useAudioGenSettingsCard((snapshot) => snapshot);
1816
- const [open, setOpen] = (0, react.useState)(false);
1817
- const [editingId, setEditingId] = (0, react.useState)(null);
1818
- const [presetPickerOpen, setPresetPickerOpen] = (0, react.useState)(false);
1819
- const [presets, setPresets] = (0, react.useState)([]);
1820
- const [presetError, setPresetError] = (0, react.useState)(null);
1821
- const [confirmDeleteId, setConfirmDeleteId] = (0, react.useState)(null);
2022
+ /** Translate one key with interpolation (the injected `t` takes no values). */
2023
+ function tpl(t, key, values) {
2024
+ let text = t(key);
2025
+ if (values === void 0) return text;
2026
+ for (const [name, value] of Object.entries(values)) text = text.replaceAll(`{${name}}`, String(value));
2027
+ return text;
2028
+ }
2029
+ function rowsOf(models) {
2030
+ return models.map((model, index) => ({
2031
+ ...model,
2032
+ rowKey: `m-${index}-${model.alias}-${model.id}`
2033
+ }));
2034
+ }
2035
+ function ChannelEditor(props) {
2036
+ const { t, writable, mode, presets } = props;
2037
+ const [presetId, setPresetId] = (0, react.useState)(mode.kind === "add-provider" ? presets[0]?.id ?? "" : "");
2038
+ const invited = (0, react.useMemo)(() => mode.kind === "add-provider" ? presets.find((preset) => preset.id === presetId) : void 0, [
2039
+ mode,
2040
+ presets,
2041
+ presetId
2042
+ ]);
2043
+ const [name, setName] = (0, react.useState)(props.channel?.name ?? invited?.name ?? "");
2044
+ const [url, setUrl] = (0, react.useState)(props.channel?.apiUrl ?? invited?.apiUrl ?? "");
2045
+ const [models, setModels] = (0, react.useState)(rowsOf(props.channel?.models ?? invited?.models ?? []));
2046
+ const [key, setKey] = (0, react.useState)("");
2047
+ const [keyAction, setKeyAction] = (0, react.useState)("none");
2048
+ const [isDefault, setIsDefault] = (0, react.useState)(props.initiallyDefault);
1822
2049
  const [discovering, setDiscovering] = (0, react.useState)(false);
1823
2050
  const [discoverError, setDiscoverError] = (0, react.useState)(null);
1824
- const [editName, setEditName] = (0, react.useState)("");
1825
- const [editUrl, setEditUrl] = (0, react.useState)("");
1826
- const [editKey, setEditKey] = (0, react.useState)("");
1827
- const [editModels, setEditModels] = (0, react.useState)("");
1828
- const [editDefault, setEditDefault] = (0, react.useState)(false);
1829
- const channels = state.channels.channels;
1830
- const editing = editingId === null ? void 0 : channels.find((channel) => channel.id === editingId);
1831
- (0, react.useEffect)(() => {
1832
- if (editing === void 0) return;
1833
- setEditName(editing.name);
1834
- setEditUrl(editing.apiUrl);
1835
- setEditKey("");
1836
- setEditModels(modelsToText(editing.models));
1837
- setEditDefault(editing.id === state.channels.defaultChannelId);
1838
- }, [editingId, editing?.id]);
1839
- if (!state.available) return null;
1840
- const blocked = !state.dirty || state.invalid || state.saving || state.channels.saving;
1841
- const saveEdit = () => {
1842
- if (editingId === null) return;
1843
- const existing = channels.find((channel) => channel.id === editingId);
1844
- const models = textToModels(editModels);
1845
- const updated = {
1846
- id: editingId,
1847
- preset: existing?.preset ?? "",
1848
- name: editName.trim(),
1849
- apiUrl: editUrl.trim(),
1850
- models
2051
+ const [candidates, setCandidates] = (0, react.useState)(null);
2052
+ const [picked, setPicked] = (0, react.useState)(/* @__PURE__ */ new Set());
2053
+ const [sourceNote, setSourceNote] = (0, react.useState)(null);
2054
+ const usePreset = (preset) => {
2055
+ setPresetId(preset?.id ?? "");
2056
+ setName(preset?.name ?? "");
2057
+ setUrl(preset?.apiUrl ?? "");
2058
+ setModels(rowsOf(preset?.models ?? []));
2059
+ setKey("");
2060
+ setKeyAction("none");
2061
+ };
2062
+ const effectiveKeyHeld = props.keyHeld && keyAction !== "clear";
2063
+ const save = () => {
2064
+ const channel = {
2065
+ id: props.channel?.id ?? newChannelId(),
2066
+ preset: mode.kind === "edit" ? props.channel?.preset ?? "" : mode.kind === "add-custom" ? "" : invited?.id ?? "",
2067
+ name: name.trim(),
2068
+ apiUrl: url.trim(),
2069
+ models: cleanModels(models)
1851
2070
  };
1852
- const next = existing === void 0 ? [...channels, updated] : channels.map((channel) => channel.id === editingId ? updated : channel);
1853
- props.channels.setChannels(next);
1854
- if (editKey.trim() !== "") props.channels.setChannelKey(editingId, editKey.trim());
1855
- if (editDefault) props.channels.setDefaultChannel(editingId);
1856
- setEditingId(null);
2071
+ const stagedKey = key.trim() !== "" ? key.trim() : keyAction === "clear" ? "" : void 0;
2072
+ props.onSave(channel, stagedKey, isDefault);
1857
2073
  };
1858
- const discoverModels = async () => {
1859
- if (editingId === null) return;
2074
+ const discoverable = url.trim() !== "" && (key.trim() !== "" || effectiveKeyHeld);
2075
+ const discover = async () => {
2076
+ if (!discoverable) return;
1860
2077
  setDiscovering(true);
1861
2078
  setDiscoverError(null);
2079
+ setSourceNote(null);
1862
2080
  try {
1863
- channels.find((channel) => channel.id === editingId);
1864
2081
  const response = await fetch(MODEL_API.discover, {
1865
2082
  method: "POST",
1866
2083
  headers: { "content-type": "application/json" },
1867
2084
  body: JSON.stringify({
1868
- channelId: editingId,
1869
- ...editUrl.trim() !== "" ? { apiUrl: editUrl.trim() } : {},
1870
- ...editKey.trim() !== "" ? { apiKey: editKey.trim() } : {}
2085
+ channelId: props.channel?.id ?? "preview",
2086
+ preset: mode.kind === "add-provider" ? invited?.id ?? "" : props.channel?.preset ?? "",
2087
+ apiUrl: url.trim(),
2088
+ ...key.trim() !== "" ? { apiKey: key.trim() } : {}
1871
2089
  })
1872
2090
  });
1873
2091
  const body = await response.json();
1874
2092
  if (body.ok !== true || body.models === void 0) throw new Error(body.message ?? `HTTP ${response.status}`);
1875
- setEditModels(modelsToText([...body.models, ...textToModels(editModels).filter((existingModel) => !body.models.some((model) => model.id === existingModel.id))]));
2093
+ const known = new Set(models.map((model) => model.id.trim()).filter(Boolean));
2094
+ const found = body.models.map((model) => ({
2095
+ ...model,
2096
+ id: model.id.trim()
2097
+ })).filter((model) => model.id !== "");
2098
+ if (found.length === 0) {
2099
+ setDiscoverError(t("channel.fetchEmpty"));
2100
+ return;
2101
+ }
2102
+ setCandidates(found);
2103
+ setPicked(new Set(found.filter((model) => !known.has(model.id)).map((model) => model.id)));
2104
+ setSourceNote(body.source ?? null);
1876
2105
  } catch (error) {
1877
2106
  setDiscoverError(error instanceof Error ? error.message : String(error));
1878
2107
  } finally {
1879
2108
  setDiscovering(false);
1880
2109
  }
1881
2110
  };
2111
+ const closeCandidates = () => {
2112
+ setCandidates(null);
2113
+ setPicked(/* @__PURE__ */ new Set());
2114
+ };
2115
+ const adoptCandidates = () => {
2116
+ if (candidates === null) return;
2117
+ const existing = [...models];
2118
+ const byId = new Map(existing.map((model, index) => [model.id.trim(), {
2119
+ model,
2120
+ index
2121
+ }]));
2122
+ for (const candidate of candidates) {
2123
+ const id = candidate.id.trim();
2124
+ if (id === "" || !picked.has(id)) continue;
2125
+ if (byId.has(id)) continue;
2126
+ byId.set(id, {
2127
+ model: {
2128
+ rowKey: `m-${Date.now()}-${existing.length}`,
2129
+ alias: candidate.alias,
2130
+ id,
2131
+ ...candidate.category === void 0 ? {} : { category: candidate.category }
2132
+ },
2133
+ index: existing.length
2134
+ });
2135
+ existing.push(byId.get(id).model);
2136
+ }
2137
+ setModels(existing);
2138
+ closeCandidates();
2139
+ };
2140
+ const patchModel = (index, next) => {
2141
+ setModels(models.map((model, at) => at === index ? {
2142
+ ...model,
2143
+ ...next
2144
+ } : model));
2145
+ };
2146
+ const presetPlaceholder = invited?.apiUrl ?? t("channel.apiUrlPlaceholder");
2147
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2148
+ className: settings_card_module_css_default.channelEditor,
2149
+ children: [
2150
+ mode.kind === "add-provider" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2151
+ className: settings_card_module_css_default.field,
2152
+ children: [
2153
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
2154
+ className: settings_card_module_css_default.label,
2155
+ htmlFor: "audiogen-editor-provider",
2156
+ children: t("channel.provider")
2157
+ }),
2158
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
2159
+ id: "audiogen-editor-provider",
2160
+ className: settings_card_module_css_default.select,
2161
+ value: presetId,
2162
+ disabled: !writable,
2163
+ onChange: (event) => usePreset(presets.find((preset) => preset.id === event.target.value)),
2164
+ children: presets.map((preset) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
2165
+ value: preset.id,
2166
+ children: preset.name
2167
+ }, preset.id))
2168
+ }),
2169
+ invited?.site !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
2170
+ className: settings_card_module_css_default.sectionHint,
2171
+ children: [
2172
+ t("channel.site"),
2173
+ ":",
2174
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
2175
+ className: settings_card_module_css_default.link,
2176
+ href: invited.site,
2177
+ target: "_blank",
2178
+ rel: "noreferrer",
2179
+ children: invited.site
2180
+ })
2181
+ ]
2182
+ }) : null
2183
+ ]
2184
+ }) : null,
2185
+ mode.kind === "add-custom" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2186
+ className: settings_card_module_css_default.field,
2187
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2188
+ className: settings_card_module_css_default.label,
2189
+ children: t("channel.provider")
2190
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
2191
+ className: settings_card_module_css_default.sectionHint,
2192
+ children: [
2193
+ t("channel.providerCustom"),
2194
+ " — ",
2195
+ t("channel.providerCustomHint")
2196
+ ]
2197
+ })]
2198
+ }) : null,
2199
+ mode.kind === "edit" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2200
+ className: settings_card_module_css_default.editorHeader,
2201
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2202
+ className: settings_card_module_css_default.editorTitle,
2203
+ children: props.channel?.name.trim() !== "" ? props.channel?.name : t("channels.untitled")
2204
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2205
+ className: settings_card_module_css_default.editorTag,
2206
+ children: mode.kind === "edit" ? t("channel.editTitle") : ""
2207
+ })]
2208
+ }) : null,
2209
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2210
+ className: settings_card_module_css_default.field,
2211
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
2212
+ className: settings_card_module_css_default.label,
2213
+ htmlFor: "audiogen-editor-name",
2214
+ children: t("channel.name")
2215
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
2216
+ id: "audiogen-editor-name",
2217
+ className: settings_card_module_css_default.input,
2218
+ value: name,
2219
+ placeholder: t("channel.namePlaceholder"),
2220
+ disabled: !writable,
2221
+ onChange: (event) => setName(event.target.value)
2222
+ })]
2223
+ }),
2224
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2225
+ className: settings_card_module_css_default.field,
2226
+ children: [
2227
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2228
+ className: settings_card_module_css_default.head,
2229
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
2230
+ className: settings_card_module_css_default.label,
2231
+ htmlFor: "audiogen-editor-key",
2232
+ children: t("channel.apiKey")
2233
+ }), effectiveKeyHeld && key.trim() === "" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2234
+ type: "button",
2235
+ className: settings_card_module_css_default.reset,
2236
+ disabled: !writable,
2237
+ onClick: () => {
2238
+ setKeyAction("clear");
2239
+ setKey("");
2240
+ },
2241
+ children: t("channel.clearKey")
2242
+ }) : null]
2243
+ }),
2244
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
2245
+ id: "audiogen-editor-key",
2246
+ className: settings_card_module_css_default.input,
2247
+ type: "password",
2248
+ value: key,
2249
+ autoComplete: "off",
2250
+ placeholder: effectiveKeyHeld ? "••••••••" : "",
2251
+ disabled: !writable,
2252
+ onChange: (event) => {
2253
+ setKey(event.target.value);
2254
+ if (event.target.value !== "") setKeyAction("none");
2255
+ }
2256
+ }),
2257
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2258
+ className: settings_card_module_css_default.sectionHint,
2259
+ children: effectiveKeyHeld ? t("channel.apiKeyStoredHint") : t("channel.apiKeyHint")
2260
+ })
2261
+ ]
2262
+ }),
2263
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
2264
+ className: settings_card_module_css_default.customSettings,
2265
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("summary", {
2266
+ className: settings_card_module_css_default.customSettingsSummary,
2267
+ children: t("channel.customSettings")
2268
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2269
+ className: settings_card_module_css_default.customSettingsBody,
2270
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2271
+ className: settings_card_module_css_default.field,
2272
+ children: [
2273
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
2274
+ className: settings_card_module_css_default.label,
2275
+ htmlFor: "audiogen-editor-url",
2276
+ children: t("channel.apiUrl")
2277
+ }),
2278
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
2279
+ id: "audiogen-editor-url",
2280
+ className: settings_card_module_css_default.input,
2281
+ type: "text",
2282
+ value: url,
2283
+ placeholder: presetPlaceholder,
2284
+ disabled: !writable,
2285
+ onChange: (event) => setUrl(event.target.value)
2286
+ }),
2287
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2288
+ className: settings_card_module_css_default.sectionHint,
2289
+ children: t("channel.apiUrlHint")
2290
+ })
2291
+ ]
2292
+ })
2293
+ })]
2294
+ }),
2295
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModelCatalog, {
2296
+ t,
2297
+ writable,
2298
+ models,
2299
+ discoverable,
2300
+ discovering,
2301
+ discoverError,
2302
+ candidates,
2303
+ picked,
2304
+ sourceNote,
2305
+ onPatchModel: patchModel,
2306
+ onRemoveModel: (index) => setModels(models.filter((_model, at) => at !== index)),
2307
+ onAddModel: () => setModels([...models, {
2308
+ rowKey: `m-${Date.now()}-${models.length}`,
2309
+ alias: "",
2310
+ id: ""
2311
+ }]),
2312
+ onDiscover: () => void discover(),
2313
+ onTogglePicked: (id) => {
2314
+ setPicked((current) => {
2315
+ const next = new Set(current);
2316
+ if (!next.delete(id)) next.add(id);
2317
+ return next;
2318
+ });
2319
+ },
2320
+ onToggleAllPicked: () => {
2321
+ setPicked((current) => candidates !== null && candidates.length > 0 && candidates.every((candidate) => current.has(candidate.id)) ? /* @__PURE__ */ new Set() : new Set((candidates ?? []).map((candidate) => candidate.id)));
2322
+ },
2323
+ onAdopt: () => adoptCandidates(),
2324
+ onCloseCandidates: closeCandidates
2325
+ }),
2326
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
2327
+ className: settings_card_module_css_default.field,
2328
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2329
+ className: settings_card_module_css_default.label,
2330
+ children: [
2331
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
2332
+ type: "checkbox",
2333
+ checked: isDefault,
2334
+ disabled: !writable,
2335
+ onChange: (event) => setIsDefault(event.target.checked)
2336
+ }),
2337
+ " ",
2338
+ t("channel.default")
2339
+ ]
2340
+ })
2341
+ }),
2342
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2343
+ className: settings_card_module_css_default.editorFooter,
2344
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2345
+ type: "button",
2346
+ className: settings_card_module_css_default.discard,
2347
+ onClick: props.onCancel,
2348
+ children: t("channel.cancel")
2349
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2350
+ type: "button",
2351
+ className: settings_card_module_css_default.save,
2352
+ onClick: save,
2353
+ children: t("channel.save")
2354
+ })]
2355
+ })
2356
+ ]
2357
+ });
2358
+ }
2359
+ function ModelCatalog(props) {
2360
+ const { t, writable, models, discoverable, discovering, candidates, picked } = props;
2361
+ const allPicked = candidates !== null && candidates.length > 0 && candidates.every((candidate) => picked.has(candidate.id));
2362
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
2363
+ className: settings_card_module_css_default.modelCatalog,
2364
+ "aria-label": t("channel.modelsTitle"),
2365
+ children: [
2366
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2367
+ className: settings_card_module_css_default.modelCatalogHead,
2368
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2369
+ className: settings_card_module_css_default.modelCatalogTitle,
2370
+ children: t("channel.modelsTitle")
2371
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2372
+ className: settings_card_module_css_default.modelCatalogMeta,
2373
+ children: models.length > 0 ? tpl(t, "channel.modelsCount", { n: models.length }) : t("channel.modelsNone")
2374
+ })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2375
+ type: "button",
2376
+ className: settings_card_module_css_default.linkButton,
2377
+ disabled: !writable || discovering || !discoverable,
2378
+ title: discoverable ? void 0 : t("channel.discoverNeedsUrlKey"),
2379
+ onClick: props.onDiscover,
2380
+ children: discovering ? t("channel.fetchingModels") : t("channel.fetchModels")
2381
+ })]
2382
+ }),
2383
+ models.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2384
+ className: settings_card_module_css_default.modelEmpty,
2385
+ children: t("channel.modelsEmpty")
2386
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
2387
+ className: settings_card_module_css_default.modelRows,
2388
+ children: models.map((model, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
2389
+ className: settings_card_module_css_default.modelRow,
2390
+ children: [
2391
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
2392
+ className: `${settings_card_module_css_default.input} ${settings_card_module_css_default.modelInput}`,
2393
+ type: "text",
2394
+ value: model.alias,
2395
+ placeholder: t("channel.modelAlias"),
2396
+ "aria-label": `${t("channel.modelAlias")} ${index + 1}`,
2397
+ disabled: !writable,
2398
+ onChange: (event) => props.onPatchModel(index, { alias: event.target.value })
2399
+ }),
2400
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2401
+ className: settings_card_module_css_default.modelArrow,
2402
+ "aria-hidden": "true",
2403
+ children: "→"
2404
+ }),
2405
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
2406
+ className: `${settings_card_module_css_default.input} ${settings_card_module_css_default.modelInput}`,
2407
+ type: "text",
2408
+ value: model.id,
2409
+ placeholder: t("channel.modelId"),
2410
+ "aria-label": `${t("channel.modelId")} ${index + 1}`,
2411
+ disabled: !writable,
2412
+ onChange: (event) => props.onPatchModel(index, { id: event.target.value })
2413
+ }),
2414
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
2415
+ className: `${settings_card_module_css_default.select} ${settings_card_module_css_default.modelCategorySelect}`,
2416
+ value: model.category ?? "",
2417
+ "aria-label": `${t("channel.modelCategory")} ${index + 1}`,
2418
+ disabled: !writable,
2419
+ onChange: (event) => {
2420
+ const value = event.target.value;
2421
+ props.onPatchModel(index, value === "" ? { category: void 0 } : { category: value });
2422
+ },
2423
+ children: MODEL_CATEGORIES.map((category) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
2424
+ value: category ?? "",
2425
+ children: category === void 0 ? t("channel.category.auto") : t(`channel.category.${category}`)
2426
+ }, category ?? "auto"))
2427
+ }),
2428
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2429
+ type: "button",
2430
+ className: settings_card_module_css_default.modelRowRemove,
2431
+ "aria-label": t("channel.removeModel"),
2432
+ disabled: !writable,
2433
+ onClick: () => props.onRemoveModel(index),
2434
+ children: "×"
2435
+ })
2436
+ ]
2437
+ }, `${model.rowKey}-${index}`))
2438
+ }),
2439
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2440
+ className: settings_card_module_css_default.modelCatalogTools,
2441
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2442
+ type: "button",
2443
+ className: settings_card_module_css_default.addModel,
2444
+ disabled: !writable,
2445
+ onClick: props.onAddModel,
2446
+ children: t("channel.addModel")
2447
+ })
2448
+ }),
2449
+ props.sourceNote !== null && props.candidates !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2450
+ className: settings_card_module_css_default.detectOk,
2451
+ children: tpl(t, "channel.discoverSource", { source: props.sourceNote })
2452
+ }) : null,
2453
+ props.discoverError !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2454
+ className: settings_card_module_css_default.failed,
2455
+ children: props.discoverError
2456
+ }) : null,
2457
+ candidates === null ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2458
+ className: settings_card_module_css_default.candidatePanel,
2459
+ children: [
2460
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2461
+ className: settings_card_module_css_default.candidateHead,
2462
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2463
+ className: settings_card_module_css_default.candidateTitle,
2464
+ children: tpl(t, "channel.candidates", { n: candidates.length })
2465
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2466
+ type: "button",
2467
+ className: settings_card_module_css_default.linkButton,
2468
+ onClick: props.onToggleAllPicked,
2469
+ children: allPicked ? t("channel.clearSelection") : t("channel.selectAll")
2470
+ })]
2471
+ }),
2472
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
2473
+ className: settings_card_module_css_default.candidateList,
2474
+ children: candidates.map((candidate) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", {
2475
+ className: settings_card_module_css_default.candidate,
2476
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
2477
+ className: settings_card_module_css_default.candidateLabel,
2478
+ children: [
2479
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
2480
+ type: "checkbox",
2481
+ checked: picked.has(candidate.id),
2482
+ disabled: models.some((model) => model.id.trim() === candidate.id),
2483
+ onChange: () => props.onTogglePicked(candidate.id)
2484
+ }),
2485
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2486
+ className: settings_card_module_css_default.candidateId,
2487
+ children: candidate.alias === candidate.id ? candidate.id : `${candidate.alias}(${candidate.id})`
2488
+ }),
2489
+ candidate.category !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2490
+ className: settings_card_module_css_default.modelBadge,
2491
+ children: t(`channel.category.${candidate.category}`)
2492
+ }) : null
2493
+ ]
2494
+ })
2495
+ }, candidate.id))
2496
+ }),
2497
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2498
+ className: settings_card_module_css_default.candidateActions,
2499
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2500
+ type: "button",
2501
+ className: settings_card_module_css_default.discard,
2502
+ onClick: props.onCloseCandidates,
2503
+ children: t("channel.cancel")
2504
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2505
+ type: "button",
2506
+ className: settings_card_module_css_default.save,
2507
+ onClick: props.onAdopt,
2508
+ children: tpl(t, "channel.adoptSelected", { n: Array.from(picked).length })
2509
+ })]
2510
+ })
2511
+ ]
2512
+ })
2513
+ ]
2514
+ });
2515
+ }
2516
+ function AudioGenSettingsCard(props) {
2517
+ const { t } = props;
2518
+ const state = props.useAudioGenSettingsCard((snapshot) => snapshot);
2519
+ const [open, setOpen] = (0, react.useState)(false);
2520
+ const [editor, setEditor] = (0, react.useState)(null);
2521
+ const [presets, setPresets] = (0, react.useState)([]);
2522
+ const [presetLoading, setPresetLoading] = (0, react.useState)(false);
2523
+ const [presetError, setPresetError] = (0, react.useState)(null);
2524
+ const [confirmDeleteId, setConfirmDeleteId] = (0, react.useState)(null);
2525
+ const channels = state.channels.channels;
2526
+ const editingChannel = editor !== null && editor.kind === "edit" ? channels.find((channel) => channel.id === editor.channelId) : void 0;
2527
+ (0, react.useEffect)(() => {
2528
+ if (editor?.kind === "add-provider" && presets.length === 0 && presetError === null && !presetLoading) {
2529
+ setPresetLoading(true);
2530
+ setPresetError(null);
2531
+ fetch(PRESETS_API, { method: "POST" }).then(async (response) => {
2532
+ const body = await response.json();
2533
+ if (!response.ok || body.ok !== true || body.presets === void 0) throw new Error(body.message ?? `HTTP ${response.status}`);
2534
+ setPresets(body.presets);
2535
+ }).catch((error) => setPresetError(error instanceof Error ? error.message : String(error))).finally(() => setPresetLoading(false));
2536
+ }
2537
+ }, [
2538
+ editor,
2539
+ presets.length,
2540
+ presetError,
2541
+ presetLoading
2542
+ ]);
2543
+ if (!state.available) return null;
2544
+ const blocked = !state.dirty || state.invalid || state.saving || state.channels.saving;
2545
+ const closeEditor = () => {
2546
+ setEditor(null);
2547
+ };
2548
+ const saveEditor = (channel, key, isDefault) => {
2549
+ const next = channels.some((candidate) => candidate.id === channel.id) ? channels.map((candidate) => candidate.id === channel.id ? channel : candidate) : [...channels, channel];
2550
+ props.channels.setChannels(next);
2551
+ if (key !== void 0) props.channels.setChannelKey(channel.id, key);
2552
+ if (isDefault) props.channels.setDefaultChannel(channel.id);
2553
+ closeEditor();
2554
+ };
2555
+ const removeChannel = (channel) => {
2556
+ const isDefault = channel.id === state.channels.defaultChannelId;
2557
+ const next = channels.filter((candidate) => candidate.id !== channel.id);
2558
+ props.channels.setChannels(next);
2559
+ if (isDefault && next.length > 0) props.channels.setDefaultChannel(next[0].id);
2560
+ setConfirmDeleteId(null);
2561
+ if (editor?.kind === "edit" && editor.channelId === channel.id) closeEditor();
2562
+ };
2563
+ const openAddProvider = () => {
2564
+ setPresetError(null);
2565
+ setEditor({ kind: "add-provider" });
2566
+ };
2567
+ const openAddCustom = () => {
2568
+ setPresetError(null);
2569
+ setEditor({ kind: "add-custom" });
2570
+ };
1882
2571
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
1883
2572
  className: settings_card_module_css_default.card,
1884
2573
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
@@ -1956,15 +2645,7 @@ window.__ModuleLoader__.load({
1956
2645
  type: "button",
1957
2646
  className: settings_card_module_css_default.channelDanger,
1958
2647
  disabled: !state.writable,
1959
- onClick: () => {
1960
- props.channels.setChannels(channels.filter((candidate) => candidate.id !== channel.id));
1961
- if (isDefault && channels.length > 1) {
1962
- const next = channels.find((candidate) => candidate.id !== channel.id);
1963
- if (next !== void 0) props.channels.setDefaultChannel(next.id);
1964
- }
1965
- setConfirmDeleteId(null);
1966
- if (editingId === channel.id) setEditingId(null);
1967
- },
2648
+ onClick: () => removeChannel(channel),
1968
2649
  children: t("channels.confirm")
1969
2650
  }),
1970
2651
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
@@ -1987,7 +2668,12 @@ window.__ModuleLoader__.load({
1987
2668
  type: "button",
1988
2669
  className: settings_card_module_css_default.channelMain,
1989
2670
  disabled: !state.writable,
1990
- onClick: () => setEditingId(channel.id),
2671
+ onClick: () => {
2672
+ setEditor({
2673
+ kind: "edit",
2674
+ channelId: channel.id
2675
+ });
2676
+ },
1991
2677
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1992
2678
  className: settings_card_module_css_default.channelName,
1993
2679
  children: isDefault ? `★ ${channel.name || t("channels.untitled")}` : channel.name || t("channels.untitled")
@@ -2010,7 +2696,12 @@ window.__ModuleLoader__.load({
2010
2696
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2011
2697
  type: "button",
2012
2698
  className: settings_card_module_css_default.channelAction,
2013
- onClick: () => setEditingId(channel.id),
2699
+ onClick: () => {
2700
+ setEditor({
2701
+ kind: "edit",
2702
+ channelId: channel.id
2703
+ });
2704
+ },
2014
2705
  children: t("channels.edit")
2015
2706
  }),
2016
2707
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
@@ -2024,208 +2715,45 @@ window.__ModuleLoader__.load({
2024
2715
  }, channel.id);
2025
2716
  })
2026
2717
  }),
2027
- presetPickerOpen ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2028
- className: settings_card_module_css_default.channelControls,
2029
- children: [
2030
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2031
- className: settings_card_module_css_default.sectionHint,
2032
- children: t("presets.title")
2033
- }),
2034
- presetError !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2035
- className: settings_card_module_css_default.failed,
2036
- children: presetError
2037
- }) : null,
2038
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2039
- className: settings_card_module_css_default.channelAddRow,
2040
- children: [
2041
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2042
- type: "button",
2043
- className: settings_card_module_css_default.channelAdd,
2044
- onClick: () => {
2045
- setPresets([]);
2046
- setPresetError(null);
2047
- fetch(PRESETS_API, { method: "POST" }).then(async (response) => {
2048
- const body = await response.json();
2049
- if (!response.ok || body.ok !== true || body.presets === void 0) throw new Error(body.message ?? `HTTP ${response.status}`);
2050
- setPresets(body.presets);
2051
- }).catch((error) => setPresetError(error instanceof Error ? error.message : String(error)));
2052
- },
2053
- children: t("channels.addProvider")
2054
- }),
2055
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2056
- type: "button",
2057
- className: settings_card_module_css_default.channelAdd,
2058
- onClick: () => {
2059
- const draft = newChannelDraft(void 0, channels);
2060
- props.channels.setChannels([...channels, draft]);
2061
- setPresetPickerOpen(false);
2062
- setEditingId(draft.id);
2063
- },
2064
- children: t("channels.addCustom")
2065
- }),
2066
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2067
- type: "button",
2068
- className: settings_card_module_css_default.channelAction,
2069
- onClick: () => setPresetPickerOpen(false),
2070
- children: "×"
2071
- })
2072
- ]
2073
- }),
2074
- presets.map((preset) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
2075
- type: "button",
2076
- className: settings_card_module_css_default.channelAdd,
2077
- onClick: () => {
2078
- const draft = newChannelDraft(preset, channels);
2079
- props.channels.setChannels([...channels, draft]);
2080
- setPresetPickerOpen(false);
2081
- setEditingId(draft.id);
2082
- },
2083
- children: [
2084
- preset.name,
2085
- " — ",
2086
- preset.hint
2087
- ]
2088
- }, preset.id))
2089
- ]
2090
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2718
+ presetError !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2719
+ className: settings_card_module_css_default.failed,
2720
+ children: presetError
2721
+ }) : null,
2722
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2091
2723
  className: settings_card_module_css_default.channelAddRow,
2092
2724
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2093
2725
  type: "button",
2094
2726
  className: settings_card_module_css_default.channelAdd,
2095
2727
  disabled: !state.writable,
2096
- onClick: () => {
2097
- setPresetError(null);
2098
- setPresetPickerOpen(true);
2099
- },
2100
- children: t("channels.addProvider")
2728
+ onClick: openAddProvider,
2729
+ children: presetLoading ? t("channels.addProviderLoading") : t("channels.addProvider")
2101
2730
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2102
2731
  type: "button",
2103
2732
  className: settings_card_module_css_default.channelAdd,
2104
2733
  disabled: !state.writable,
2105
- onClick: () => {
2106
- const draft = newChannelDraft(void 0, channels);
2107
- props.channels.setChannels([...channels, draft]);
2108
- setEditingId(draft.id);
2109
- },
2734
+ onClick: openAddCustom,
2110
2735
  children: t("channels.addCustom")
2111
2736
  })]
2112
- })
2113
- ]
2114
- }),
2115
- editing !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2116
- className: settings_card_module_css_default.body,
2117
- children: [
2118
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2119
- className: settings_card_module_css_default.field,
2120
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
2121
- className: settings_card_module_css_default.label,
2122
- htmlFor: `audiogen-name-${editing.id}`,
2123
- children: t("channel.name")
2124
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
2125
- id: `audiogen-name-${editing.id}`,
2126
- className: settings_card_module_css_default.input,
2127
- value: editName,
2128
- onChange: (event) => setEditName(event.target.value)
2129
- })]
2130
- }),
2131
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2132
- className: settings_card_module_css_default.field,
2133
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
2134
- className: settings_card_module_css_default.label,
2135
- htmlFor: `audiogen-url-${editing.id}`,
2136
- children: t("channel.apiUrl")
2137
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
2138
- id: `audiogen-url-${editing.id}`,
2139
- className: settings_card_module_css_default.input,
2140
- value: editUrl,
2141
- onChange: (event) => setEditUrl(event.target.value),
2142
- placeholder: "https://…"
2143
- })]
2144
- }),
2145
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2146
- className: settings_card_module_css_default.field,
2147
- children: [
2148
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
2149
- className: settings_card_module_css_default.label,
2150
- htmlFor: `audiogen-key-${editing.id}`,
2151
- children: t("channel.apiKey")
2152
- }),
2153
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
2154
- id: `audiogen-key-${editing.id}`,
2155
- className: settings_card_module_css_default.input,
2156
- type: "password",
2157
- value: editKey,
2158
- onChange: (event) => setEditKey(event.target.value),
2159
- placeholder: state.channels.keySet[editing.id] ? "••••••" : ""
2160
- }),
2161
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2162
- className: settings_card_module_css_default.sectionHint,
2163
- children: t("channel.apiKeyHint")
2164
- })
2165
- ]
2166
- }),
2167
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2168
- className: settings_card_module_css_default.field,
2169
- children: [
2170
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
2171
- className: settings_card_module_css_default.label,
2172
- htmlFor: `audiogen-models-${editing.id}`,
2173
- children: t("channel.models")
2174
- }),
2175
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
2176
- id: `audiogen-models-${editing.id}`,
2177
- className: settings_card_module_css_default.textarea,
2178
- value: editModels,
2179
- onChange: (event) => setEditModels(event.target.value)
2180
- }),
2181
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2182
- className: settings_card_module_css_default.sectionHint,
2183
- children: t("channel.modelsHint")
2184
- }),
2185
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2186
- className: settings_card_module_css_default.channelAddRow,
2187
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2188
- type: "button",
2189
- className: settings_card_module_css_default.channelAdd,
2190
- disabled: discovering || !state.writable,
2191
- onClick: () => void discoverModels(),
2192
- children: discovering ? "获取中…" : "获取可用模型"
2193
- })
2194
- }),
2195
- discoverError !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2196
- className: settings_card_module_css_default.failed,
2197
- children: discoverError
2198
- }) : null
2199
- ]
2200
- }),
2201
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
2202
- className: settings_card_module_css_default.label,
2203
- children: [
2204
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
2205
- type: "checkbox",
2206
- checked: editDefault,
2207
- onChange: (event) => setEditDefault(event.target.checked)
2208
- }),
2209
- " ",
2210
- t("channel.default")
2211
- ]
2212
2737
  }),
2213
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2214
- className: settings_card_module_css_default.footer,
2215
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2216
- type: "button",
2217
- className: settings_card_module_css_default.discard,
2218
- onClick: () => setEditingId(null),
2219
- children: t("channel.cancel")
2220
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2221
- type: "button",
2222
- className: settings_card_module_css_default.save,
2223
- onClick: saveEdit,
2224
- children: t("channel.save")
2225
- })]
2226
- })
2738
+ editor !== null ? editor.kind === "add-provider" && presets.length === 0 && presetError === null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2739
+ className: settings_card_module_css_default.sectionHint,
2740
+ children: presetLoading ? t("channels.addProviderLoading") : t("channels.addProviderFailed")
2741
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2742
+ className: settings_card_module_css_default.editorWrap,
2743
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChannelEditor, {
2744
+ t,
2745
+ writable: state.writable,
2746
+ mode: editor,
2747
+ channel: editingChannel,
2748
+ keyHeld: editor.kind === "edit" ? state.channels.keySet[editor.channelId] === true : false,
2749
+ presets,
2750
+ initiallyDefault: editor.kind === "edit" ? editor.channelId === state.channels.defaultChannelId : channels.length === 0,
2751
+ onCancel: closeEditor,
2752
+ onSave: saveEditor
2753
+ }, editor.kind === "edit" ? `edit-${editor.channelId}` : editor.kind)
2754
+ }) : null
2227
2755
  ]
2228
- }) : null,
2756
+ }),
2229
2757
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2230
2758
  className: settings_card_module_css_default.field,
2231
2759
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
@@ -2316,17 +2844,17 @@ window.__ModuleLoader__.load({
2316
2844
  document.head.appendChild(tag);
2317
2845
  }
2318
2846
  var audio_toolview_module_css_default = {
2319
- "empty": "_7K1QKa_empty",
2320
- "root": "_7K1QKa_root",
2321
2847
  "message": "_7K1QKa_message",
2322
- "audio": "_7K1QKa_audio",
2323
- "audios": "_7K1QKa_audios",
2324
2848
  "status": "_7K1QKa_status",
2325
2849
  "audioRow": "_7K1QKa_audioRow",
2326
- "download": "_7K1QKa_download",
2850
+ "empty": "_7K1QKa_empty",
2851
+ "error": "_7K1QKa_error",
2852
+ "audio": "_7K1QKa_audio",
2327
2853
  "icon": "_7K1QKa_icon",
2328
- "header": "_7K1QKa_header",
2329
- "error": "_7K1QKa_error"
2854
+ "download": "_7K1QKa_download",
2855
+ "root": "_7K1QKa_root",
2856
+ "audios": "_7K1QKa_audios",
2857
+ "header": "_7K1QKa_header"
2330
2858
  };
2331
2859
  //#endregion
2332
2860
  //#region src/client/audio-toolview.tsx