@goodandready/dsh-voice 0.8.15 → 0.8.17
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 +13 -27
- package/lib/index.js +4 -0
- package/lib/providers.js +9 -2
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -123,6 +123,8 @@ window.__ModuleLoader__.load({
|
|
|
123
123
|
'general': 'General',
|
|
124
124
|
'whisperEndpoint': 'Local whisper: endpoint',
|
|
125
125
|
'whisperEndpointHint': 'POST /inference of a whisper.cpp server',
|
|
126
|
+
'deepgramEndpoint': 'Deepgram: base URL',
|
|
127
|
+
'deepgramEndpointHint': 'Base URL for Deepgram or self-hosted deployment (default https://api.deepgram.com)',
|
|
126
128
|
'whisperBin': 'Local whisper: binary',
|
|
127
129
|
'whisperBinHint': 'used when autostart is on',
|
|
128
130
|
'whisperModel': 'Local whisper: model',
|
|
@@ -268,6 +270,8 @@ window.__ModuleLoader__.load({
|
|
|
268
270
|
'general': 'Общее',
|
|
269
271
|
'whisperEndpoint': 'Локальный whisper: endpoint',
|
|
270
272
|
'whisperEndpointHint': 'POST /inference сервера whisper.cpp',
|
|
273
|
+
'deepgramEndpoint': 'Deepgram: базовый URL',
|
|
274
|
+
'deepgramEndpointHint': 'Базовый адрес Deepgram или self-hosted развёртывания (по умолчанию https://api.deepgram.com)',
|
|
271
275
|
'whisperBin': 'Локальный whisper: бинарь',
|
|
272
276
|
'whisperBinHint': 'используется при автозапуске',
|
|
273
277
|
'whisperModel': 'Локальный whisper: модель',
|
|
@@ -1885,6 +1889,7 @@ window.__ModuleLoader__.load({
|
|
|
1885
1889
|
textField('whisperUrl', t('whisperEndpoint'), t('whisperEndpointHint')),
|
|
1886
1890
|
textField('whisperBin', t('whisperBin'), t('whisperBinHint')),
|
|
1887
1891
|
textField('whisperModel', t('whisperModel'), t('whisperBinHint')),
|
|
1892
|
+
textField('deepgramBaseUrl', t('deepgramEndpoint'), t('deepgramEndpointHint')),
|
|
1888
1893
|
React.createElement('label', { className: 'dvs-field' }, t('whisperAutostart'),
|
|
1889
1894
|
React.createElement('input', {
|
|
1890
1895
|
type: 'checkbox', checked: !!(draft && draft.autoStart), disabled: !writable,
|
|
@@ -2061,37 +2066,18 @@ window.__ModuleLoader__.load({
|
|
|
2061
2066
|
}
|
|
2062
2067
|
|
|
2063
2068
|
function registerSettings(ctx) {
|
|
2064
|
-
//
|
|
2065
|
-
//
|
|
2066
|
-
//
|
|
2067
|
-
|
|
2068
|
-
try {
|
|
2069
|
-
ctx.slots.inject('settings.plugin.item', () => ctx.slots.register(
|
|
2070
|
-
{
|
|
2071
|
-
name: 'settings.plugin.item',
|
|
2072
|
-
key: NS,
|
|
2073
|
-
// locale в записи слота — то, из-за чего компонент получает props.t.
|
|
2074
|
-
locale: NS,
|
|
2075
|
-
inject: () => ({ ctx: ctx }),
|
|
2076
|
-
},
|
|
2077
|
-
PluginCard,
|
|
2078
|
-
))
|
|
2079
|
-
return true
|
|
2080
|
-
} catch (e) { return false }
|
|
2081
|
-
}
|
|
2082
|
-
if (tryPluginItem()) return
|
|
2083
|
-
// Запасной путь: в этой сборке слота нет — остаёмся боковым
|
|
2084
|
-
// разделом, чтобы настройки не пропали.
|
|
2085
|
-
ctx.slots.inject('settings.section', () => ctx.slots.register(
|
|
2069
|
+
// Карточка настроек во вкладке «Настройки → Плагины → Настройки плагинов» (#18).
|
|
2070
|
+
// Ключ регистрации обязан равняться NS (пространству настроек), иначе
|
|
2071
|
+
// вкладка молча пропустит слот.
|
|
2072
|
+
ctx.slots.inject('settings.plugin.item', () => ctx.slots.register(
|
|
2086
2073
|
{
|
|
2087
|
-
name: 'settings.
|
|
2088
|
-
|
|
2089
|
-
|
|
2074
|
+
name: 'settings.plugin.item',
|
|
2075
|
+
key: NS,
|
|
2076
|
+
// locale в записи слота — то, из-за чего компонент получает props.t.
|
|
2090
2077
|
locale: NS,
|
|
2091
|
-
label: () => t('title'),
|
|
2092
2078
|
inject: () => ({ ctx: ctx }),
|
|
2093
2079
|
},
|
|
2094
|
-
|
|
2080
|
+
PluginCard,
|
|
2095
2081
|
))
|
|
2096
2082
|
}
|
|
2097
2083
|
|
package/lib/index.js
CHANGED
|
@@ -97,6 +97,9 @@ export const Config = z.object({
|
|
|
97
97
|
customProviders: z.array(CustomProvider).default([])
|
|
98
98
|
.description('Own recognition providers, usable in both chains next to the built-in ones.'),
|
|
99
99
|
deepgramKeyEnv: z.string().default('DEEPGRAM_API_KEY'),
|
|
100
|
+
deepgramBaseUrl: z.string().default('https://api.deepgram.com')
|
|
101
|
+
.description('Deepgram-compatible host. Point this at a private/self-hosted Deepgram deployment '
|
|
102
|
+
+ 'instead of the public api.deepgram.com endpoint.'),
|
|
100
103
|
groqKeyEnv: z.string().default('GROQ_API_KEY'),
|
|
101
104
|
hfTokenEnv: z.string().default('HF_TOKEN'),
|
|
102
105
|
whisperUrl: z.string().default('http://127.0.0.1:8001/inference'),
|
|
@@ -438,6 +441,7 @@ export function apply(ctx, baseConfig) {
|
|
|
438
441
|
contextGlossary: cfg.contextGlossary !== false,
|
|
439
442
|
sensevoiceUrl: cfg.sensevoiceUrl,
|
|
440
443
|
sensevoiceAutostart: !!cfg.sensevoiceAutostart,
|
|
444
|
+
deepgramBaseUrl: cfg.deepgramBaseUrl || 'https://api.deepgram.com',
|
|
441
445
|
realtimeStreaming: !!cfg.realtimeStreaming,
|
|
442
446
|
realtimeProvider: cfg.realtimeProvider || 'openai',
|
|
443
447
|
realtimeModel: cfg.realtimeModel || 'gpt-4o-realtime-preview',
|
package/lib/providers.js
CHANGED
|
@@ -116,7 +116,8 @@ export function makeProviders(deps, req) {
|
|
|
116
116
|
const key = await resolveKey(cfg.deepgramKeyEnv)
|
|
117
117
|
if (!key) return { ok: false, provider: 'deepgram', reason: `no ${cfg.deepgramKeyEnv}` }
|
|
118
118
|
const model = pickModel(models, 'deepgram')
|
|
119
|
-
const
|
|
119
|
+
const base = String(cfg.deepgramBaseUrl || 'https://api.deepgram.com').replace(/\/+$/, '')
|
|
120
|
+
const url = `${base}/v1/listen?model=${encodeURIComponent(model)}`
|
|
120
121
|
+ (!isAutoLang(lang) ? `&language=${encodeURIComponent(lang)}` : '') + '&smart_format=true'
|
|
121
122
|
const res = await fetchImpl(url, {
|
|
122
123
|
method: 'POST',
|
|
@@ -184,7 +185,13 @@ export function makeProviders(deps, req) {
|
|
|
184
185
|
}
|
|
185
186
|
const form = new FormData()
|
|
186
187
|
form.append('file', new Blob([sendBytes], { type: sendMime }), fileName(sendMime))
|
|
187
|
-
|
|
188
|
+
// Unlike OpenAI-compatible APIs, whisper.cpp inherits its server's default
|
|
189
|
+
// language when the form omits this field (normally `en`). Send `auto`
|
|
190
|
+
// explicitly so every request detects the spoken language.
|
|
191
|
+
form.append('language', isAutoLang(lang) ? 'auto' : lang)
|
|
192
|
+
// Also override a server started with --translate: this plugin always needs
|
|
193
|
+
// a transcript in the spoken language, never Whisper's English translation.
|
|
194
|
+
form.append('translate', 'false')
|
|
188
195
|
if (vocab) form.append('prompt', vocab)
|
|
189
196
|
form.append('response_format', 'json')
|
|
190
197
|
const res = await fetchImpl(cfg.whisperUrl, { method: 'POST', body: form, signal })
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@goodandready/dsh-voice",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.17",
|
|
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",
|