dsh-audiogen 0.3.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
@@ -125,8 +125,10 @@ window.__ModuleLoader__.load({
125
125
  "channels.title": "音频渠道",
126
126
  "channels.hint": "每个渠道是一个独立的音频厂商/API 端点,可配置多个。",
127
127
  "channels.empty": "还没有渠道。",
128
- "channels.addProvider": "+ 添加预置厂商",
129
- "channels.addCustom": "+ 添加自定义渠道",
128
+ "channels.addProvider": "+ 添加提供方",
129
+ "channels.addProviderLoading": "加载提供方…",
130
+ "channels.addProviderFailed": "提供方目录加载失败,请点击重试。",
131
+ "channels.addCustom": "+ 添加自定义提供方",
130
132
  "channels.edit": "编辑",
131
133
  "channels.delete": "删除",
132
134
  "channels.confirm": "确认删除",
@@ -138,17 +140,49 @@ window.__ModuleLoader__.load({
138
140
  "channels.statusReady": "可用",
139
141
  "channels.statusIncomplete": "未完成",
140
142
  "channels.untitled": "未命名渠道",
143
+ "channel.title": "渠道设置",
144
+ "channel.editTitle": "编辑渠道",
145
+ "channel.provider": "提供方",
146
+ "channel.providerCustom": "自定义渠道",
147
+ "channel.providerCustomHint": "任意 OpenAI 兼容 TTS 或通用音频 POST 接口",
148
+ "channel.site": "官网",
141
149
  "channel.name": "名称",
150
+ "channel.namePlaceholder": "渠道名称(如:MiniMax 主渠道)",
142
151
  "channel.apiUrl": "API 地址",
152
+ "channel.apiUrlPlaceholder": "提供方默认地址",
153
+ "channel.apiUrlHint": "留空使用提供方默认地址。",
143
154
  "channel.apiKey": "API 密钥",
144
- "channel.apiKeyHint": "留空则保持当前密钥;输入新值可更换。",
145
- "channel.models": "模型 / 音色(每行一个:别名=上游ID)",
146
- "channel.modelsHint": "每行格式:别名=上游ID,可加 @分类(tts/music/sfx/voice_design/voice_clone);例如 tts-1=tts-1 @tts 或 Rachel=21m00Tcm4TlvDq8ikWAM @tts",
147
- "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": "设为默认渠道",
148
184
  "channel.cancel": "取消",
149
- "channel.save": "保存渠道",
150
- "presets.title": "预置厂商",
151
- "presets.custom": "自定义渠道"
185
+ "channel.save": "保存渠道"
152
186
  };
153
187
  const en = {
154
188
  "entry.label": "AI Audio",
@@ -189,8 +223,10 @@ window.__ModuleLoader__.load({
189
223
  "channels.title": "Audio channels",
190
224
  "channels.hint": "Each channel is an independent audio vendor/API endpoint.",
191
225
  "channels.empty": "No channels yet.",
192
- "channels.addProvider": "+ Add preset vendor",
193
- "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",
194
230
  "channels.edit": "Edit",
195
231
  "channels.delete": "Delete",
196
232
  "channels.confirm": "Confirm delete",
@@ -202,17 +238,49 @@ window.__ModuleLoader__.load({
202
238
  "channels.statusReady": "Ready",
203
239
  "channels.statusIncomplete": "Incomplete",
204
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",
205
247
  "channel.name": "Name",
248
+ "channel.namePlaceholder": "Channel name (e.g. MiniMax main)",
206
249
  "channel.apiUrl": "API URL",
250
+ "channel.apiUrlPlaceholder": "Provider default",
251
+ "channel.apiUrlHint": "Leave blank to use the provider default.",
207
252
  "channel.apiKey": "API key",
208
- "channel.apiKeyHint": "Leave blank to keep the current key.",
209
- "channel.models": "Models / voices (one per line: alias=upstreamId)",
210
- "channel.modelsHint": "One per line: alias=upstreamId, optional @category (tts/music/sfx/voice_design/voice_clone); e.g. tts-1=tts-1 @tts or Rachel=21m00Tcm4TlvDq8ikWAM @tts",
211
- "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",
212
282
  "channel.cancel": "Cancel",
213
- "channel.save": "Save channel",
214
- "presets.title": "Preset vendors",
215
- "presets.custom": "Custom channel"
283
+ "channel.save": "Save channel"
216
284
  };
217
285
  //#endregion
218
286
  //#region src/client/helpers.ts
@@ -464,7 +532,7 @@ window.__ModuleLoader__.load({
464
532
  }
465
533
  //#endregion
466
534
  //#region \0dsh-css:/Users/shimingming/Projects_code/dsh-audiogen/src/client/audio-panel.module.css.mjs
467
- 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}";
468
536
  const tagId$3 = "dsh-audiogen/audio-panel.module.css";
469
537
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$3) + "]") === null) {
470
538
  const tag = document.createElement("style");
@@ -474,33 +542,36 @@ window.__ModuleLoader__.load({
474
542
  document.head.appendChild(tag);
475
543
  }
476
544
  var audio_panel_module_css_default = {
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",
551
+ "textarea": "Oo1fpq_textarea",
552
+ "result": "Oo1fpq_result",
478
553
  "input": "Oo1fpq_input",
479
- "panel": "Oo1fpq_panel",
480
554
  "historyTitle": "Oo1fpq_historyTitle",
481
- "historyMeta": "Oo1fpq_historyMeta",
482
- "historyEmpty": "Oo1fpq_historyEmpty",
483
- "generate": "Oo1fpq_generate",
484
- "audioList": "Oo1fpq_audioList",
485
- "hint": "Oo1fpq_hint",
486
- "error": "Oo1fpq_error",
487
555
  "download": "Oo1fpq_download",
488
- "result": "Oo1fpq_result",
489
- "layout": "Oo1fpq_layout",
490
- "history": "Oo1fpq_history",
491
- "historyItem": "Oo1fpq_historyItem",
492
- "modeRow": "Oo1fpq_modeRow",
493
- "modeButton": "Oo1fpq_modeButton",
494
- "historyAudio": "Oo1fpq_historyAudio",
556
+ "checkbox": "Oo1fpq_checkbox",
495
557
  "header": "Oo1fpq_header",
496
- "textarea": "Oo1fpq_textarea",
497
- "form": "Oo1fpq_form",
498
- "title": "Oo1fpq_title",
499
- "audioCard": "Oo1fpq_audioCard",
500
558
  "empty": "Oo1fpq_empty",
559
+ "generate": "Oo1fpq_generate",
560
+ "title": "Oo1fpq_title",
501
561
  "audio": "Oo1fpq_audio",
562
+ "modeRow": "Oo1fpq_modeRow",
563
+ "select": "Oo1fpq_select",
564
+ "historyAudio": "Oo1fpq_historyAudio",
565
+ "historyItem": "Oo1fpq_historyItem",
566
+ "error": "Oo1fpq_error",
567
+ "panel": "Oo1fpq_panel",
568
+ "historyMeta": "Oo1fpq_historyMeta",
569
+ "modeButton": "Oo1fpq_modeButton",
570
+ "advanced": "Oo1fpq_advanced",
571
+ "audioCard": "Oo1fpq_audioCard",
502
572
  "historyPrompt": "Oo1fpq_historyPrompt",
503
- "select": "Oo1fpq_select"
573
+ "form": "Oo1fpq_form",
574
+ "history": "Oo1fpq_history"
504
575
  };
505
576
  //#endregion
506
577
  //#region src/client/AudioGenPanel.tsx
@@ -557,10 +628,22 @@ window.__ModuleLoader__.load({
557
628
  const [speed, setSpeed] = (0, react.useState)("");
558
629
  const [duration, setDuration] = (0, react.useState)("");
559
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);
560
639
  const [loading, setLoading] = (0, react.useState)(false);
561
640
  const [error, setError] = (0, react.useState)(null);
562
641
  const [outputs, setOutputs] = (0, react.useState)([]);
563
642
  const { entries, reload, clear } = useHistory();
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]);
564
647
  const visibleModels = (0, react.useMemo)(() => {
565
648
  if (mode === "voice_design") return [];
566
649
  return modelOptions.models.filter((entry) => entry.category === void 0 || entry.category === "tts" && mode === "tts" || entry.category === mode).map((entry) => entry.alias);
@@ -584,7 +667,15 @@ window.__ModuleLoader__.load({
584
667
  ...voice.trim() !== "" ? { voice: voice.trim() } : {},
585
668
  ...speed.trim() !== "" ? { speed: Number(speed) } : {},
586
669
  ...duration.trim() !== "" ? { duration: Number(duration) } : {},
587
- ...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 } : {}
588
679
  });
589
680
  if (!response.ok) {
590
681
  setError(response.message ?? "生成失败");
@@ -676,7 +767,7 @@ window.__ModuleLoader__.load({
676
767
  className: audio_panel_module_css_default.input,
677
768
  value: voice,
678
769
  onChange: (event) => setVoice(event.target.value),
679
- placeholder: "alloy / 自定义音色"
770
+ placeholder: isMiniMaxChannel ? "male-qn-qingse / female-shaonv" : "alloy / 自定义音色"
680
771
  })]
681
772
  }) : null,
682
773
  mode === "tts" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
@@ -692,6 +783,118 @@ window.__ModuleLoader__.load({
692
783
  placeholder: "1.0"
693
784
  })]
694
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,
695
898
  mode === "music" || mode === "sfx" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
696
899
  className: audio_panel_module_css_default.label,
697
900
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: tt("duration.label") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
@@ -847,167 +1050,167 @@ window.__ModuleLoader__.load({
847
1050
  document.head.appendChild(tag);
848
1051
  }
849
1052
  var panel_module_css_default = {
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",
850
1063
  "referenceActions": "rwa6qG_referenceActions",
851
- "taskRows": "rwa6qG_taskRows",
852
- "canvasError": "rwa6qG_canvasError",
853
- "galleryRatioList": "rwa6qG_galleryRatioList",
854
- "historyTitle": "rwa6qG_historyTitle",
855
- "studio": "rwa6qG_studio",
856
- "taskRow": "rwa6qG_taskRow",
857
- "templatesButton": "rwa6qG_templatesButton",
858
- "gallerySearch": "rwa6qG_gallerySearch",
859
- "taskTray": "rwa6qG_taskTray",
1064
+ "galleryBulkButton": "rwa6qG_galleryBulkButton",
1065
+ "modelMenu": "rwa6qG_modelMenu",
1066
+ "lightboxIndex": "rwa6qG_lightboxIndex",
1067
+ "lightboxTools": "rwa6qG_lightboxTools",
860
1068
  "updateActions": "rwa6qG_updateActions",
861
- "paramHint": "rwa6qG_paramHint",
862
- "connectionDot": "rwa6qG_connectionDot",
863
- "panelHeading": "rwa6qG_panelHeading",
864
- "historyClear": "rwa6qG_historyClear",
865
- "panelHeader": "rwa6qG_panelHeader",
866
- "modePill": "rwa6qG_modePill",
867
- "historyInfo": "rwa6qG_historyInfo",
1069
+ "canvas": "rwa6qG_canvas",
1070
+ "galleryTagFilter": "rwa6qG_galleryTagFilter",
1071
+ "galleryMasonry": "rwa6qG_galleryMasonry",
1072
+ "gallerySearch": "rwa6qG_gallerySearch",
1073
+ "bigSpinner": "rwa6qG_bigSpinner",
1074
+ "comparisonImageButton": "rwa6qG_comparisonImageButton",
1075
+ "prompt": "rwa6qG_prompt",
1076
+ "lightboxActions": "rwa6qG_lightboxActions",
1077
+ "lightboxCopy": "rwa6qG_lightboxCopy",
1078
+ "studio": "rwa6qG_studio",
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",
1087
+ "lightboxCaptionRow": "rwa6qG_lightboxCaptionRow",
1088
+ "galleryFilterCount": "rwa6qG_galleryFilterCount",
1089
+ "modeRow": "rwa6qG_modeRow",
1090
+ "modelWrap": "rwa6qG_modelWrap",
868
1091
  "canvasState": "rwa6qG_canvasState",
869
- "canvasStateTitle": "rwa6qG_canvasStateTitle",
870
- "card": "rwa6qG_card",
871
- "dshImageGenToastIn": "rwa6qG_dshImageGenToastIn",
1092
+ "gallerySort": "rwa6qG_gallerySort",
1093
+ "panel": "rwa6qG_panel",
872
1094
  "configGuideBody": "rwa6qG_configGuideBody",
873
1095
  "modelMenuItem": "rwa6qG_modelMenuItem",
874
- "galleryRatio": "rwa6qG_galleryRatio",
875
- "galleryTagFilterList": "rwa6qG_galleryTagFilterList",
876
- "comparisonImageButton": "rwa6qG_comparisonImageButton",
877
- "comparisonFullscreenGrid": "rwa6qG_comparisonFullscreenGrid",
878
- "promptFooter": "rwa6qG_promptFooter",
1096
+ "canvasStateHint": "rwa6qG_canvasStateHint",
1097
+ "lightboxTool": "rwa6qG_lightboxTool",
1098
+ "panelHeading": "rwa6qG_panelHeading",
1099
+ "hiddenFile": "rwa6qG_hiddenFile",
1100
+ "zoomHint": "rwa6qG_zoomHint",
1101
+ "galleryCardInfo": "rwa6qG_galleryCardInfo",
1102
+ "image": "rwa6qG_image",
1103
+ "history": "rwa6qG_history",
1104
+ "canvasMeta": "rwa6qG_canvasMeta",
1105
+ "canvasStateTitle": "rwa6qG_canvasStateTitle",
879
1106
  "galleryFilter": "rwa6qG_galleryFilter",
880
- "gallerySelect": "rwa6qG_gallerySelect",
881
- "galleryMasonry": "rwa6qG_galleryMasonry",
1107
+ "galleryToolbar": "rwa6qG_galleryToolbar",
1108
+ "config": "rwa6qG_config",
1109
+ "historyInfo": "rwa6qG_historyInfo",
1110
+ "updateRelease": "rwa6qG_updateRelease",
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",
882
1120
  "historyFilters": "rwa6qG_historyFilters",
883
- "history": "rwa6qG_history",
884
- "uploadIcon": "rwa6qG_uploadIcon",
885
- "historyAction": "rwa6qG_historyAction",
886
- "lightboxCopy": "rwa6qG_lightboxCopy",
1121
+ "dshImageGenSpin": "rwa6qG_dshImageGenSpin",
1122
+ "uploadBox": "rwa6qG_uploadBox",
1123
+ "gallerySelectionBar": "rwa6qG_gallerySelectionBar",
887
1124
  "comparisonBoard": "rwa6qG_comparisonBoard",
888
- "historyEmpty": "rwa6qG_historyEmpty",
889
- "galleryTagFilter": "rwa6qG_galleryTagFilter",
890
- "image": "rwa6qG_image",
891
- "canvasStateHint": "rwa6qG_canvasStateHint",
892
- "galleryAdd": "rwa6qG_galleryAdd",
893
- "config": "rwa6qG_config",
894
- "lightboxActions": "rwa6qG_lightboxActions",
1125
+ "historyItem": "rwa6qG_historyItem",
895
1126
  "galleryTags": "rwa6qG_galleryTags",
896
- "generateButton": "rwa6qG_generateButton",
897
- "panelTitle": "rwa6qG_panelTitle",
898
- "historyThumbPlaceholder": "rwa6qG_historyThumbPlaceholder",
1127
+ "galleryCount": "rwa6qG_galleryCount",
1128
+ "galleryTagEditor": "rwa6qG_galleryTagEditor",
1129
+ "compareToggle": "rwa6qG_compareToggle",
1130
+ "card": "rwa6qG_card",
1131
+ "updateText": "rwa6qG_updateText",
1132
+ "paramLabel": "rwa6qG_paramLabel",
899
1133
  "historyMain": "rwa6qG_historyMain",
900
- "canvasMeta": "rwa6qG_canvasMeta",
901
- "download": "rwa6qG_download",
902
- "prompt": "rwa6qG_prompt",
903
- "entryLabel": "rwa6qG_entryLabel",
904
- "galleryToast": "rwa6qG_galleryToast",
905
- "optionPill": "rwa6qG_optionPill",
906
- "lightboxScaleFrame": "rwa6qG_lightboxScaleFrame",
907
- "galleryHeading": "rwa6qG_galleryHeading",
908
- "compareControl": "rwa6qG_compareControl",
909
- "imageCaption": "rwa6qG_imageCaption",
910
- "promptCount": "rwa6qG_promptCount",
1134
+ "optionRow": "rwa6qG_optionRow",
911
1135
  "lightboxStage": "rwa6qG_lightboxStage",
912
- "updateRelease": "rwa6qG_updateRelease",
913
- "lightboxDownload": "rwa6qG_lightboxDownload",
914
- "gallerySelectMode": "rwa6qG_gallerySelectMode",
915
- "compareToggle": "rwa6qG_compareToggle",
916
- "grid": "rwa6qG_grid",
917
- "zoomHint": "rwa6qG_zoomHint",
918
- "modelSelect": "rwa6qG_modelSelect",
919
- "modelMenu": "rwa6qG_modelMenu",
920
- "lightboxFigure": "rwa6qG_lightboxFigure",
921
- "lightboxTools": "rwa6qG_lightboxTools",
922
- "compareModelChoices": "rwa6qG_compareModelChoices",
923
- "gallerySelectionClear": "rwa6qG_gallerySelectionClear",
924
- "lightboxMeta": "rwa6qG_lightboxMeta",
925
- "taskPrompt": "rwa6qG_taskPrompt",
926
- "modelWrap": "rwa6qG_modelWrap",
927
- "updateBanner": "rwa6qG_updateBanner",
928
- "configGuide": "rwa6qG_configGuide",
929
- "modelLabel": "rwa6qG_modelLabel",
1136
+ "galleryRatioList": "rwa6qG_galleryRatioList",
1137
+ "taskTray": "rwa6qG_taskTray",
1138
+ "paramHint": "rwa6qG_paramHint",
1139
+ "galleryRemove": "rwa6qG_galleryRemove",
1140
+ "imageCaption": "rwa6qG_imageCaption",
1141
+ "galleryTagFilterList": "rwa6qG_galleryTagFilterList",
930
1142
  "historyMeta": "rwa6qG_historyMeta",
931
- "galleryBulkButton": "rwa6qG_galleryBulkButton",
932
- "generateInner": "rwa6qG_generateInner",
933
- "lightboxImage": "rwa6qG_lightboxImage",
934
- "lightboxClose": "rwa6qG_lightboxClose",
935
- "entryIcon": "rwa6qG_entryIcon",
936
- "historyHeader": "rwa6qG_historyHeader",
937
- "view": "rwa6qG_view",
938
- "galleryWorkspace": "rwa6qG_galleryWorkspace",
939
- "galleryAvatar": "rwa6qG_galleryAvatar",
940
- "taskTrayChevron": "rwa6qG_taskTrayChevron",
941
- "canvas": "rwa6qG_canvas",
942
- "lightboxEdit": "rwa6qG_lightboxEdit",
943
- "taskTrayCount": "rwa6qG_taskTrayCount",
944
- "taskTrayToggle": "rwa6qG_taskTrayToggle",
945
- "galleryCardInfo": "rwa6qG_galleryCardInfo",
946
- "imageCard": "rwa6qG_imageCard",
947
- "galleryCount": "rwa6qG_galleryCount",
948
- "galleryTagEdit": "rwa6qG_galleryTagEdit",
949
- "historySearch": "rwa6qG_historySearch",
950
- "historyActions": "rwa6qG_historyActions",
951
1143
  "lightboxZoomLevel": "rwa6qG_lightboxZoomLevel",
1144
+ "galleryHeading": "rwa6qG_galleryHeading",
952
1145
  "reference": "rwa6qG_reference",
953
- "historyPrompt": "rwa6qG_historyPrompt",
954
- "galleryFilterNote": "rwa6qG_galleryFilterNote",
955
- "taskTrayHeader": "rwa6qG_taskTrayHeader",
956
- "galleryImage": "rwa6qG_galleryImage",
957
- "comparisonFullscreen": "rwa6qG_comparisonFullscreen",
958
- "galleryClear": "rwa6qG_galleryClear",
959
- "footer": "rwa6qG_footer",
960
- "canvasHistoryTag": "rwa6qG_canvasHistoryTag",
961
- "uploadBox": "rwa6qG_uploadBox",
962
- "hiddenFile": "rwa6qG_hiddenFile",
963
- "dshImageGenSpin": "rwa6qG_dshImageGenSpin",
964
- "optionRow": "rwa6qG_optionRow",
965
- "comparisonGrid": "rwa6qG_comparisonGrid",
966
- "galleryRemove": "rwa6qG_galleryRemove",
967
- "panel": "rwa6qG_panel",
968
- "updateText": "rwa6qG_updateText",
969
- "lightboxNav": "rwa6qG_lightboxNav",
970
- "galleryFilterHeading": "rwa6qG_galleryFilterHeading",
971
- "paramLabel": "rwa6qG_paramLabel",
972
- "taskTrayClose": "rwa6qG_taskTrayClose",
973
- "gallerySort": "rwa6qG_gallerySort",
974
- "galleryTagEditor": "rwa6qG_galleryTagEditor",
975
- "lightboxCaptionRow": "rwa6qG_lightboxCaptionRow",
1146
+ "galleryImageButton": "rwa6qG_galleryImageButton",
976
1147
  "historyList": "rwa6qG_historyList",
977
- "galleryTagInput": "rwa6qG_galleryTagInput",
978
- "lightboxIndex": "rwa6qG_lightboxIndex",
979
- "galleryFilterCount": "rwa6qG_galleryFilterCount",
1148
+ "historyPrompt": "rwa6qG_historyPrompt",
1149
+ "modelMenuList": "rwa6qG_modelMenuList",
980
1150
  "galleryFilterDivider": "rwa6qG_galleryFilterDivider",
1151
+ "galleryViewToggle": "rwa6qG_galleryViewToggle",
1152
+ "lightboxClose": "rwa6qG_lightboxClose",
1153
+ "galleryRatio": "rwa6qG_galleryRatio",
1154
+ "canvasEmptyIcon": "rwa6qG_canvasEmptyIcon",
1155
+ "canvasHistoryTag": "rwa6qG_canvasHistoryTag",
1156
+ "lightboxCaption": "rwa6qG_lightboxCaption",
1157
+ "lightboxMeta": "rwa6qG_lightboxMeta",
1158
+ "historyAction": "rwa6qG_historyAction",
981
1159
  "enhanceButton": "rwa6qG_enhanceButton",
982
- "historyItem": "rwa6qG_historyItem",
983
- "uploadHint": "rwa6qG_uploadHint",
984
- "connectionStatus": "rwa6qG_connectionStatus",
985
- "modeRow": "rwa6qG_modeRow",
986
- "modelMenuList": "rwa6qG_modelMenuList",
1160
+ "taskTrayChevron": "rwa6qG_taskTrayChevron",
987
1161
  "spinner": "rwa6qG_spinner",
988
- "lightbox": "rwa6qG_lightbox",
989
- "githubLink": "rwa6qG_githubLink",
990
- "lightboxTool": "rwa6qG_lightboxTool",
991
- "historyThumb": "rwa6qG_historyThumb",
992
- "canvasEmptyIcon": "rwa6qG_canvasEmptyIcon",
993
- "lightboxCaption": "rwa6qG_lightboxCaption",
994
- "bigSpinner": "rwa6qG_bigSpinner",
995
- "optionGrid": "rwa6qG_optionGrid",
996
- "taskStatus": "rwa6qG_taskStatus",
997
- "configScroll": "rwa6qG_configScroll",
998
- "gallerySelectionBar": "rwa6qG_gallerySelectionBar",
999
- "galleryImageButton": "rwa6qG_galleryImageButton",
1000
- "galleryCard": "rwa6qG_galleryCard",
1162
+ "generateInner": "rwa6qG_generateInner",
1163
+ "taskRow": "rwa6qG_taskRow",
1164
+ "lightboxNav": "rwa6qG_lightboxNav",
1165
+ "lightboxDownload": "rwa6qG_lightboxDownload",
1166
+ "promptFooter": "rwa6qG_promptFooter",
1167
+ "grid": "rwa6qG_grid",
1001
1168
  "referenceImage": "rwa6qG_referenceImage",
1002
- "entry": "rwa6qG_entry",
1003
- "galleryFilters": "rwa6qG_galleryFilters",
1004
- "galleryToolbarActions": "rwa6qG_galleryToolbarActions",
1005
- "canvasBody": "rwa6qG_canvasBody",
1169
+ "imageCard": "rwa6qG_imageCard",
1170
+ "galleryToast": "rwa6qG_galleryToast",
1006
1171
  "galleryBadge": "rwa6qG_galleryBadge",
1007
- "paramGroup": "rwa6qG_paramGroup",
1008
1172
  "galleryCardFooter": "rwa6qG_galleryCardFooter",
1009
- "galleryToolbar": "rwa6qG_galleryToolbar",
1010
- "galleryViewToggle": "rwa6qG_galleryViewToggle"
1173
+ "comparisonFullscreen": "rwa6qG_comparisonFullscreen",
1174
+ "historyEmpty": "rwa6qG_historyEmpty",
1175
+ "galleryToolbarActions": "rwa6qG_galleryToolbarActions",
1176
+ "taskTrayCount": "rwa6qG_taskTrayCount",
1177
+ "taskTrayClose": "rwa6qG_taskTrayClose",
1178
+ "templatesButton": "rwa6qG_templatesButton",
1179
+ "gallerySelectMode": "rwa6qG_gallerySelectMode",
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",
1190
+ "galleryTagInput": "rwa6qG_galleryTagInput",
1191
+ "connectionDot": "rwa6qG_connectionDot",
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"
1011
1214
  };
1012
1215
  //#endregion
1013
1216
  //#region src/client/mount.tsx
@@ -1654,7 +1857,7 @@ window.__ModuleLoader__.load({
1654
1857
  }
1655
1858
  //#endregion
1656
1859
  //#region \0dsh-css:/Users/shimingming/Projects_code/dsh-audiogen/src/client/settings-card.module.css.mjs
1657
- 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}}";
1658
1861
  const tagId$1 = "dsh-audiogen/settings-card.module.css";
1659
1862
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
1660
1863
  const tag = document.createElement("style");
@@ -1664,97 +1867,79 @@ window.__ModuleLoader__.load({
1664
1867
  document.head.appendChild(tag);
1665
1868
  }
1666
1869
  var settings_card_module_css_default = {
1870
+ "footer": "zmjoSq_footer",
1871
+ "save": "zmjoSq_save",
1872
+ "modelCatalog": "zmjoSq_modelCatalog",
1873
+ "channelDotReady": "zmjoSq_channelDotReady",
1874
+ "candidateTitle": "zmjoSq_candidateTitle",
1667
1875
  "label": "zmjoSq_label",
1668
- "optionalContent": "zmjoSq_optionalContent",
1669
- "channelAdd": "zmjoSq_channelAdd",
1670
- "modelRowRemove": "zmjoSq_modelRowRemove",
1671
- "description": "zmjoSq_description",
1672
- "head": "zmjoSq_head",
1673
- "modelCandidateList": "zmjoSq_modelCandidateList",
1674
- "presetHint": "zmjoSq_presetHint",
1876
+ "candidatePanel": "zmjoSq_candidatePanel",
1675
1877
  "select": "zmjoSq_select",
1676
- "notExposed": "zmjoSq_notExposed",
1677
- "sectionHint": "zmjoSq_sectionHint",
1678
1878
  "editorFooter": "zmjoSq_editorFooter",
1679
- "modelRowBadges": "zmjoSq_modelRowBadges",
1680
- "modelFetchRow": "zmjoSq_modelFetchRow",
1681
- "editorPanel": "zmjoSq_editorPanel",
1682
- "disclosure": "zmjoSq_disclosure",
1683
- "sectionHeader": "zmjoSq_sectionHeader",
1684
- "save": "zmjoSq_save",
1879
+ "description": "zmjoSq_description",
1880
+ "channelMain": "zmjoSq_channelMain",
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",
1685
1891
  "channelSection": "zmjoSq_channelSection",
1686
- "manualModelRow": "zmjoSq_manualModelRow",
1687
- "modelSection": "zmjoSq_modelSection",
1688
- "field": "zmjoSq_field",
1892
+ "detectOk": "zmjoSq_detectOk",
1893
+ "channelDotWarn": "zmjoSq_channelDotWarn",
1894
+ "body": "zmjoSq_body",
1895
+ "channelDanger": "zmjoSq_channelDanger",
1896
+ "linkButton": "zmjoSq_linkButton",
1689
1897
  "deleteConfirmText": "zmjoSq_deleteConfirmText",
1690
- "modelSummary": "zmjoSq_modelSummary",
1691
- "channelAddRow": "zmjoSq_channelAddRow",
1898
+ "editorHeader": "zmjoSq_editorHeader",
1899
+ "discard": "zmjoSq_discard",
1900
+ "editorTitle": "zmjoSq_editorTitle",
1901
+ "head": "zmjoSq_head",
1902
+ "channelHost": "zmjoSq_channelHost",
1903
+ "chevronOpen": "zmjoSq_chevronOpen",
1904
+ "modelRow": "zmjoSq_modelRow",
1905
+ "chevron": "zmjoSq_chevron",
1906
+ "sectionHeader": "zmjoSq_sectionHeader",
1692
1907
  "channelMeta": "zmjoSq_channelMeta",
1693
- "editorTools": "zmjoSq_editorTools",
1694
- "hint": "zmjoSq_hint",
1695
- "editorClose": "zmjoSq_editorClose",
1696
- "modelFetch": "zmjoSq_modelFetch",
1697
- "sectionTitle": "zmjoSq_sectionTitle",
1698
- "channelEmpty": "zmjoSq_channelEmpty",
1699
- "readOnly": "zmjoSq_readOnly",
1700
- "channelAction": "zmjoSq_channelAction",
1701
1908
  "failed": "zmjoSq_failed",
1702
- "channelControls": "zmjoSq_channelControls",
1703
- "presetRow": "zmjoSq_presetRow",
1704
- "headText": "zmjoSq_headText",
1705
- "versionRow": "zmjoSq_versionRow",
1706
- "modelCandidate": "zmjoSq_modelCandidate",
1707
- "channelDotReady": "zmjoSq_channelDotReady",
1708
- "channelDotWarn": "zmjoSq_channelDotWarn",
1709
- "footer": "zmjoSq_footer",
1710
- "channelHost": "zmjoSq_channelHost",
1711
- "channelRow": "zmjoSq_channelRow",
1712
- "channelMain": "zmjoSq_channelMain",
1713
- "editorField": "zmjoSq_editorField",
1714
- "modelRows": "zmjoSq_modelRows",
1715
- "presetMeta": "zmjoSq_presetMeta",
1716
- "reset": "zmjoSq_reset",
1717
- "name": "zmjoSq_name",
1718
- "versionValue": "zmjoSq_versionValue",
1719
- "badges": "zmjoSq_badges",
1720
- "badge": "zmjoSq_badge",
1721
- "channelName": "zmjoSq_channelName",
1722
- "editorSectionHeader": "zmjoSq_editorSectionHeader",
1723
- "presetName": "zmjoSq_presetName",
1724
- "pending": "zmjoSq_pending",
1725
- "invalid": "zmjoSq_invalid",
1726
- "modelChip": "zmjoSq_modelChip",
1909
+ "modelCatalogHead": "zmjoSq_modelCatalogHead",
1727
1910
  "header": "zmjoSq_header",
1728
- "modelRow": "zmjoSq_modelRow",
1911
+ "link": "zmjoSq_link",
1912
+ "field": "zmjoSq_field",
1913
+ "input": "zmjoSq_input",
1914
+ "editorWrap": "zmjoSq_editorWrap",
1915
+ "modelInput": "zmjoSq_modelInput",
1916
+ "channelAddRow": "zmjoSq_channelAddRow",
1917
+ "candidateActions": "zmjoSq_candidateActions",
1729
1918
  "channelList": "zmjoSq_channelList",
1730
- "inputInvalid": "zmjoSq_inputInvalid",
1731
- "versionLabel": "zmjoSq_versionLabel",
1732
- "editorBackdrop": "zmjoSq_editorBackdrop",
1733
- "chevron": "zmjoSq_chevron",
1734
- "card": "zmjoSq_card",
1735
- "chevronOpen": "zmjoSq_chevronOpen",
1736
- "editorHeader": "zmjoSq_editorHeader",
1737
- "modelCandidateLabel": "zmjoSq_modelCandidateLabel",
1738
- "sectionDivider": "zmjoSq_sectionDivider",
1919
+ "modelEmpty": "zmjoSq_modelEmpty",
1739
1920
  "addModel": "zmjoSq_addModel",
1740
- "channelBadge": "zmjoSq_channelBadge",
1741
- "editorDivider": "zmjoSq_editorDivider",
1742
- "input": "zmjoSq_input",
1743
- "modelArrow": "zmjoSq_modelArrow",
1744
- "textarea": "zmjoSq_textarea",
1745
- "presetInlineHeader": "zmjoSq_presetInlineHeader",
1746
- "modelRowInputs": "zmjoSq_modelRowInputs",
1747
- "presetInline": "zmjoSq_presetInline",
1748
- "presetList": "zmjoSq_presetList",
1749
- "discard": "zmjoSq_discard",
1750
- "channelDanger": "zmjoSq_channelDanger",
1751
- "spacer": "zmjoSq_spacer",
1752
- "textareaInvalid": "zmjoSq_textareaInvalid",
1753
- "inlineDisclosure": "zmjoSq_inlineDisclosure",
1754
- "body": "zmjoSq_body",
1755
- "modelChoices": "zmjoSq_modelChoices",
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",
1756
1937
  "modelBadge": "zmjoSq_modelBadge",
1757
- "detectOk": "zmjoSq_detectOk"
1938
+ "channelName": "zmjoSq_channelName",
1939
+ "sectionHint": "zmjoSq_sectionHint",
1940
+ "channelEditor": "zmjoSq_channelEditor",
1941
+ "customSettings": "zmjoSq_customSettings",
1942
+ "channelBadge": "zmjoSq_channelBadge"
1758
1943
  };
1759
1944
  //#endregion
1760
1945
  //#region src/client/SettingsCard.tsx
@@ -1764,6 +1949,12 @@ window.__ModuleLoader__.load({
1764
1949
  * Registers into the official `settings.plugin.item` slot. It manages a list
1765
1950
  * of audio channels (each with API URL, per-channel secret, and model/voice
1766
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.
1767
1958
  */
1768
1959
  var AudioGenSettingsCardController = class {
1769
1960
  scope;
@@ -1803,110 +1994,580 @@ window.__ModuleLoader__.load({
1803
1994
  };
1804
1995
  }
1805
1996
  };
1806
- function newChannelDraft(preset, existing) {
1807
- const id = `ch-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`;
1808
- if (preset === void 0) return {
1809
- id,
1810
- preset: "",
1811
- name: "",
1812
- apiUrl: "",
1813
- models: []
1814
- };
1815
- return {
1816
- id,
1817
- preset: preset.id,
1818
- name: preset.name,
1819
- apiUrl: preset.apiUrl,
1820
- models: preset.models.map((model) => ({ ...model }))
1821
- };
1822
- }
1823
- function modelsToText(models) {
1824
- 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)}`;
1825
2007
  }
1826
- function textToModels(text) {
1827
- return text.split(/\n|,/).map((line) => line.trim()).filter(Boolean).map((line) => {
1828
- const at = line.lastIndexOf(" @");
1829
- const category = at >= 0 ? line.slice(at + 2).trim() : void 0;
1830
- const body = at >= 0 ? line.slice(0, at).trim() : line;
1831
- const eq = body.indexOf("=");
1832
- const alias = eq >= 0 ? body.slice(0, eq).trim() : body.trim();
1833
- const id = eq >= 0 ? body.slice(eq + 1).trim() : alias;
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;
1834
2014
  return {
1835
- alias,
1836
- id: id === "" ? alias : id,
1837
- ...category === void 0 || category === "" ? {} : { category }
2015
+ alias: alias === "" ? id : alias,
2016
+ id,
2017
+ ...model.category === void 0 ? {} : { category: model.category }
1838
2018
  };
1839
- }).filter((model) => model.alias !== "");
2019
+ }).filter((model) => model !== void 0);
2020
+ return [...new Map(cleaned.map((model) => [model.alias, model])).values()];
1840
2021
  }
1841
- function AudioGenSettingsCard(props) {
1842
- const { t } = props;
1843
- const state = props.useAudioGenSettingsCard((snapshot) => snapshot);
1844
- const [open, setOpen] = (0, react.useState)(false);
1845
- const [editingId, setEditingId] = (0, react.useState)(null);
1846
- const [presetPickerOpen, setPresetPickerOpen] = (0, react.useState)(false);
1847
- const [presets, setPresets] = (0, react.useState)([]);
1848
- const [presetError, setPresetError] = (0, react.useState)(null);
1849
- 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);
1850
2049
  const [discovering, setDiscovering] = (0, react.useState)(false);
1851
2050
  const [discoverError, setDiscoverError] = (0, react.useState)(null);
1852
- const [editName, setEditName] = (0, react.useState)("");
1853
- const [editUrl, setEditUrl] = (0, react.useState)("");
1854
- const [editKey, setEditKey] = (0, react.useState)("");
1855
- const [editModels, setEditModels] = (0, react.useState)("");
1856
- const [editDefault, setEditDefault] = (0, react.useState)(false);
1857
- const channels = state.channels.channels;
1858
- const editing = editingId === null ? void 0 : channels.find((channel) => channel.id === editingId);
1859
- (0, react.useEffect)(() => {
1860
- if (editing === void 0) return;
1861
- setEditName(editing.name);
1862
- setEditUrl(editing.apiUrl);
1863
- setEditKey("");
1864
- setEditModels(modelsToText(editing.models));
1865
- setEditDefault(editing.id === state.channels.defaultChannelId);
1866
- }, [editingId, editing?.id]);
1867
- if (!state.available) return null;
1868
- const blocked = !state.dirty || state.invalid || state.saving || state.channels.saving;
1869
- const saveEdit = () => {
1870
- if (editingId === null) return;
1871
- const existing = channels.find((channel) => channel.id === editingId);
1872
- const models = textToModels(editModels);
1873
- const updated = {
1874
- id: editingId,
1875
- preset: existing?.preset ?? "",
1876
- name: editName.trim(),
1877
- apiUrl: editUrl.trim(),
1878
- 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)
1879
2070
  };
1880
- const next = existing === void 0 ? [...channels, updated] : channels.map((channel) => channel.id === editingId ? updated : channel);
1881
- props.channels.setChannels(next);
1882
- if (editKey.trim() !== "") props.channels.setChannelKey(editingId, editKey.trim());
1883
- if (editDefault) props.channels.setDefaultChannel(editingId);
1884
- setEditingId(null);
2071
+ const stagedKey = key.trim() !== "" ? key.trim() : keyAction === "clear" ? "" : void 0;
2072
+ props.onSave(channel, stagedKey, isDefault);
1885
2073
  };
1886
- const discoverModels = async () => {
1887
- if (editingId === null) return;
2074
+ const discoverable = url.trim() !== "" && (key.trim() !== "" || effectiveKeyHeld);
2075
+ const discover = async () => {
2076
+ if (!discoverable) return;
1888
2077
  setDiscovering(true);
1889
2078
  setDiscoverError(null);
2079
+ setSourceNote(null);
1890
2080
  try {
1891
- channels.find((channel) => channel.id === editingId);
1892
2081
  const response = await fetch(MODEL_API.discover, {
1893
2082
  method: "POST",
1894
2083
  headers: { "content-type": "application/json" },
1895
2084
  body: JSON.stringify({
1896
- channelId: editingId,
1897
- ...editUrl.trim() !== "" ? { apiUrl: editUrl.trim() } : {},
1898
- ...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() } : {}
1899
2089
  })
1900
2090
  });
1901
2091
  const body = await response.json();
1902
2092
  if (body.ok !== true || body.models === void 0) throw new Error(body.message ?? `HTTP ${response.status}`);
1903
- setEditModels(modelsToText([...body.models, ...textToModels(editModels).filter((existingModel) => !body.models.some((model) => model.id === existingModel.id))]));
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);
1904
2105
  } catch (error) {
1905
2106
  setDiscoverError(error instanceof Error ? error.message : String(error));
1906
2107
  } finally {
1907
2108
  setDiscovering(false);
1908
2109
  }
1909
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
+ };
1910
2571
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
1911
2572
  className: settings_card_module_css_default.card,
1912
2573
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
@@ -1984,15 +2645,7 @@ window.__ModuleLoader__.load({
1984
2645
  type: "button",
1985
2646
  className: settings_card_module_css_default.channelDanger,
1986
2647
  disabled: !state.writable,
1987
- onClick: () => {
1988
- props.channels.setChannels(channels.filter((candidate) => candidate.id !== channel.id));
1989
- if (isDefault && channels.length > 1) {
1990
- const next = channels.find((candidate) => candidate.id !== channel.id);
1991
- if (next !== void 0) props.channels.setDefaultChannel(next.id);
1992
- }
1993
- setConfirmDeleteId(null);
1994
- if (editingId === channel.id) setEditingId(null);
1995
- },
2648
+ onClick: () => removeChannel(channel),
1996
2649
  children: t("channels.confirm")
1997
2650
  }),
1998
2651
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
@@ -2015,7 +2668,12 @@ window.__ModuleLoader__.load({
2015
2668
  type: "button",
2016
2669
  className: settings_card_module_css_default.channelMain,
2017
2670
  disabled: !state.writable,
2018
- onClick: () => setEditingId(channel.id),
2671
+ onClick: () => {
2672
+ setEditor({
2673
+ kind: "edit",
2674
+ channelId: channel.id
2675
+ });
2676
+ },
2019
2677
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2020
2678
  className: settings_card_module_css_default.channelName,
2021
2679
  children: isDefault ? `★ ${channel.name || t("channels.untitled")}` : channel.name || t("channels.untitled")
@@ -2038,7 +2696,12 @@ window.__ModuleLoader__.load({
2038
2696
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2039
2697
  type: "button",
2040
2698
  className: settings_card_module_css_default.channelAction,
2041
- onClick: () => setEditingId(channel.id),
2699
+ onClick: () => {
2700
+ setEditor({
2701
+ kind: "edit",
2702
+ channelId: channel.id
2703
+ });
2704
+ },
2042
2705
  children: t("channels.edit")
2043
2706
  }),
2044
2707
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
@@ -2052,208 +2715,45 @@ window.__ModuleLoader__.load({
2052
2715
  }, channel.id);
2053
2716
  })
2054
2717
  }),
2055
- presetPickerOpen ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2056
- className: settings_card_module_css_default.channelControls,
2057
- children: [
2058
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2059
- className: settings_card_module_css_default.sectionHint,
2060
- children: t("presets.title")
2061
- }),
2062
- presetError !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2063
- className: settings_card_module_css_default.failed,
2064
- children: presetError
2065
- }) : null,
2066
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2067
- className: settings_card_module_css_default.channelAddRow,
2068
- children: [
2069
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2070
- type: "button",
2071
- className: settings_card_module_css_default.channelAdd,
2072
- onClick: () => {
2073
- setPresets([]);
2074
- setPresetError(null);
2075
- fetch(PRESETS_API, { method: "POST" }).then(async (response) => {
2076
- const body = await response.json();
2077
- if (!response.ok || body.ok !== true || body.presets === void 0) throw new Error(body.message ?? `HTTP ${response.status}`);
2078
- setPresets(body.presets);
2079
- }).catch((error) => setPresetError(error instanceof Error ? error.message : String(error)));
2080
- },
2081
- children: t("channels.addProvider")
2082
- }),
2083
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2084
- type: "button",
2085
- className: settings_card_module_css_default.channelAdd,
2086
- onClick: () => {
2087
- const draft = newChannelDraft(void 0, channels);
2088
- props.channels.setChannels([...channels, draft]);
2089
- setPresetPickerOpen(false);
2090
- setEditingId(draft.id);
2091
- },
2092
- children: t("channels.addCustom")
2093
- }),
2094
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2095
- type: "button",
2096
- className: settings_card_module_css_default.channelAction,
2097
- onClick: () => setPresetPickerOpen(false),
2098
- children: "×"
2099
- })
2100
- ]
2101
- }),
2102
- presets.map((preset) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
2103
- type: "button",
2104
- className: settings_card_module_css_default.channelAdd,
2105
- onClick: () => {
2106
- const draft = newChannelDraft(preset, channels);
2107
- props.channels.setChannels([...channels, draft]);
2108
- setPresetPickerOpen(false);
2109
- setEditingId(draft.id);
2110
- },
2111
- children: [
2112
- preset.name,
2113
- " — ",
2114
- preset.hint
2115
- ]
2116
- }, preset.id))
2117
- ]
2118
- }) : /* @__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", {
2119
2723
  className: settings_card_module_css_default.channelAddRow,
2120
2724
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2121
2725
  type: "button",
2122
2726
  className: settings_card_module_css_default.channelAdd,
2123
2727
  disabled: !state.writable,
2124
- onClick: () => {
2125
- setPresetError(null);
2126
- setPresetPickerOpen(true);
2127
- },
2128
- children: t("channels.addProvider")
2728
+ onClick: openAddProvider,
2729
+ children: presetLoading ? t("channels.addProviderLoading") : t("channels.addProvider")
2129
2730
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2130
2731
  type: "button",
2131
2732
  className: settings_card_module_css_default.channelAdd,
2132
2733
  disabled: !state.writable,
2133
- onClick: () => {
2134
- const draft = newChannelDraft(void 0, channels);
2135
- props.channels.setChannels([...channels, draft]);
2136
- setEditingId(draft.id);
2137
- },
2734
+ onClick: openAddCustom,
2138
2735
  children: t("channels.addCustom")
2139
2736
  })]
2140
- })
2141
- ]
2142
- }),
2143
- editing !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2144
- className: settings_card_module_css_default.body,
2145
- children: [
2146
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2147
- className: settings_card_module_css_default.field,
2148
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
2149
- className: settings_card_module_css_default.label,
2150
- htmlFor: `audiogen-name-${editing.id}`,
2151
- children: t("channel.name")
2152
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
2153
- id: `audiogen-name-${editing.id}`,
2154
- className: settings_card_module_css_default.input,
2155
- value: editName,
2156
- onChange: (event) => setEditName(event.target.value)
2157
- })]
2158
- }),
2159
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2160
- className: settings_card_module_css_default.field,
2161
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
2162
- className: settings_card_module_css_default.label,
2163
- htmlFor: `audiogen-url-${editing.id}`,
2164
- children: t("channel.apiUrl")
2165
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
2166
- id: `audiogen-url-${editing.id}`,
2167
- className: settings_card_module_css_default.input,
2168
- value: editUrl,
2169
- onChange: (event) => setEditUrl(event.target.value),
2170
- placeholder: "https://…"
2171
- })]
2172
- }),
2173
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2174
- className: settings_card_module_css_default.field,
2175
- children: [
2176
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
2177
- className: settings_card_module_css_default.label,
2178
- htmlFor: `audiogen-key-${editing.id}`,
2179
- children: t("channel.apiKey")
2180
- }),
2181
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
2182
- id: `audiogen-key-${editing.id}`,
2183
- className: settings_card_module_css_default.input,
2184
- type: "password",
2185
- value: editKey,
2186
- onChange: (event) => setEditKey(event.target.value),
2187
- placeholder: state.channels.keySet[editing.id] ? "••••••" : ""
2188
- }),
2189
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2190
- className: settings_card_module_css_default.sectionHint,
2191
- children: t("channel.apiKeyHint")
2192
- })
2193
- ]
2194
- }),
2195
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2196
- className: settings_card_module_css_default.field,
2197
- children: [
2198
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
2199
- className: settings_card_module_css_default.label,
2200
- htmlFor: `audiogen-models-${editing.id}`,
2201
- children: t("channel.models")
2202
- }),
2203
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
2204
- id: `audiogen-models-${editing.id}`,
2205
- className: settings_card_module_css_default.textarea,
2206
- value: editModels,
2207
- onChange: (event) => setEditModels(event.target.value)
2208
- }),
2209
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2210
- className: settings_card_module_css_default.sectionHint,
2211
- children: t("channel.modelsHint")
2212
- }),
2213
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2214
- className: settings_card_module_css_default.channelAddRow,
2215
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2216
- type: "button",
2217
- className: settings_card_module_css_default.channelAdd,
2218
- disabled: discovering || !state.writable,
2219
- onClick: () => void discoverModels(),
2220
- children: discovering ? "获取中…" : "获取可用模型"
2221
- })
2222
- }),
2223
- discoverError !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2224
- className: settings_card_module_css_default.failed,
2225
- children: discoverError
2226
- }) : null
2227
- ]
2228
- }),
2229
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
2230
- className: settings_card_module_css_default.label,
2231
- children: [
2232
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
2233
- type: "checkbox",
2234
- checked: editDefault,
2235
- onChange: (event) => setEditDefault(event.target.checked)
2236
- }),
2237
- " ",
2238
- t("channel.default")
2239
- ]
2240
2737
  }),
2241
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2242
- className: settings_card_module_css_default.footer,
2243
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2244
- type: "button",
2245
- className: settings_card_module_css_default.discard,
2246
- onClick: () => setEditingId(null),
2247
- children: t("channel.cancel")
2248
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2249
- type: "button",
2250
- className: settings_card_module_css_default.save,
2251
- onClick: saveEdit,
2252
- children: t("channel.save")
2253
- })]
2254
- })
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
2255
2755
  ]
2256
- }) : null,
2756
+ }),
2257
2757
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2258
2758
  className: settings_card_module_css_default.field,
2259
2759
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
@@ -2345,16 +2845,16 @@ window.__ModuleLoader__.load({
2345
2845
  }
2346
2846
  var audio_toolview_module_css_default = {
2347
2847
  "message": "_7K1QKa_message",
2348
- "audios": "_7K1QKa_audios",
2349
- "download": "_7K1QKa_download",
2350
- "icon": "_7K1QKa_icon",
2351
- "error": "_7K1QKa_error",
2352
2848
  "status": "_7K1QKa_status",
2353
- "header": "_7K1QKa_header",
2354
2849
  "audioRow": "_7K1QKa_audioRow",
2355
2850
  "empty": "_7K1QKa_empty",
2851
+ "error": "_7K1QKa_error",
2852
+ "audio": "_7K1QKa_audio",
2853
+ "icon": "_7K1QKa_icon",
2854
+ "download": "_7K1QKa_download",
2356
2855
  "root": "_7K1QKa_root",
2357
- "audio": "_7K1QKa_audio"
2856
+ "audios": "_7K1QKa_audios",
2857
+ "header": "_7K1QKa_header"
2358
2858
  };
2359
2859
  //#endregion
2360
2860
  //#region src/client/audio-toolview.tsx