@goodandready/dsh-voice 0.8.21 → 0.8.22
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-src/70-settings.js +9 -2
- package/lib/client.js +9 -2
- package/lib/providers.js +26 -6
- package/package.json +1 -1
|
@@ -274,7 +274,14 @@
|
|
|
274
274
|
return () => clearInterval(timer)
|
|
275
275
|
}, [ready])
|
|
276
276
|
|
|
277
|
-
|
|
277
|
+
const deepClone = (obj) => {
|
|
278
|
+
if (typeof structuredClone === 'function') {
|
|
279
|
+
try { return structuredClone(obj) } catch (e) { /* fallback */ }
|
|
280
|
+
}
|
|
281
|
+
try { return JSON.parse(JSON.stringify(obj)) } catch (e) { return Object.assign({}, obj) }
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
React.useEffect(() => { if (ready && draft === null) setDraft(deepClone(value)) }, [ready, draft, value])
|
|
278
285
|
|
|
279
286
|
React.useEffect(() => {
|
|
280
287
|
if (!ready) return
|
|
@@ -335,7 +342,7 @@
|
|
|
335
342
|
}
|
|
336
343
|
|
|
337
344
|
const setIn = (mode, key, v) => setDraft((d) => {
|
|
338
|
-
const next =
|
|
345
|
+
const next = deepClone(d || {})
|
|
339
346
|
next[mode] = next[mode] || {}
|
|
340
347
|
next[mode][key] = v
|
|
341
348
|
return next
|
package/lib/client.js
CHANGED
|
@@ -1606,7 +1606,14 @@ window.__ModuleLoader__.load({
|
|
|
1606
1606
|
return () => clearInterval(timer)
|
|
1607
1607
|
}, [ready])
|
|
1608
1608
|
|
|
1609
|
-
|
|
1609
|
+
const deepClone = (obj) => {
|
|
1610
|
+
if (typeof structuredClone === 'function') {
|
|
1611
|
+
try { return structuredClone(obj) } catch (e) { /* fallback */ }
|
|
1612
|
+
}
|
|
1613
|
+
try { return JSON.parse(JSON.stringify(obj)) } catch (e) { return Object.assign({}, obj) }
|
|
1614
|
+
}
|
|
1615
|
+
|
|
1616
|
+
React.useEffect(() => { if (ready && draft === null) setDraft(deepClone(value)) }, [ready, draft, value])
|
|
1610
1617
|
|
|
1611
1618
|
React.useEffect(() => {
|
|
1612
1619
|
if (!ready) return
|
|
@@ -1667,7 +1674,7 @@ window.__ModuleLoader__.load({
|
|
|
1667
1674
|
}
|
|
1668
1675
|
|
|
1669
1676
|
const setIn = (mode, key, v) => setDraft((d) => {
|
|
1670
|
-
const next =
|
|
1677
|
+
const next = deepClone(d || {})
|
|
1671
1678
|
next[mode] = next[mode] || {}
|
|
1672
1679
|
next[mode][key] = v
|
|
1673
1680
|
return next
|
package/lib/providers.js
CHANGED
|
@@ -113,6 +113,14 @@ async function readErrorDetail(res, defaultLabel) {
|
|
|
113
113
|
return `${defaultLabel} ${detail}`
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
+
async function safeJson(res, defaultLabel) {
|
|
117
|
+
try {
|
|
118
|
+
return await res.json()
|
|
119
|
+
} catch {
|
|
120
|
+
throw new Error(`${defaultLabel}: invalid JSON response`)
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
116
124
|
export function makeProviders(deps, req) {
|
|
117
125
|
const { resolveKey, fetchImpl, cfg } = deps
|
|
118
126
|
const { bytes, mime, lang, signal, models } = req
|
|
@@ -134,7 +142,10 @@ export function makeProviders(deps, req) {
|
|
|
134
142
|
signal,
|
|
135
143
|
})
|
|
136
144
|
if (!res.ok) throw new Error(await readErrorDetail(res, 'Deepgram'))
|
|
137
|
-
|
|
145
|
+
let data
|
|
146
|
+
try { data = await safeJson(res, 'Deepgram') } catch (e) {
|
|
147
|
+
return { ok: false, provider: 'deepgram', reason: e.message }
|
|
148
|
+
}
|
|
138
149
|
const text = (data?.results?.channels?.[0]?.alternatives?.[0]?.transcript || '').trim()
|
|
139
150
|
return { ok: text.length > 0, provider: 'deepgram', text, reason: text ? '' : 'empty transcript' }
|
|
140
151
|
}
|
|
@@ -154,7 +165,10 @@ export function makeProviders(deps, req) {
|
|
|
154
165
|
signal,
|
|
155
166
|
})
|
|
156
167
|
if (!res.ok) throw new Error(await readErrorDetail(res, 'Groq'))
|
|
157
|
-
|
|
168
|
+
let data
|
|
169
|
+
try { data = await safeJson(res, 'Groq') } catch (e) {
|
|
170
|
+
return { ok: false, provider: 'groq', reason: e.message }
|
|
171
|
+
}
|
|
158
172
|
const text = (data?.text || '').trim()
|
|
159
173
|
return { ok: text.length > 0, provider: 'groq', text, reason: text ? '' : 'empty transcript' }
|
|
160
174
|
}
|
|
@@ -170,7 +184,10 @@ export function makeProviders(deps, req) {
|
|
|
170
184
|
signal,
|
|
171
185
|
})
|
|
172
186
|
if (!res.ok) throw new Error(await readErrorDetail(res, 'HF'))
|
|
173
|
-
|
|
187
|
+
let data
|
|
188
|
+
try { data = await safeJson(res, 'HF') } catch (e) {
|
|
189
|
+
return { ok: false, provider: 'hf', reason: e.message }
|
|
190
|
+
}
|
|
174
191
|
const text = (data?.text || '').trim()
|
|
175
192
|
return { ok: text.length > 0, provider: 'hf', text, reason: text ? '' : 'empty transcript' }
|
|
176
193
|
}
|
|
@@ -210,7 +227,10 @@ export function makeProviders(deps, req) {
|
|
|
210
227
|
try { const e = await res.json(); if (e?.error) detail = e.error } catch { /* body is not json */ }
|
|
211
228
|
return { ok: false, provider: 'local-whisper', reason: `local whisper: ${detail}` }
|
|
212
229
|
}
|
|
213
|
-
|
|
230
|
+
let data
|
|
231
|
+
try { data = await safeJson(res, 'local whisper') } catch (e) {
|
|
232
|
+
return { ok: false, provider: 'local-whisper', reason: e.message }
|
|
233
|
+
}
|
|
214
234
|
const text = (data?.text || '').trim()
|
|
215
235
|
return { ok: text.length > 0, provider: 'local-whisper', text, reason: text ? '' : 'empty transcript' }
|
|
216
236
|
}
|
|
@@ -298,7 +318,7 @@ export function makeProviders(deps, req) {
|
|
|
298
318
|
method: 'POST', headers, body: form, signal,
|
|
299
319
|
})
|
|
300
320
|
if (!res.ok) throw new Error(await readErrorDetail(res, label))
|
|
301
|
-
const data = await res
|
|
321
|
+
const data = await safeJson(res, label)
|
|
302
322
|
return (data?.text || '').trim()
|
|
303
323
|
}
|
|
304
324
|
|
|
@@ -331,7 +351,7 @@ export function makeProviders(deps, req) {
|
|
|
331
351
|
signal,
|
|
332
352
|
})
|
|
333
353
|
if (!res.ok) throw new Error(await readErrorDetail(res, label))
|
|
334
|
-
const data = await res
|
|
354
|
+
const data = await safeJson(res, label)
|
|
335
355
|
return String(data?.choices?.[0]?.message?.content || '').trim()
|
|
336
356
|
}
|
|
337
357
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@goodandready/dsh-voice",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.22",
|
|
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",
|