@goodandready/dsh-voice 0.8.19 → 0.8.21

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
@@ -213,7 +213,10 @@ export function apply(ctx, baseConfig) {
213
213
  try {
214
214
  const controller = new AbortController()
215
215
  const t = setTimeout(() => controller.abort(), 2000)
216
- const res = await fetch(live().whisperUrl.split('/inference')[0] + '/', { signal: controller.signal })
216
+ const rawUrl = String(live().whisperUrl || '').trim()
217
+ const base = rawUrl.includes('/inference') ? rawUrl.split('/inference')[0] : rawUrl.replace(/\/+$/, '')
218
+ if (!base) return false
219
+ const res = await fetch(base + '/', { signal: controller.signal })
217
220
  clearTimeout(t)
218
221
  return res.ok
219
222
  } catch { return false }
@@ -266,7 +269,8 @@ export function apply(ctx, baseConfig) {
266
269
  if (!cfg.sensevoiceModel) return false
267
270
  if (await sensevoiceAlive()) return true
268
271
  try {
269
- const port = new URL(cfg.sensevoiceUrl).port || '6006'
272
+ let port = '6006'
273
+ try { port = new URL(cfg.sensevoiceUrl).port || '6006' } catch { /* invalid URL */ }
270
274
  const spec = ctx.shell.resolve({
271
275
  command: `${JSON.stringify(cfg.sensevoiceBin)}`
272
276
  + ` --sense-voice-model=${JSON.stringify(cfg.sensevoiceModel)}`
@@ -533,7 +537,7 @@ export function apply(ctx, baseConfig) {
533
537
  + 'Use for voice messages, recordings, interviews.',
534
538
  parameters: {
535
539
  file_path: { type: 'string', required: true, description: 'Absolute path to the audio file (wav, mp3, m4a, ogg, flac, webm).' },
536
- language: { type: 'string', description: `Recognition language code. Default: ${baseConfig.message.language}.` },
540
+ language: { type: 'string', description: `Recognition language code. Default: ${(baseConfig && baseConfig.message && baseConfig.message.language) || 'ru'}.` },
537
541
  },
538
542
  output: {
539
543
  schema: {
@@ -549,7 +553,7 @@ export function apply(ctx, baseConfig) {
549
553
  },
550
554
  },
551
555
  isConcurrencySafe: () => false,
552
- timeoutMs: baseConfig.timeoutMs * 3 + 5000,
556
+ timeoutMs: 365000,
553
557
  async execute(args, exec) {
554
558
  const cfg = live()
555
559
  const filePath = String(args.file_path || '').trim()
package/lib/providers.js CHANGED
@@ -102,6 +102,17 @@ function isAutoLang(lang) {
102
102
  return !lang || lang === 'auto' || String(lang).includes(',')
103
103
  }
104
104
 
105
+ async function readErrorDetail(res, defaultLabel) {
106
+ let detail = `HTTP ${res.status}`
107
+ try {
108
+ const e = await res.json()
109
+ if (e?.error) detail = typeof e.error === 'string' ? e.error : (e.error.message || JSON.stringify(e.error))
110
+ else if (e?.message) detail = e.message
111
+ else if (e?.err_msg) detail = e.err_msg
112
+ } catch { /* not json */ }
113
+ return `${defaultLabel} ${detail}`
114
+ }
115
+
105
116
  export function makeProviders(deps, req) {
106
117
  const { resolveKey, fetchImpl, cfg } = deps
107
118
  const { bytes, mime, lang, signal, models } = req
@@ -122,7 +133,7 @@ export function makeProviders(deps, req) {
122
133
  body: bytes,
123
134
  signal,
124
135
  })
125
- if (!res.ok) throw new Error(`Deepgram HTTP ${res.status}`)
136
+ if (!res.ok) throw new Error(await readErrorDetail(res, 'Deepgram'))
126
137
  const data = await res.json()
127
138
  const text = (data?.results?.channels?.[0]?.alternatives?.[0]?.transcript || '').trim()
128
139
  return { ok: text.length > 0, provider: 'deepgram', text, reason: text ? '' : 'empty transcript' }
@@ -142,7 +153,7 @@ export function makeProviders(deps, req) {
142
153
  body: form,
143
154
  signal,
144
155
  })
145
- if (!res.ok) throw new Error(`Groq HTTP ${res.status}`)
156
+ if (!res.ok) throw new Error(await readErrorDetail(res, 'Groq'))
146
157
  const data = await res.json()
147
158
  const text = (data?.text || '').trim()
148
159
  return { ok: text.length > 0, provider: 'groq', text, reason: text ? '' : 'empty transcript' }
@@ -158,7 +169,7 @@ export function makeProviders(deps, req) {
158
169
  body: bytes,
159
170
  signal,
160
171
  })
161
- if (!res.ok) throw new Error(`HF HTTP ${res.status}`)
172
+ if (!res.ok) throw new Error(await readErrorDetail(res, 'HF'))
162
173
  const data = await res.json()
163
174
  const text = (data?.text || '').trim()
164
175
  return { ok: text.length > 0, provider: 'hf', text, reason: text ? '' : 'empty transcript' }
@@ -286,7 +297,7 @@ export function makeProviders(deps, req) {
286
297
  const res = await fetchImpl(`${base}/audio/transcriptions`, {
287
298
  method: 'POST', headers, body: form, signal,
288
299
  })
289
- if (!res.ok) throw new Error(`${label} HTTP ${res.status}`)
300
+ if (!res.ok) throw new Error(await readErrorDetail(res, label))
290
301
  const data = await res.json()
291
302
  return (data?.text || '').trim()
292
303
  }
@@ -319,7 +330,7 @@ export function makeProviders(deps, req) {
319
330
  }),
320
331
  signal,
321
332
  })
322
- if (!res.ok) throw new Error(`${label} HTTP ${res.status}`)
333
+ if (!res.ok) throw new Error(await readErrorDetail(res, label))
323
334
  const data = await res.json()
324
335
  return String(data?.choices?.[0]?.message?.content || '').trim()
325
336
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goodandready/dsh-voice",
3
- "version": "0.8.19",
3
+ "version": "0.8.21",
4
4
  "description": "Voice input for DeepSeek Harness: dictation chunked by pauses and voice messages, each with its own provider fallback chain (Deepgram, Groq, HuggingFace, local whisper.cpp, plus any OpenAI-compatible API of your own).",
5
5
  "license": "MIT",
6
6
  "type": "module",