@goodandready/dsh-voice 0.7.3 → 0.8.0

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/README.md CHANGED
@@ -137,7 +137,9 @@ Put a normal provider after it: if the browser cannot do it, recording falls bac
137
137
 
138
138
  ## Configure (Web GUI)
139
139
 
140
- Settings → **Голос** (Voice) has four blocks:
140
+ Settings → **Plugins → Plugin settings → Voice** the plugin's own
141
+ collapsible card in the plugins tab; the sidebar keeps no separate row for it.
142
+ The card has four blocks:
141
143
 
142
144
  - **Dictation** — fallback chain (provider + optional model per row, order is
143
145
  the order of attempts), language, and the silence threshold that ends a
package/lib/client.js CHANGED
@@ -24,6 +24,9 @@ window.__ModuleLoader__.load({
24
24
  // на него же приходится откат, если перевода нет.
25
25
  const en = {
26
26
  'saveFailed': 'Some fields were not saved —',
27
+ 'cardHint': 'Dictation and voice messages: providers, chains, local whisper',
28
+ 'expand': 'Expand',
29
+ 'collapse': 'Collapse',
27
30
  'composerUnavailable': 'Composer unavailable',
28
31
  'keySpace': 'Space',
29
32
  'keyUnset': 'not set',
@@ -96,6 +99,9 @@ window.__ModuleLoader__.load({
96
99
  }
97
100
  const ru = {
98
101
  'saveFailed': 'Часть полей не сохранилась —',
102
+ 'cardHint': 'Диктовка и голосовые сообщения: провайдеры, цепочки, локальный whisper',
103
+ 'expand': 'Развернуть',
104
+ 'collapse': 'Свернуть',
99
105
  'composerUnavailable': 'Композер недоступен',
100
106
  'keySpace': 'Пробел',
101
107
  'keyUnset': 'не задана',
@@ -241,6 +247,8 @@ window.__ModuleLoader__.load({
241
247
  React.createElement('path', { d: 'M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z' }),
242
248
  React.createElement('line', { x1: 12, y1: 9, x2: 12, y2: 13 }),
243
249
  React.createElement('line', { x1: 12, y1: 17, x2: 12.01, y2: 17 }))
250
+ const chevronIcon = () => React.createElement('svg', ic,
251
+ React.createElement('path', { d: 'M6 9l6 6 6-6' }))
244
252
 
245
253
  // ------------------------------------------------------------ transport
246
254
  function blobToBase64(blob) {
@@ -877,7 +885,15 @@ window.__ModuleLoader__.load({
877
885
  '.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}' +
878
886
  '.dvs-wait{font-size:13px;color:var(--dsw-alias-label-secondary);line-height:1.5;max-width:520px}' +
879
887
  '.dvs-ok{font-size:12px;color:var(--dsw-alias-state-success-primary)}' +
880
- '.dvs-bad{font-size:12px;color:var(--dsw-alias-state-error-primary)}'
888
+ '.dvs-bad{font-size:12px;color:var(--dsw-alias-state-error-primary)}' +
889
+ '.dvo-pcard{list-style:none;background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);border-radius:10px}' +
890
+ '.dvo-phead{display:flex;align-items:center;gap:8px;width:100%;padding:12px 14px;background:transparent;border:none;border-radius:10px;cursor:pointer;text-align:left;font:inherit;color:inherit}' +
891
+ '.dvo-pheadtext{display:flex;flex-direction:column;gap:2px;flex:1;min-width:0}' +
892
+ '.dvo-ptitle{font-size:14px;font-weight:600;color:var(--dsw-alias-label-primary)}' +
893
+ '.dvo-pdesc{font-size:12px;color:var(--dsw-alias-label-secondary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}' +
894
+ '.dvo-pchev{flex:none;display:flex;color:var(--dsw-alias-label-secondary);transition:transform .15s ease}' +
895
+ '.dvo-pcardOpen .dvo-pchev{transform:rotate(180deg)}' +
896
+ '.dvo-pbody{border-top:1px solid var(--dsw-alias-border-l1);padding:12px 14px}'
881
897
  const setCssId = 'dsh-voice/settings.module.css'
882
898
  if (typeof document !== 'undefined' && !document.querySelector('style[data-plugin-css="' + setCssId + '"]')) {
883
899
  const tag = document.createElement('style')
@@ -1210,13 +1226,59 @@ window.__ModuleLoader__.load({
1210
1226
  )
1211
1227
  }
1212
1228
 
1229
+ // Карточка во вкладке «Настройки плагинов» (#18): ядро даёт только рамку
1230
+ // списка, поэтому заголовок, пояснение и сворачивание — наши.
1231
+ // Тело монтируется при первом раскрытии: снапшот настроек тогда и придёт.
1232
+ function PluginCard(props) {
1233
+ const [open, setOpen] = React.useState(false)
1234
+ const tt = (props && props.t) || t
1235
+ const title = tt('title')
1236
+ return React.createElement('li',
1237
+ { className: open ? 'dvo-pcard dvo-pcardOpen' : 'dvo-pcard' },
1238
+ React.createElement('button',
1239
+ {
1240
+ type: 'button', className: 'dvo-phead',
1241
+ 'aria-expanded': open ? 'true' : 'false',
1242
+ 'aria-label': (open ? tt('collapse') : tt('expand')) + ': ' + title,
1243
+ onClick: () => setOpen((v) => !v),
1244
+ },
1245
+ React.createElement('span', { className: 'dvo-pheadtext' },
1246
+ React.createElement('span', { className: 'dvo-ptitle' }, title),
1247
+ React.createElement('span', { className: 'dvo-pdesc' }, tt('cardHint')),
1248
+ ),
1249
+ React.createElement('span', { className: 'dvo-pchev' }, chevronIcon()),
1250
+ ),
1251
+ open ? React.createElement('div', { className: 'dvo-pbody' }, React.createElement(VoiceSection, props)) : null,
1252
+ )
1253
+ }
1254
+
1213
1255
  function registerSettings(ctx) {
1256
+ // Слот объявлен пакетом настроек ядра; вкладка перебирает пространства
1257
+ // настроек, поэтому ключ регистрации обязан равняться NS, не id пакета:
1258
+ // не равен — карточка не появится вовсе, молча.
1259
+ const tryPluginItem = () => {
1260
+ try {
1261
+ ctx.slots.inject('settings.plugin.item', () => ctx.slots.register(
1262
+ {
1263
+ name: 'settings.plugin.item',
1264
+ key: NS,
1265
+ // locale в записи слота — то, из-за чего компонент получает props.t.
1266
+ locale: NS,
1267
+ inject: () => ({ ctx: ctx }),
1268
+ },
1269
+ PluginCard,
1270
+ ))
1271
+ return true
1272
+ } catch (e) { return false }
1273
+ }
1274
+ if (tryPluginItem()) return
1275
+ // Запасной путь: в этой сборке слота нет — остаёмся боковым
1276
+ // разделом, чтобы настройки не пропали.
1214
1277
  ctx.slots.inject('settings.section', () => ctx.slots.register(
1215
1278
  {
1216
1279
  name: 'settings.section',
1217
1280
  id: '@goodandready/dsh-voice',
1218
1281
  order: 30,
1219
- // locale в записи слота — то, из-за чего компонент получает props.t.
1220
1282
  locale: NS,
1221
1283
  label: () => t('title'),
1222
1284
  inject: () => ({ ctx: ctx }),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goodandready/dsh-voice",
3
- "version": "0.7.3",
3
+ "version": "0.8.0",
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",