@goodandready/dsh-voice 0.4.0 → 0.4.1
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 +45 -7
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -425,6 +425,7 @@ window.__ModuleLoader__.load({
|
|
|
425
425
|
'.dvs-save{background:var(--dsw-alias-brand-primary);color:#fff;border:none;border-radius:6px;padding:7px 14px;font-size:13px;cursor:pointer}' +
|
|
426
426
|
'.dvs-card{display:flex;flex-direction:column;gap:6px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;padding:10px}' +
|
|
427
427
|
'.dvs-card input,.dvs-card select{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-primary);border-radius:6px;padding:6px 8px;font-size:13px}' +
|
|
428
|
+
'.dvs-wait{font-size:13px;color:var(--dsw-alias-label-secondary);line-height:1.5;max-width:520px}' +
|
|
428
429
|
'.dvs-ok{font-size:12px;color:var(--dsw-alias-state-success-primary)}' +
|
|
429
430
|
'.dvs-bad{font-size:12px;color:var(--dsw-alias-state-error-primary)}'
|
|
430
431
|
const setCssId = 'dsh-voice/settings.module.css'
|
|
@@ -541,19 +542,56 @@ window.__ModuleLoader__.load({
|
|
|
541
542
|
return () => { alive = false; off() }
|
|
542
543
|
}, [])
|
|
543
544
|
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
545
|
+
// Снимок приходит со статусом, и он важнее самого значения.
|
|
546
|
+
// loading — ответа хоста ещё нет;
|
|
547
|
+
// unavailable — хост ответил, но наш namespace ему пока неизвестен:
|
|
548
|
+
// так бывает, если страницу открыли в первые секунды
|
|
549
|
+
// после старта, пока плагины ещё регистрируются;
|
|
550
|
+
// ready — значения на месте.
|
|
551
|
+
// При unavailable поле writable берётся из документа и остаётся true,
|
|
552
|
+
// поэтому без проверки статуса карточка рисует пустую, но с виду рабочую
|
|
553
|
+
// форму — именно так этот баг и выглядел.
|
|
554
|
+
const ready = !!snap && snap.status === 'ready'
|
|
555
|
+
const value = ready && snap.value ? snap.value : {}
|
|
556
|
+
const writable = ready && snap.writable !== false
|
|
557
|
+
|
|
558
|
+
// Зеркало настроек в браузере перечитывается только на запись значения и
|
|
559
|
+
// на переподключение; появление namespace таким сигналом не считается.
|
|
560
|
+
// Значит само оно не починится — просим перечитать, пока не готово.
|
|
561
|
+
// Зеркало общее, так что это чинит и остальные разделы настроек.
|
|
562
|
+
React.useEffect(() => {
|
|
563
|
+
if (ready) return undefined
|
|
564
|
+
let tries = 0
|
|
565
|
+
const timer = setInterval(() => {
|
|
566
|
+
if (tries >= 15) { clearInterval(timer); return }
|
|
567
|
+
tries += 1
|
|
568
|
+
try { ctx.settingsScope.describe().load() } catch (e) { /* сервис ещё не поднялся */ }
|
|
569
|
+
}, 1000)
|
|
570
|
+
return () => clearInterval(timer)
|
|
571
|
+
}, [ready])
|
|
572
|
+
|
|
573
|
+
// Черновик сеем только из готового снимка. Раньше он заполнялся из
|
|
574
|
+
// первого пришедшего, и пустой замораживался навсегда: следующий снимок
|
|
575
|
+
// уже не пересевал его, и карточка оставалась пустой до перезагрузки.
|
|
576
|
+
React.useEffect(() => { if (ready && draft === null) setDraft(JSON.parse(JSON.stringify(value))) }, [ready, draft, value])
|
|
547
577
|
// Клиент должен знать порог VAD и окно отмены — они живут в тех же настройках.
|
|
548
578
|
React.useEffect(() => {
|
|
549
|
-
if (!
|
|
579
|
+
if (!ready) return
|
|
550
580
|
voice.settings = {
|
|
551
581
|
vadSilenceMs: Number(value && value.dictation && value.dictation.vadSilenceMs) || 700,
|
|
552
582
|
autoSendMs: Number(value && value.message && value.message.autoSendMs) || 4000,
|
|
553
583
|
}
|
|
554
|
-
}, [
|
|
555
|
-
|
|
556
|
-
if (!
|
|
584
|
+
}, [ready, value])
|
|
585
|
+
|
|
586
|
+
if (!ready) {
|
|
587
|
+
const waiting = !snap || snap.status === 'loading'
|
|
588
|
+
return React.createElement('div', { className: 'dvs-wrap' },
|
|
589
|
+
React.createElement('div', { className: 'dvs-wait' }, waiting
|
|
590
|
+
? 'Загрузка настроек…'
|
|
591
|
+
: 'Харнесс ещё не объявил настройки плагина. Если он только что перезапустился, '
|
|
592
|
+
+ 'раздел появится сам через несколько секунд.'),
|
|
593
|
+
)
|
|
594
|
+
}
|
|
557
595
|
|
|
558
596
|
const setIn = (mode, key, v) => setDraft((d) => {
|
|
559
597
|
const next = JSON.parse(JSON.stringify(d || {}))
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@goodandready/dsh-voice",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
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",
|