@goodandready/dsh-tts 0.3.21 → 0.3.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.js CHANGED
@@ -783,7 +783,32 @@ window.__ModuleLoader__.load({
783
783
  const [saved, setSaved] = React.useState(false)
784
784
  const [err, setErr] = React.useState('')
785
785
  const [integrations, setIntegrations] = React.useState({ voice: { installed: false }, messenger: { installed: false } })
786
- const writable = true
786
+ const ctx = props && props.ctx
787
+ const scope = (ctx && ((ctx.get && ctx.get('lanSettings')) || ctx.settingsScope))
788
+ ? ((ctx.get && ctx.get('lanSettings')) || ctx.settingsScope).bind({ namespace: NS })
789
+ : null
790
+ const [snap, setSnap] = React.useState(null)
791
+
792
+ React.useEffect(() => {
793
+ if (!scope) return undefined
794
+ let alive = true
795
+ const render = () => { if (alive && scope.getSnapshot) setSnap(scope.getSnapshot()) }
796
+ render()
797
+ if (scope.subscribe) {
798
+ const off = scope.subscribe(render)
799
+ return () => { alive = false; if (typeof off === 'function') off() }
800
+ }
801
+ return () => { alive = false }
802
+ }, [scope])
803
+
804
+ // Статус снимка настроек важнее самого значения:
805
+ // loading — ответа хоста ещё нет;
806
+ // unavailable — хост ответил, но пространство настроек пока не готово;
807
+ // ready — значения на месте.
808
+ // При unavailable поле writable берётся из документа и остаётся true,
809
+ // поэтому без проверки статуса карточка рисует пустую, но с виду рабочую форму.
810
+ const ready = !scope || (!!snap && snap.status === 'ready')
811
+ const writable = !scope ? true : (ready && snap.writable !== false)
787
812
 
788
813
  const applyPayload = (data) => {
789
814
  const cfg = data && data.config ? data.config : {}
@@ -1327,7 +1352,7 @@ window.__ModuleLoader__.load({
1327
1352
  ),
1328
1353
  ),
1329
1354
  open ? React.createElement('div', { className: 'dts-body' },
1330
- React.createElement(TtsSection, Object.assign({}, props, { compact: true })),
1355
+ React.createElement(TtsSection, Object.assign({}, props, { compact: true, ctx: props && props.ctx })),
1331
1356
  ) : null,
1332
1357
  )
1333
1358
  }
@@ -1438,19 +1463,24 @@ window.__ModuleLoader__.load({
1438
1463
  // Вкладка перебирает пространства настроек и ищет слот по entryKey,
1439
1464
  // равному имени пространства: ключ обязан равняться NS, иначе карточка
1440
1465
  // не появится молча, без единой ошибки в журнале.
1441
- let moved = false
1442
- try {
1443
- moved = !!ctx.slots.inject('settings.plugin.item', () => ctx.slots.register(
1444
- {
1445
- name: 'settings.plugin.item',
1446
- key: NS,
1447
- locale: NS,
1448
- inject: () => ({ ctx: ctx }),
1449
- },
1450
- TtsCard,
1451
- ))
1452
- } catch (noPluginItemSlot) { moved = false }
1453
- if (moved) return
1466
+ const tryPluginItem = () => {
1467
+ try {
1468
+ const res = ctx.slots.inject('settings.plugin.item', () => ctx.slots.register(
1469
+ {
1470
+ name: 'settings.plugin.item',
1471
+ key: NS,
1472
+ locale: NS,
1473
+ inject: () => ({ ctx: ctx }),
1474
+ },
1475
+ TtsCard,
1476
+ ))
1477
+ if (res === false) return false
1478
+ return true
1479
+ } catch (noPluginItemSlot) {
1480
+ return false
1481
+ }
1482
+ }
1483
+ if (tryPluginItem()) return
1454
1484
  // Запасной путь для сборок без settings.plugin.item: прежний раздел
1455
1485
  // в боковом списке, чтобы настройки не пропали.
1456
1486
  ctx.slots.inject('settings.section', () => ctx.slots.register(
@@ -1466,7 +1496,7 @@ window.__ModuleLoader__.load({
1466
1496
  ))
1467
1497
  }
1468
1498
 
1469
- exports.inject = ['slots', 'locale']
1499
+ exports.inject = ['slots', 'settingsScope', 'locale']
1470
1500
  exports.apply = function apply(ctx) {
1471
1501
  registerSettings(ctx)
1472
1502
  registerSpeaker(ctx)
package/lib/index.js CHANGED
@@ -20,7 +20,8 @@ import {
20
20
  stripSecretsFromConfig,
21
21
  } from './keys.js'
22
22
 
23
- export const name = 'dsh-tts'
23
+ // Scoped identity matching package.json and cordis.patch.yml
24
+ export const name = '@goodandready/dsh-tts'
24
25
  export const inject = ['tools', 'credentials', 'llm', 'webServer', 'settings']
25
26
 
26
27
  const NS = 'dsh-tts'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goodandready/dsh-tts",
3
- "version": "0.3.21",
3
+ "version": "0.3.22",
4
4
  "description": "Text-to-speech for DeepSeek Harness: speak agent replies in the Web UI with a provider fallback chain (OpenAI, ElevenLabs, Google, Azure, Groq, Deepgram, OpenRouter, Edge, Piper, eSpeak).",
5
5
  "license": "MIT",
6
6
  "type": "module",