dsh-audiogen 0.4.5 → 0.4.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.js CHANGED
@@ -892,22 +892,33 @@ async function enhancePromptText(deps, prompt, mode) {
892
892
  if (provider === "" || model === "") throw new AudioGenError("未找到 Agent 默认模型(agent-default-model):请先在「设置 → 模型」中配置默认模型", "no-default-model");
893
893
  const runtime = deps.llm?.();
894
894
  if (runtime === void 0 || runtime.stream === void 0) throw new AudioGenError("宿主 LLM 服务不可用(ctx.llm 未注册)", "llm-unavailable");
895
+ const controller = new AbortController();
896
+ const timer = setTimeout(() => controller.abort(new DOMException("The operation timed out.", "TimeoutError")), 3e4);
897
+ timer.unref?.();
895
898
  let output = "";
896
- for await (const chunk of runtime.stream({
897
- provider,
898
- model,
899
- messages: [{
900
- role: "user",
901
- content: text
902
- }],
903
- system: instructionsFor(mode),
904
- temperature: .7,
905
- maxTokens: 1200
906
- })) {
907
- const record = chunk;
908
- if (record.type === "text-delta" && typeof record.text === "string") output += record.text;
899
+ try {
900
+ for await (const chunk of runtime.stream({
901
+ provider,
902
+ model,
903
+ messages: [{
904
+ role: "user",
905
+ content: text
906
+ }],
907
+ system: instructionsFor(mode),
908
+ temperature: .7,
909
+ maxTokens: 1200,
910
+ signal: controller.signal
911
+ })) {
912
+ const record = chunk;
913
+ if (record.type === "text-delta" && typeof record.text === "string") output += record.text;
914
+ else if (record.type === "block-end" && record.block !== void 0 && record.block.type === "text" && typeof record.block.text === "string") output += record.block.text;
915
+ }
916
+ } finally {
917
+ clearTimeout(timer);
909
918
  }
910
- return stripFences(output.trim());
919
+ const result = stripFences(output.trim());
920
+ if (result === "") throw new AudioGenError("模型未返回增强内容:请检查「设置 → 模型」的默认模型是否可用(或稍后重试)", "enhance-empty-result");
921
+ return result;
911
922
  }
912
923
  /** 去掉模型可能包裹的 ``` 代码围栏。 */
913
924
  function stripFences(value) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "dsh-audiogen",
3
3
  "description": "AI audio generation plugin for the dsh web GUI: multi-vendor TTS/music/sound-effect channels (OpenAI-compatible, ElevenLabs, MiniMax, Stability AI and custom), per-channel model/voice catalogs, Agent tool and a sidebar AI 音频 panel.",
4
- "version": "0.4.5",
4
+ "version": "0.4.6",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
7
7
  "exports": {
@@ -97,9 +97,9 @@
97
97
  flex-direction: column;
98
98
  gap: 11px;
99
99
  flex: none;
100
- width: 300px;
101
- min-width: 260px;
102
- max-width: 340px;
100
+ width: 380px;
101
+ min-width: 320px;
102
+ max-width: 440px;
103
103
  min-height: 0;
104
104
  overflow-y: auto;
105
105
  padding: 2px;
@@ -260,6 +260,7 @@
260
260
  .resultCol {
261
261
  flex: 1;
262
262
  min-width: 0;
263
+ max-width: 760px;
263
264
  display: flex;
264
265
  flex-direction: column;
265
266
  gap: 10px;
@@ -1314,3 +1315,9 @@
1314
1315
  display: flex;
1315
1316
  gap: 6px;
1316
1317
  }
1318
+
1319
+ .enhanceActionsRow {
1320
+ display: flex;
1321
+ justify-content: flex-end;
1322
+ margin-top: -4px;
1323
+ }
@@ -527,6 +527,8 @@ export function StudioView(props: {
527
527
  }
528
528
  const bool = (key: string): boolean | undefined => typeof params[key] === 'boolean' ? params[key] as boolean : undefined
529
529
  setMode(modeValue)
530
+ const promptValue = str('prompt')
531
+ if (promptValue !== undefined) setPrompt(promptValue)
530
532
  const modelValue = str('model') ?? singleModel
531
533
  if (modelValue !== '') setModel(modelValue)
532
534
  if (compareModelsRestore !== undefined && compareModelsRestore.length > 0) {
@@ -591,11 +593,11 @@ export function StudioView(props: {
591
593
  setError(null)
592
594
  try {
593
595
  const result = await api.enhancePrompt(prompt.trim(), mode)
594
- if (result.ok !== true || result.enhanced === undefined) {
596
+ if (result.ok !== true || result.enhanced === undefined || result.enhanced.trim() === '') {
595
597
  setError(result.message ?? '增强失败,请稍后重试')
596
598
  return
597
599
  }
598
- setEnhancePreview(result.enhanced)
600
+ setEnhancePreview(result.enhanced.trim())
599
601
  } catch (err) {
600
602
  setError(err instanceof Error ? err.message : String(err))
601
603
  } finally {
@@ -895,16 +897,16 @@ export function StudioView(props: {
895
897
  ))}
896
898
  </div>
897
899
 
898
- <div className={css.formSectionRow}>
899
- <p className={css.formSection}>输入</p>
900
- <button type="button" className={css.ghostButton} disabled={enhancing} onClick={() => void runEnhance()}>
901
- {enhancing ? '增强中…' : '✨ 增强提示词'}
902
- </button>
903
- </div>
900
+ <p className={css.formSection}>输入</p>
904
901
  <label className={css.label}>
905
902
  <span>{mode === 'voice_design' ? '音色描述' : mode === 'tts' ? '文本' : '提示词'}</span>
906
903
  <textarea className={css.textarea} value={prompt} onChange={event => setPrompt(event.target.value)} placeholder={tt('prompt.placeholder')} />
907
904
  </label>
905
+ <div className={css.enhanceActionsRow}>
906
+ <button type="button" className={css.ghostButton} disabled={enhancing} onClick={() => void runEnhance()}>
907
+ {enhancing ? '增强中…' : '✨ 增强提示词'}
908
+ </button>
909
+ </div>
908
910
  {enhancePreview !== null ? (
909
911
  <div className={css.enhanceCard}>
910
912
  <div className={css.enhanceCardHead}>
@@ -49,19 +49,36 @@ export async function enhancePromptText(deps: PromptEnhanceDeps, prompt: string,
49
49
  if (runtime === undefined || runtime.stream === undefined) {
50
50
  throw new AudioGenError('宿主 LLM 服务不可用(ctx.llm 未注册)', 'llm-unavailable')
51
51
  }
52
+ const controller = new AbortController()
53
+ const timer = setTimeout(() => controller.abort(new DOMException('The operation timed out.', 'TimeoutError')), 30_000)
54
+ timer.unref?.()
52
55
  let output = ''
53
- for await (const chunk of runtime.stream({
54
- provider,
55
- model,
56
- messages: [{ role: 'user', content: text }],
57
- system: instructionsFor(mode),
58
- temperature: 0.7,
59
- maxTokens: 1200,
60
- })) {
61
- const record = chunk as { type?: string; text?: string }
62
- if (record.type === 'text-delta' && typeof record.text === 'string') output += record.text
56
+ try {
57
+ for await (const chunk of runtime.stream({
58
+ provider,
59
+ model,
60
+ messages: [{ role: 'user', content: text }],
61
+ system: instructionsFor(mode),
62
+ temperature: 0.7,
63
+ maxTokens: 1200,
64
+ signal: controller.signal,
65
+ })) {
66
+ const record = chunk as { type?: string; text?: string; block?: { type?: string; text?: string } }
67
+ if (record.type === 'text-delta' && typeof record.text === 'string') {
68
+ output += record.text
69
+ } else if (record.type === 'block-end' && record.block !== undefined
70
+ && record.block.type === 'text' && typeof record.block.text === 'string') {
71
+ output += record.block.text
72
+ }
73
+ }
74
+ } finally {
75
+ clearTimeout(timer)
63
76
  }
64
- return stripFences(output.trim())
77
+ const result = stripFences(output.trim())
78
+ if (result === '') {
79
+ throw new AudioGenError('模型未返回增强内容:请检查「设置 → 模型」的默认模型是否可用(或稍后重试)', 'enhance-empty-result')
80
+ }
81
+ return result
65
82
  }
66
83
 
67
84
  /** 去掉模型可能包裹的 ``` 代码围栏。 */
package/src/protocol.ts CHANGED
@@ -8,7 +8,7 @@
8
8
  export const AUDIOGEN_SETTINGS_NAMESPACE = 'dsh-audiogen'
9
9
 
10
10
  /** Published package version shared by the host updater and the client UI. */
11
- export const PLUGIN_VERSION = '0.4.5'
11
+ export const PLUGIN_VERSION = '0.4.6'
12
12
 
13
13
  /** Same-origin route family (loopback-only, mirroring dsh-imagegen). */
14
14
  export const SETTINGS_API = {