@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.
Files changed (2) hide show
  1. package/lib/client.js +45 -7
  2. 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
- const value = snap && snap.value ? snap.value : {}
545
- const writable = snap ? snap.writable !== false : false
546
- React.useEffect(() => { if (snap && draft === null) setDraft(JSON.parse(JSON.stringify(value))) }, [snap, draft, value])
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 (!snap) return
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
- }, [snap])
555
-
556
- if (!snap) return React.createElement('div', { className: 'dvs-wrap' }, 'Загрузка…')
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.0",
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",