@ykurilov/agent-chat-voice-dialog 0.0.0-stage → 0.55.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.
Files changed (50) hide show
  1. package/CHANGELOG.md +800 -0
  2. package/LICENSE +21 -0
  3. package/README.md +346 -2
  4. package/dist/chunk-5TB3BXP7.js +1403 -0
  5. package/dist/chunk-5TB3BXP7.js.map +1 -0
  6. package/dist/chunk-FHOXXM2X.js +113 -0
  7. package/dist/chunk-FHOXXM2X.js.map +1 -0
  8. package/dist/chunk-HANKMYWW.js +364 -0
  9. package/dist/chunk-HANKMYWW.js.map +1 -0
  10. package/dist/hono.js +61 -0
  11. package/dist/hono.js.map +1 -0
  12. package/dist/index.js +1618 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/server.js +284 -0
  15. package/dist/server.js.map +1 -0
  16. package/dist/types/browser/barge-in-filter.d.ts +32 -0
  17. package/dist/types/browser/capture-worklet.d.ts +8 -0
  18. package/dist/types/browser/dialog-engine.d.ts +46 -0
  19. package/dist/types/browser/dialog-state.d.ts +39 -0
  20. package/dist/types/browser/filler-client.d.ts +22 -0
  21. package/dist/types/browser/filler-scheduler.d.ts +64 -0
  22. package/dist/types/browser/human-sounds.d.ts +34 -0
  23. package/dist/types/browser/latency-meter.d.ts +29 -0
  24. package/dist/types/browser/microphone-capture.d.ts +28 -0
  25. package/dist/types/browser/page-lifecycle.d.ts +19 -0
  26. package/dist/types/browser/speech-player.d.ts +40 -0
  27. package/dist/types/browser/spoken-text.d.ts +4 -0
  28. package/dist/types/browser/voice-tag-sounds.d.ts +27 -0
  29. package/dist/types/browser/voices.d.ts +20 -0
  30. package/dist/types/hono.d.ts +27 -0
  31. package/dist/types/index.d.ts +25 -0
  32. package/dist/types/protocol.d.ts +144 -0
  33. package/dist/types/server/dialog-relay.d.ts +138 -0
  34. package/dist/types/server/dialog-session.d.ts +97 -0
  35. package/dist/types/server/filler-routes.d.ts +17 -0
  36. package/dist/types/server/fillers.d.ts +42 -0
  37. package/dist/types/server/ogg-opus.d.ts +14 -0
  38. package/dist/types/server/pcm-level.d.ts +2 -0
  39. package/dist/types/server/scribe-sounds.d.ts +35 -0
  40. package/dist/types/server/sound-dedupe.d.ts +13 -0
  41. package/dist/types/server/sound-window.d.ts +32 -0
  42. package/dist/types/server/sounds-usage.d.ts +30 -0
  43. package/dist/types/server/speech-stream.d.ts +47 -0
  44. package/dist/types/server/speech-usage.d.ts +33 -0
  45. package/dist/types/server/voice-message.d.ts +44 -0
  46. package/dist/types/server/voices.d.ts +36 -0
  47. package/dist/types/server/window-budget.d.ts +12 -0
  48. package/dist/types/server.d.ts +25 -0
  49. package/dist/types/shared/spoken-text-core.d.ts +40 -0
  50. package/package.json +63 -3
package/CHANGELOG.md ADDED
@@ -0,0 +1,800 @@
1
+ # @ykurilov/agent-chat-voice-dialog
2
+
3
+ ## 0.55.0
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [51f7b38]
8
+ - Updated dependencies [cdc7dd7]
9
+ - @ykurilov/agent-chat-core@0.55.0
10
+ - @ykurilov/agent-chat-voice@0.55.0
11
+ - @ykurilov/agent-chat-react@0.55.0
12
+
13
+ ## 0.54.0
14
+
15
+ ### Patch Changes
16
+
17
+ - Updated dependencies [c8fb0dd]
18
+ - Updated dependencies [73d3aaa]
19
+ - Updated dependencies [fa90219]
20
+ - @ykurilov/agent-chat-react@0.54.0
21
+ - @ykurilov/agent-chat-core@0.54.0
22
+ - @ykurilov/agent-chat-voice@0.54.0
23
+
24
+ ## 0.53.0
25
+
26
+ ### Patch Changes
27
+
28
+ - Updated dependencies [b6a7786]
29
+ - @ykurilov/agent-chat-core@0.53.0
30
+ - @ykurilov/agent-chat-react@0.53.0
31
+ - @ykurilov/agent-chat-voice@0.53.0
32
+
33
+ ## 0.52.0
34
+
35
+ ### Patch Changes
36
+
37
+ - @ykurilov/agent-chat-core@0.52.0
38
+ - @ykurilov/agent-chat-react@0.52.0
39
+ - @ykurilov/agent-chat-voice@0.52.0
40
+
41
+ ## 0.51.0
42
+
43
+ ### Patch Changes
44
+
45
+ - Updated dependencies [41b1726]
46
+ - @ykurilov/agent-chat-core@0.51.0
47
+ - @ykurilov/agent-chat-voice@0.51.0
48
+ - @ykurilov/agent-chat-react@0.51.0
49
+
50
+ ## 0.50.0
51
+
52
+ ### Patch Changes
53
+
54
+ - @ykurilov/agent-chat-core@0.50.0
55
+ - @ykurilov/agent-chat-react@0.50.0
56
+ - @ykurilov/agent-chat-voice@0.50.0
57
+
58
+ ## 0.49.0
59
+
60
+ ### Patch Changes
61
+
62
+ - Updated dependencies [084cef7]
63
+ - @ykurilov/agent-chat-core@0.49.0
64
+ - @ykurilov/agent-chat-react@0.49.0
65
+ - @ykurilov/agent-chat-voice@0.49.0
66
+
67
+ ## 0.48.0
68
+
69
+ ### Patch Changes
70
+
71
+ - Updated dependencies [fa10d5a]
72
+ - @ykurilov/agent-chat-core@0.48.0
73
+ - @ykurilov/agent-chat-voice@0.48.0
74
+ - @ykurilov/agent-chat-react@0.48.0
75
+
76
+ ## 0.47.0
77
+
78
+ ### Patch Changes
79
+
80
+ - Updated dependencies [5a59c33]
81
+ - @ykurilov/agent-chat-core@0.47.0
82
+ - @ykurilov/agent-chat-voice@0.47.0
83
+ - @ykurilov/agent-chat-react@0.47.0
84
+
85
+ ## 0.46.2
86
+
87
+ ### Patch Changes
88
+
89
+ - Updated dependencies [3d0d2f2]
90
+ - @ykurilov/agent-chat-core@0.46.2
91
+ - @ykurilov/agent-chat-voice@0.46.2
92
+ - @ykurilov/agent-chat-react@0.46.2
93
+
94
+ ## 0.46.1
95
+
96
+ ### Patch Changes
97
+
98
+ - @ykurilov/agent-chat-core@0.46.1
99
+ - @ykurilov/agent-chat-react@0.46.1
100
+ - @ykurilov/agent-chat-voice@0.46.1
101
+
102
+ ## 0.46.0
103
+
104
+ ### Patch Changes
105
+
106
+ - Updated dependencies [56d7528]
107
+ - Updated dependencies [a1933fd]
108
+ - Updated dependencies [52cc67d]
109
+ - @ykurilov/agent-chat-core@0.46.0
110
+ - @ykurilov/agent-chat-react@0.46.0
111
+ - @ykurilov/agent-chat-voice@0.46.0
112
+
113
+ ## 0.45.0
114
+
115
+ ### Patch Changes
116
+
117
+ - Updated dependencies [eb74c58]
118
+ - Updated dependencies [ac9aede]
119
+ - @ykurilov/agent-chat-react@0.45.0
120
+ - @ykurilov/agent-chat-voice@0.45.0
121
+ - @ykurilov/agent-chat-core@0.45.0
122
+
123
+ ## 0.44.0
124
+
125
+ ### Patch Changes
126
+
127
+ - Updated dependencies [6a2b5d9]
128
+ - @ykurilov/agent-chat-core@0.44.0
129
+ - @ykurilov/agent-chat-react@0.44.0
130
+ - @ykurilov/agent-chat-voice@0.44.0
131
+
132
+ ## 0.43.0
133
+
134
+ ### Patch Changes
135
+
136
+ - Updated dependencies [763f4c5]
137
+ - @ykurilov/agent-chat-core@0.43.0
138
+ - @ykurilov/agent-chat-voice@0.43.0
139
+ - @ykurilov/agent-chat-react@0.43.0
140
+
141
+ ## 0.42.0
142
+
143
+ ### Patch Changes
144
+
145
+ - Updated dependencies [a385276]
146
+ - @ykurilov/agent-chat-core@0.42.0
147
+ - @ykurilov/agent-chat-react@0.42.0
148
+ - @ykurilov/agent-chat-voice@0.42.0
149
+
150
+ ## 0.41.0
151
+
152
+ ### Patch Changes
153
+
154
+ - Updated dependencies [9472fcb]
155
+ - @ykurilov/agent-chat-core@0.41.0
156
+ - @ykurilov/agent-chat-react@0.41.0
157
+ - @ykurilov/agent-chat-voice@0.41.0
158
+
159
+ ## 0.40.0
160
+
161
+ ### Patch Changes
162
+
163
+ - Updated dependencies [0e7aab3]
164
+ - @ykurilov/agent-chat-core@0.40.0
165
+ - @ykurilov/agent-chat-react@0.40.0
166
+ - @ykurilov/agent-chat-voice@0.40.0
167
+
168
+ ## 0.39.1
169
+
170
+ ### Patch Changes
171
+
172
+ - Updated dependencies [5c0f3af]
173
+ - @ykurilov/agent-chat-react@0.39.1
174
+ - @ykurilov/agent-chat-voice@0.39.1
175
+ - @ykurilov/agent-chat-core@0.39.1
176
+
177
+ ## 0.39.0
178
+
179
+ ### Patch Changes
180
+
181
+ - Updated dependencies [3b90429]
182
+ - @ykurilov/agent-chat-core@0.39.0
183
+ - @ykurilov/agent-chat-react@0.39.0
184
+ - @ykurilov/agent-chat-voice@0.39.0
185
+
186
+ ## 0.38.0
187
+
188
+ ### Patch Changes
189
+
190
+ - Updated dependencies [1cae504]
191
+ - Updated dependencies [4065a4a]
192
+ - @ykurilov/agent-chat-core@0.38.0
193
+ - @ykurilov/agent-chat-voice@0.38.0
194
+ - @ykurilov/agent-chat-react@0.38.0
195
+
196
+ ## 0.37.0
197
+
198
+ ### Patch Changes
199
+
200
+ - Updated dependencies [7f49d12]
201
+ - Updated dependencies [ea78982]
202
+ - @ykurilov/agent-chat-core@0.37.0
203
+ - @ykurilov/agent-chat-voice@0.37.0
204
+ - @ykurilov/agent-chat-react@0.37.0
205
+
206
+ ## 0.36.0
207
+
208
+ ### Patch Changes
209
+
210
+ - Updated dependencies [3487fb4]
211
+ - Updated dependencies [8c43b86]
212
+ - Updated dependencies [6f42418]
213
+ - Updated dependencies [5f13c74]
214
+ - @ykurilov/agent-chat-core@0.36.0
215
+ - @ykurilov/agent-chat-react@0.36.0
216
+ - @ykurilov/agent-chat-voice@0.36.0
217
+
218
+ ## 0.35.0
219
+
220
+ ### Patch Changes
221
+
222
+ - Updated dependencies [6ceee78]
223
+ - Updated dependencies [2382026]
224
+ - @ykurilov/agent-chat-react@0.35.0
225
+ - @ykurilov/agent-chat-core@0.35.0
226
+ - @ykurilov/agent-chat-voice@0.35.0
227
+
228
+ ## 0.34.0
229
+
230
+ ### Patch Changes
231
+
232
+ - Updated dependencies [d039ce4]
233
+ - @ykurilov/agent-chat-core@0.34.0
234
+ - @ykurilov/agent-chat-react@0.34.0
235
+ - @ykurilov/agent-chat-voice@0.34.0
236
+
237
+ ## 0.33.0
238
+
239
+ ### Patch Changes
240
+
241
+ - Updated dependencies [4a72339]
242
+ - @ykurilov/agent-chat-core@0.33.0
243
+ - @ykurilov/agent-chat-voice@0.33.0
244
+ - @ykurilov/agent-chat-react@0.33.0
245
+
246
+ ## 0.32.0
247
+
248
+ ### Patch Changes
249
+
250
+ - Updated dependencies [4087a22]
251
+ - Updated dependencies [71c32b7]
252
+ - Updated dependencies [cae13bf]
253
+ - Updated dependencies [a94bda9]
254
+ - Updated dependencies [4e44492]
255
+ - Updated dependencies [ac9b7d3]
256
+ - Updated dependencies [27f4b1e]
257
+ - @ykurilov/agent-chat-react@0.32.0
258
+ - @ykurilov/agent-chat-core@0.32.0
259
+ - @ykurilov/agent-chat-voice@0.32.0
260
+
261
+ ## 0.31.2
262
+
263
+ ### Patch Changes
264
+
265
+ - @ykurilov/agent-chat-core@0.31.2
266
+ - @ykurilov/agent-chat-react@0.31.2
267
+ - @ykurilov/agent-chat-voice@0.31.2
268
+
269
+ ## 0.31.1
270
+
271
+ ### Patch Changes
272
+
273
+ - @ykurilov/agent-chat-core@0.31.1
274
+ - @ykurilov/agent-chat-react@0.31.1
275
+ - @ykurilov/agent-chat-voice@0.31.1
276
+
277
+ ## 0.31.0
278
+
279
+ ### Patch Changes
280
+
281
+ - @ykurilov/agent-chat-core@0.31.0
282
+ - @ykurilov/agent-chat-react@0.31.0
283
+ - @ykurilov/agent-chat-voice@0.31.0
284
+
285
+ ## 0.30.0
286
+
287
+ ### Patch Changes
288
+
289
+ - @ykurilov/agent-chat-core@0.30.0
290
+ - @ykurilov/agent-chat-react@0.30.0
291
+ - @ykurilov/agent-chat-voice@0.30.0
292
+
293
+ ## 0.29.0
294
+
295
+ ### Patch Changes
296
+
297
+ - @ykurilov/agent-chat-core@0.29.0
298
+ - @ykurilov/agent-chat-react@0.29.0
299
+ - @ykurilov/agent-chat-voice@0.29.0
300
+
301
+ ## 0.28.0
302
+
303
+ ### Patch Changes
304
+
305
+ - Updated dependencies [11c3c97]
306
+ - Updated dependencies [d63ccaa]
307
+ - Updated dependencies [6a2f903]
308
+ - Updated dependencies [189cba9]
309
+ - @ykurilov/agent-chat-core@0.28.0
310
+ - @ykurilov/agent-chat-react@0.28.0
311
+ - @ykurilov/agent-chat-voice@0.28.0
312
+
313
+ ## 0.27.0
314
+
315
+ ### Patch Changes
316
+
317
+ - Updated dependencies [d8341b2]
318
+ - Updated dependencies [5e4ed28]
319
+ - Updated dependencies [e0bb519]
320
+ - @ykurilov/agent-chat-core@0.27.0
321
+ - @ykurilov/agent-chat-react@0.27.0
322
+ - @ykurilov/agent-chat-voice@0.27.0
323
+
324
+ ## 0.26.2
325
+
326
+ ### Patch Changes
327
+
328
+ - Updated dependencies [f24858a]
329
+ - @ykurilov/agent-chat-core@0.26.2
330
+ - @ykurilov/agent-chat-voice@0.26.2
331
+ - @ykurilov/agent-chat-react@0.26.2
332
+
333
+ ## 0.26.1
334
+
335
+ ### Patch Changes
336
+
337
+ - Updated dependencies [5b52515]
338
+ - @ykurilov/agent-chat-react@0.26.1
339
+ - @ykurilov/agent-chat-voice@0.26.1
340
+ - @ykurilov/agent-chat-core@0.26.1
341
+
342
+ ## 0.26.0
343
+
344
+ ### Patch Changes
345
+
346
+ - Updated dependencies [eb43e47]
347
+ - @ykurilov/agent-chat-core@0.26.0
348
+ - @ykurilov/agent-chat-voice@0.26.0
349
+ - @ykurilov/agent-chat-react@0.26.0
350
+
351
+ ## 0.25.0
352
+
353
+ ### Patch Changes
354
+
355
+ - Updated dependencies [99d426e]
356
+ - Updated dependencies [d8201f6]
357
+ - @ykurilov/agent-chat-core@0.25.0
358
+ - @ykurilov/agent-chat-voice@0.25.0
359
+ - @ykurilov/agent-chat-react@0.25.0
360
+
361
+ ## 0.24.0
362
+
363
+ ### Minor Changes
364
+
365
+ - 9b895cd: Ломает приложения: только исчерпывающие `switch` по видам ошибок сервера и событиям чата (новые значения) и код, который
366
+ сам читает ответ `resolveUser`. Без новых настроек поведение прежнее.
367
+
368
+ Агент внутри продукта: агент работает с объектами приложения — уроком, заказом, документом. Всё по желанию; без новых
369
+ настроек запрос к модели не меняется ни на байт. Подробно — `docs/in-product-agent.md`.
370
+
371
+ - **Проверка перед ходом.** `beforeTurn({ userId, chat, action, text? })` отказывает своими словами: 403 `turn_refused`
372
+ до любых записей и лимитов, на отправке, правке, повторе, переделке, подтверждении, виджете, служебных сообщениях, фоновой
373
+ задаче и в мессенджерах. `resolveUser` может вернуть `{ refused: { code, message, status? } }` → `access_refused` на всех
374
+ адресах чата, голоса, голосового режима (WebSocket 4401) и мессенджеров. React: `onTurnRefused`, текст отказа вместо «нет
375
+ связи», сообщение возвращается в поле. Ручная проверка — `service.assertTurnAllowed`.
376
+ - **Итог хода.** `afterTurn(turn)` после каждого хода с повторами и сроком (`afterTurnAttempts`, `afterTurnTimeoutMs`),
377
+ переживает перезапуск сервера. `TurnResult`: владелец и автор хода, текст, части, расход, действие, канал, объект,
378
+ сотрудник. События приложения `{ type, data? }` — из хука, из инструмента (`model.emitAppEvent`) и вне хода
379
+ (`service.publishAppEvent`); в React `appEvents` и `onAppEvent`, события переживают перезагрузку. Модели не уходят.
380
+ - **Чат объекта.** Ключ и данные объекта у чата, один чат на ключ у человека: `service.openSubjectChat`, на сервере
381
+ `subjectChats` (`POST …/subject`), в React `<AgentChat subject="lesson:42" />`. Данные объекта видят `beforeTurn`,
382
+ инструменты (`model.subject`) и `afterTurn`; в браузер и модели не уходят.
383
+ - **Приветствие.** `greeting: { text }` — первое сообщение от агента без вызова модели. Проверено на всех моделях каталога.
384
+ - **Лимит сообщений.** Окно лимитов с `limitMessages` вместо `limitUsd`, `exemptUsers` — люди без лимитов,
385
+ `onMessageThreshold` — пороги. Отказ — 429 с `unit: "messages"`.
386
+ - **Импорт старой переписки.** `service.importChat({ ownerId, chat, messages })` с датами и картинками
387
+ (`attachments.importFile`), без хода, памяти, расхода и лимитов.
388
+ - **Сотрудник проверяет чат человека.** Песочница с опцией `people`: админ видит чаты человека только на чтение и
389
+ проверяет ответы в копии у себя. Память человека в копии только читается, расход — на админа, человек ничего не видит.
390
+ Инструменты приложения получают `model.staff` и в копии в данные человека не пишут.
391
+ - **Свои кнопки у поля ввода.** `composerActions` с помощником `{ value, setValue, send, addFiles, busy, blocked, canSend }`.
392
+ Договор скина v19: `Composer.actions`; скин v18 работает без кнопок, Тандем готов.
393
+ - **Хранилища.** Миграции применяются сами: SQLite `0015`, PostgreSQL `0014` (ключ объекта, состояние хука итога).
394
+
395
+ ### Что может сломаться
396
+
397
+ - **Исчерпывающие `switch` по закрытым спискам.** Новые значения: вид ошибки сервера `turn_refused` и `access_refused`
398
+ (`HandlerErrorKind`), события чата `after-turn-failed` и `app-event` (`ChatEvent`), `unit` у отказа лимита. Добавьте ветки
399
+ и надписи.
400
+ - **Список чатов без чатов объектов.** `listChats` и `GET {basePath}` по умолчанию не показывают чаты с ключом объекта.
401
+ Касается только приложений, которые начнут ими пользоваться; показать — `chatList: { subjectChats: true }` или
402
+ `listChats(userId, { subjects: "include" })`.
403
+ - **Свой `resolveUser` в обёртках.** Тип ответа — `ResolvedUser` (`{ id } | { refused } | null`). Код, который сам вызывает
404
+ `resolveUser` и читает `.id`, сначала проверяет `"refused" in user`.
405
+ - **Своё хранилище.** Для новых возможностей нужны необязательные методы (`findChatBySubject`, `importChat`,
406
+ `setAfterTurnState`, `listPendingAfterTurn`); без них эти возможности при включении дают ошибку при старте, остальное
407
+ работает. `listChats(ownerId, options?)` получил второй параметр — чаты с ключом скрывать по умолчанию.
408
+ - **Свой `ChatService`** (заглушки в тестах) добавляет новые методы: `openSubjectChat`, `importChat`, `assertTurnAllowed`, `peekHistory`,
409
+ `publishAppEvent`.
410
+ - **Своя реализация `SpendingLimits`** может добавить `takeMessage` — без него сообщения не считаются.
411
+ - **`AgentChat`: `chatId` стал необязательным** — нужен ровно один из `chatId` и `subject`; ни одного или оба — ошибка при
412
+ рендере. При смене `chatId` чат пересоздаётся: черновик и состояние прошлого чата не переносятся.
413
+ - **Окна лимитов: `limitUsd` стал необязательным** (у окна сообщений его нет). Код, который читает свои окна, проверяет
414
+ `limitMessages`.
415
+ - **Отказ сервера в React** (`ServerRefusal`) получил `kind` и `code`. 401 со словами приложения (`access_refused`) — это
416
+ отказ, а не «вход истёк».
417
+ - **«Пустой чат»** для «Нового чата»: чат объекта пустым не считается, обычный чат с одним приветствием — считается.
418
+ - Новый подпуть `@ykurilov/agent-chat-core/access` — помощники отказа в доступе для своих обработчиков.
419
+
420
+ ### Как обновить приложение
421
+
422
+ 1. `pnpm up "@ykurilov/agent-chat-*@^0.24.0"`. Миграции базы применяются сами при открытии хранилища.
423
+ 2. Исчерпывающие `switch` по `HandlerErrorKind` (сервер) и `ChatEvent` (`chatEvents` ядра): найдите их поиском и добавьте
424
+ ветки `turn_refused`, `access_refused`, `after-turn-failed`, `app-event`. Обязательных надписей не прибавилось: текст
425
+ отказа приходит с сервера. Свой словарь для лимита сообщений — необязательные `spendingMessagesLeft`,
426
+ `spendingMessagesExhausted`, `editMessageLimit`.
427
+
428
+ Было: `switch (event.type) { case "tasks-changed": … case "notice-added": … default: assertNever(event) }`
429
+ Стало: те же ветки плюс `case "after-turn-failed": case "app-event": break;`
430
+ 3. Свой код, который сам зовёт `resolveUser` и читает `.id`: сначала `if (user && "refused" in user) …`.
431
+ 4. Ничего больше не нужно, если новые возможности не включать. Чтобы включить — `docs/in-product-agent.md`.
432
+ 5. Свой скин: кнопки у поля появятся, когда `Composer` начнёт рисовать `actions` (договор v19, `docs/skin-v19.md`).
433
+ 6. Проверка: `pnpm typecheck` без ошибок, чат открывается и отвечает как раньше.
434
+
435
+ ### Patch Changes
436
+
437
+ - Updated dependencies [9b895cd]
438
+ - @ykurilov/agent-chat-core@0.24.0
439
+ - @ykurilov/agent-chat-react@0.24.0
440
+ - @ykurilov/agent-chat-voice@0.24.0
441
+
442
+ ## 0.23.0
443
+
444
+ ### Patch Changes
445
+
446
+ - Updated dependencies [30fb729]
447
+ - @ykurilov/agent-chat-react@0.23.0
448
+ - @ykurilov/agent-chat-voice@0.23.0
449
+ - @ykurilov/agent-chat-core@0.23.0
450
+
451
+ ## 0.22.0
452
+
453
+ ### Patch Changes
454
+
455
+ - @ykurilov/agent-chat-core@0.22.0
456
+ - @ykurilov/agent-chat-react@0.22.0
457
+ - @ykurilov/agent-chat-voice@0.22.0
458
+
459
+ ## 0.21.0
460
+
461
+ ### Patch Changes
462
+
463
+ - Updated dependencies [7c3bcc4]
464
+ - @ykurilov/agent-chat-core@0.21.0
465
+ - @ykurilov/agent-chat-voice@0.21.0
466
+ - @ykurilov/agent-chat-react@0.21.0
467
+
468
+ ## 0.20.0
469
+
470
+ ### Minor Changes
471
+
472
+ - fd16b01: Голосовые ответы для мессенджеров: `createVoiceReplies` из `@ykurilov/agent-chat-voice-dialog/server` озвучивает готовый ответ (ElevenLabs) в файл `audio/ogg`. Расход пишется как `speech` и входит в лимиты. Ответ примерно в 438 знаков на `eleven_v4_turbo` — около 30 секунд речи и ≈ $0,048. Настройки и цена — в README пакета.
473
+
474
+ Что сделать в приложении: ничего. Голосовой режим в браузере работает как раньше.
475
+
476
+ ### Patch Changes
477
+
478
+ - Updated dependencies [fd16b01]
479
+ - Updated dependencies [fd16b01]
480
+ - Updated dependencies [fd16b01]
481
+ - @ykurilov/agent-chat-core@0.20.0
482
+ - @ykurilov/agent-chat-voice@0.20.0
483
+ - @ykurilov/agent-chat-react@0.20.0
484
+
485
+ ## 0.19.0
486
+
487
+ ### Patch Changes
488
+
489
+ - Updated dependencies [fde2297]
490
+ - Updated dependencies [aa0fd51]
491
+ - Updated dependencies [6f26b93]
492
+ - Updated dependencies [9f94dbe]
493
+ - Updated dependencies [2013f15]
494
+ - Updated dependencies [aa0fd51]
495
+ - Updated dependencies [05e258b]
496
+ - Updated dependencies [aa0fd51]
497
+ - @ykurilov/agent-chat-core@0.19.0
498
+ - @ykurilov/agent-chat-react@0.19.0
499
+ - @ykurilov/agent-chat-voice@0.19.0
500
+
501
+ ## 0.18.6
502
+
503
+ ### Patch Changes
504
+
505
+ - @ykurilov/agent-chat-core@0.18.6
506
+ - @ykurilov/agent-chat-react@0.18.6
507
+ - @ykurilov/agent-chat-voice@0.18.6
508
+
509
+ ## 0.18.5
510
+
511
+ ### Patch Changes
512
+
513
+ - Updated dependencies [56b9ab6]
514
+ - @ykurilov/agent-chat-react@0.18.5
515
+ - @ykurilov/agent-chat-voice@0.18.5
516
+ - @ykurilov/agent-chat-core@0.18.5
517
+
518
+ ## 0.18.4
519
+
520
+ ### Patch Changes
521
+
522
+ - @ykurilov/agent-chat-core@0.18.4
523
+ - @ykurilov/agent-chat-react@0.18.4
524
+ - @ykurilov/agent-chat-voice@0.18.4
525
+
526
+ ## 0.18.3
527
+
528
+ ### Patch Changes
529
+
530
+ - Updated dependencies [ce3c26f]
531
+ - @ykurilov/agent-chat-react@0.18.3
532
+ - @ykurilov/agent-chat-voice@0.18.3
533
+ - @ykurilov/agent-chat-core@0.18.3
534
+
535
+ ## 0.18.2
536
+
537
+ ### Patch Changes
538
+
539
+ - Updated dependencies [7e7e966]
540
+ - @ykurilov/agent-chat-react@0.18.2
541
+ - @ykurilov/agent-chat-voice@0.18.2
542
+ - @ykurilov/agent-chat-core@0.18.2
543
+
544
+ ## 0.18.1
545
+
546
+ ### Patch Changes
547
+
548
+ - Updated dependencies [179ad9d]
549
+ - @ykurilov/agent-chat-react@0.18.1
550
+ - @ykurilov/agent-chat-voice@0.18.1
551
+ - @ykurilov/agent-chat-core@0.18.1
552
+
553
+ ## 0.18.0
554
+
555
+ ### Patch Changes
556
+
557
+ - Updated dependencies [43d7ebe]
558
+ - @ykurilov/agent-chat-core@0.18.0
559
+ - @ykurilov/agent-chat-react@0.18.0
560
+ - @ykurilov/agent-chat-voice@0.18.0
561
+
562
+ ## 0.17.0
563
+
564
+ ### Patch Changes
565
+
566
+ - Updated dependencies [e5d0860]
567
+ - @ykurilov/agent-chat-react@0.17.0
568
+ - @ykurilov/agent-chat-voice@0.17.0
569
+ - @ykurilov/agent-chat-core@0.17.0
570
+
571
+ ## 0.16.0
572
+
573
+ ### Minor Changes
574
+
575
+ - cf52f10: **Ломает только исчерпывающие проверки:** у `UsageSource` появилось значение `images`, у видов ошибок сервера — `widget_not_pending` и `invalid_answer`, у `ChatService` — метод `answerWidget`. Своё хранилище должно поддержать условную запись `AwaitingMessagePatch.expectedParts` (при несовпадении частей — `MessageNotAwaitingError`; помощник `sameMessageParts` из core), иначе две копии сервера могут затереть ответы друг друга; общие тесты хранилищ это проверяют. Остальное необязательно, приложение без правок работает как раньше.
576
+
577
+ Что нового: агент может спросить кнопками, звёздами или формой (виджеты), нарисовать схему блоком ` ```mermaid ` и создать картинки через Runware. Всё включается отдельно:
578
+
579
+ - виджеты: `agent: { widgets: { basic: true, custom: [свойВиджет] } }`, свой виджет — `defineWidget` из core и компонент в `widgets={{ … }}` у `AgentChat`; ответ человека идёт на `POST /:chatId/widgets/:toolCallId`, ход ждёт со статусом `awaiting_approval`;
580
+ - схемы: новый пакет `@ykurilov/agent-chat-diagrams`, `agent: { diagrams: true }` на сервере и `diagrams={diagramsClient}` на странице;
581
+ - картинки: новый пакет `@ykurilov/agent-chat-images` (нужен пакет вложений и `RUNWARE_API_KEY`), `images.tools(model)` в `agent.tools`, `images={imagesClient}` на странице; свой срок ожидания (210 с) инструмент сообщает ядру сам (`declareToolTimeout`), расход бронируется до заказа (`assertWithinLimit({ pendingUsd })`);
582
+ - окно просмотра картинок и схем: Тандем готов, своему скину — необязательные части договора версии 13 (`Widget`, `SuggestedReplies`, `GeneratedImages`, `MediaViewer`, `diagramColors`, `renderDiagram`). `splitMermaidBlocks` экспортируется из react;
583
+ - вложения: `Attachments.storage` и `detectFileKind` экспортируются из пакета вложений;
584
+ - голосовой режим произносит вопрос и варианты ждущего виджета и говорит «схема на экране» вместо блока схемы;
585
+ - «Стоп» на экране закрывает висящие вызовы так же, как сервер, разрешённые без результата — «результат неизвестен» (`stoppedToolCallReasons.resultUnknown`);
586
+ - упавший свой виджет страницы заменяется запасным видом скина, лента цела.
587
+
588
+ Подробно: `docs/widgets.md`, `docs/diagrams.md`, `docs/images.md`, `docs/media-viewer.md`.
589
+
590
+ ### Как обновить приложение
591
+
592
+ Обычному приложению на SQLite или PostgreSQL из набора делать ничего не нужно: миграций нет, всё новое включается отдельно.
593
+
594
+ 1. Исчерпывающий `switch` по `UsageSource` — добавьте ветку `"images"`; по видам ошибок сервера — `"widget_not_pending"` и `"invalid_answer"`.
595
+ 2. Своя реализация `ChatService` — добавьте метод `answerWidget({ chatId, ownerId, toolCallId, answer, page }): Promise<{ resumed: boolean }>` (тип `WidgetAnswerRequest` из core, образец — служба из core).
596
+ 3. Своё хранилище: `updateAwaitingMessage` получает необязательное поле `expectedParts`. Если оно есть и части сообщения в базе с ним не совпадают (`sameMessageParts` из core), бросайте `MessageNotAwaitingError`; проверку и запись делайте в одной транзакции. Прогоните общие тесты хранилищ из core.
597
+ 4. Своя обёртка `assertWithinLimit` из limits — пробрасывайте новое необязательное поле `pendingUsd`.
598
+ 5. Проверка: `pnpm typecheck`, затем в чате отправить сообщение и получить ответ.
599
+
600
+ ### Patch Changes
601
+
602
+ - Updated dependencies [cf52f10]
603
+ - @ykurilov/agent-chat-core@0.16.0
604
+ - @ykurilov/agent-chat-react@0.16.0
605
+ - @ykurilov/agent-chat-voice@0.16.0
606
+
607
+ ## 0.15.0
608
+
609
+ ### Minor Changes
610
+
611
+ - f05ad23: Встроенные провайдеры (OpenRouter, DeepSeek, Fireworks, Together) можно подключить через прокси: свой адрес `baseURL`
612
+ и заголовки `headers` к каждому запросу. Нужно серверу в России, откуда зарубежные провайдеры напрямую недоступны.
613
+ Через прокси идёт всё: ход агента, фоновые вызовы памяти и сжатия, сверка расхода OpenRouter. Меню моделей, цены и учёт
614
+ расходов те же. Значения заголовков вычищаются из ошибок и журналов, как ключи.
615
+
616
+ Новое: правка каталога `extendCatalog(…, { connectProviders: { openrouter: { baseURL, headers } } })` (провайдер остаётся
617
+ на своём месте, с прежними настройками), фабрики `createDeepSeekProvider`, `createFireworksProvider`,
618
+ `createTogetherProvider`, у `createOpenRouterProvider` — `baseURL` и `headers`, тип `ProviderConnection`, поля
619
+ `connection` и `connect` у `ProviderDescription` (необязательные). Голос: `headers` у чистки текста
620
+ (`polish: { provider: "together", baseUrl, headers }`) и у звуков человека (`sounds: { baseUrl, headers }`).
621
+
622
+ ### Как обновить приложение
623
+
624
+ Ничего делать не нужно: без новых настроек запросы идут прямо к провайдерам, как раньше.
625
+
626
+ Чтобы пустить провайдера через прокси, в файле, где собирается каталог моделей (обычно рядом с `createChatHandler`):
627
+
628
+ ```ts
629
+ import { extendCatalog, standardCatalog } from "@ykurilov/agent-chat-core";
630
+
631
+ const catalog = extendCatalog(standardCatalog, {
632
+ connectProviders: {
633
+ openrouter: {
634
+ baseURL: "https://fr-api-route.yeycourses.com/openrouter/api/v1",
635
+ headers: { "X-Proxy-Token": process.env.PROXY_TOKEN! },
636
+ },
637
+ },
638
+ });
639
+
640
+ createChatHandler({ /* … */ catalog });
641
+ ```
642
+
643
+ Токен прокси — только в окружении сервера (`PROXY_TOKEN`), не в коде. Не задан `PROXY_TOKEN` — ошибка при старте
644
+ (у заголовка нет значения). Значение заголовка короче 8 знаков и заголовок `Authorization` — тоже ошибка при старте.
645
+ Прокси должен пробрасывать заголовок ответа `x-generation-id`, иначе расход OpenRouter останется оценкой. Проверка:
646
+ один ответ в чате приходит, в журнале прокси виден запрос.
647
+
648
+ ### Patch Changes
649
+
650
+ - Updated dependencies [f05ad23]
651
+ - Updated dependencies [f05ad23]
652
+ - @ykurilov/agent-chat-core@0.15.0
653
+ - @ykurilov/agent-chat-react@0.15.0
654
+ - @ykurilov/agent-chat-voice@0.15.0
655
+
656
+ ## 0.14.0
657
+
658
+ ### Minor Changes
659
+
660
+ - 96098be: Мелкие исправления (022). Символ с кодом ноль в первом сообщении больше не роняет отправку на Postgres: он выбрасывается из названия чата, из записей памяти и из сводки сжатия истории (иначе запись сжатия падала бы при каждой попытке); в самом тексте сообщения он лежит как раньше. Вложения отмечаются прикреплёнными до записи сообщения, а не после: если сервер упал между двумя шагами, чистка брошенных файлов не удалит их через сутки (файл, отмеченный зря, безвреден и уходит вместе с чатом). Во всех пакетах появилось поле `engines: { node: ">=22" }`; голосовой сервер (`createVoiceRelay`) и голосовой диалог (`createDialogRelay`) на Node 20 сразу при создании говорят понятной ошибкой, что нужен Node 22 (раньше падали при первом соединении; со своим `connectUpstream` проверки нет). В пакете вложений `react` и `@ykurilov/agent-chat-react` стали необязательными peer-зависимостями: серверу без экрана они больше не ставятся. Приложению, которое берёт `@ykurilov/agent-chat-attachments/react`, достаточно иметь их в проекте — для чата на экране они нужны и так; если они подтягивались только через вложения, добавьте их в зависимости приложения.
661
+ - f9b6162: Защита от запросов с чужих страниц. Браузер прикладывает куки человека и к запросу, который отправила чужая страница (обычная HTML-форма, WebSocket), поэтому раньше чужой сайт мог от имени человека записать «факт» в память, создать чат, начать ход или открыть голос. **Меняется поведение по умолчанию:** запрос, который меняет данные (не GET), с чужой страницы получает `403 { error: { kind: "forbidden_origin" } }` до входа и любых записей; подъём WebSocket голоса (`createVoiceRelay`, голосовой режим) проверяется так же, хотя это GET; временный ключ `createVoiceHandler` чужой странице не выдаётся; голосовой режим (`mountDialogRelay`) без `allowedOrigins` больше не пропускает чужие страницы. Свой сайт (`Sec-Fetch-Site: same-origin` или Origin совпадает с `Host` / `X-Forwarded-Host`) и запросы не из браузера проходят как раньше. Чат на чужом сайте, который шлёт запросы прямо оттуда (например, GetCourse), — новая настройка `allowedOrigins: ["https://school.getcourse.ru"]` у `createChatHandler`, `createVoiceRelay`, `createVoiceHandler` и `mountDialogRelay`; CORS и куки `SameSite=None; Secure` настраивает приложение. Неверная запись в списке — ошибка при создании. Отказ пишется в журнал один раз на адрес страницы. Ядро экспортирует `createRequestOriginCheck` и `isSafeMethod`. Ещё: тело запроса больше 1 МиБ сервер не дочитывает и отвечает `413 { error: { kind: "too_large" } }` (самое длинное сообщение, 100 000 знаков, проходит).
662
+ - 1b2f9f1: Фронт и API на разных адресах. `allowedOrigins` у `createChatHandler`, `createVoiceRelay`, `createVoiceHandler` и `mountDialogRelay` принимает шаблон поддоменов `https://*.example.com`: он пускает `app.example.com` и `a.b.example.com`, но не сам `example.com` и не `evil-example.com`; схема и порт должны совпасть, слишком широкий шаблон (`https://*.com`, `https://*.com.`) — ошибка при создании. Общие суффиксы вроде `*.co.uk` проверка не распознаёт: в шаблон вписывают свой домен. Отказ из-за того, что `Origin` не совпал с `Host` (старый браузер или `http://` за прокси, который подменил `Host`), журнал теперь называет прямо: «Origin не совпал с Host (…); за прокси передайте Host/X-Forwarded-Host» с готовыми строками для nginx. `onRefused` у `createRequestOriginCheck` получает `{ origin, reason, hosts? }` вместо строки; новые экспорты ядра — `originRefusalHint` и тип `OriginRefusal`. Клиент на 403 с `forbidden_origin` в теле показывает «Сервер чата не принимает сообщения с этой страницы» (у правки — только в редакторе), возвращает текст в поле и в режиме разработки пишет в консоль, какой адрес вписать в `allowedOrigins`; другой 403 (например, HTML-страница прокси) — обычный сбой. Новое: `ChatRefusal` и `ErrorNoticeKind` получили `forbidden_origin` (`ErrorNotice` скина может получить этот `kind`), причина отказа правки `forbidden_origin`.
663
+
664
+ **Изменение договора надписей:** в `ChatLabels` два новых обязательных ключа — `errors.forbidden_origin` и `editErrors.forbiddenOrigin`. Словарь на основе `{ ...russianLabels }` получает их сам; свой словарь целиком — дополните ими, иначе ошибка типов. Отдельного номера версии у договора надписей нет. Ещё: при отказе по месту хода (`too_many_turns`) или занятом чате файлы вложений больше не принимаются и не остаются ничьими; пока файлы принимаются, чат занят, и второе сообщение в него получает 409.
665
+ - 00965e1: Голосовой режим: когда модель долго молчит, размышляет или вызывает инструмент, голос говорит короткую фразу («Хмм…», «Дай-ка подумаю…», «Сейчас поищу в интернете.», «Дай-ка вспомню.», «Ещё чуть-чуть…»). Фраза не попадает в чат и не уходит модели, настоящий ответ встаёт сразу за ней, перебивание её глушит.
666
+
667
+ - Включено само, если у режима настроена озвучка. Выключить: `speech.fillerPhrases: false` на сервере или `fillers: false` у `createVoiceDialogEngine`. Свои фразы: `speech.fillerPhrases`; пороги и привязка инструментов к видам фраз: `fillers.settings`. Подробности и пороги по умолчанию — в README пакета, раздел «Заполнители».
668
+ - Если у вида одна фраза, она звучит и в следующих ходах; после инструмента без текста ответа «думает» взводится заново; список голосов не получен — фразы грузятся голосом из «готов».
669
+ - Новые маршруты рядом с остальными: `GET {path}/fillers` и `GET {path}/fillers/{id}`; `mountDialogRelay` подключает их сам.
670
+ - Звук фраз синтезируется один раз на голос и хранится в памяти сервера. Расход первого синтеза записывается как озвучка (`source: "speech"`) на человека, чей запрос его вызвал, и на его чат; умолчания стоят около 275 знаков на голос.
671
+ - В `react` у моста чата `DialogChatBridge` появился необязательный метод `subscribeAssistantActivity` (начало и конец размышления или вызова инструмента); `useVoiceDialog` его реализует.
672
+
673
+ Обновление ничего не требует: приложение с настроенной озвучкой начнёт говорить заполнители само. Если не нужны — добавьте `fillerPhrases: false` в `speech`. Приложение, которое написало свой мост чата, продолжает работать: заполнитель «молчит» работает без нового метода.
674
+ - 0e8e0ae: Голосовой режим: человек продолжил говорить, пока модель ещё думает, — вторая фраза дописывается к первой, а не уходит вторым сообщением. Ход останавливается, вместо прежнего сообщения уходит склеенное («Так. Дай-ка подумать.»), модель отвечает один раз; пустого оборванного ответа и отдельного «Так.» в чате нет.
675
+
676
+ - Склеивается, пока у хода нет ни текста, ни звука, ни начатого вызова инструмента (размышление и заполнитель не мешают). Текст или звук уже пошли, начат инструмент, сказано стоп-слово или два междометия — поведение прежнее: перебивание и отдельное сообщение. Подробности — в README пакета voice-dialog, раздел «Склейка фраз».
677
+ - Склейка идёт через правку последнего сообщения человека: старая фраза остаётся в базе, но обрывком склейки: переключателя веток у склеенного сообщения нет, пролистать на обрывок нельзя (если человек потом сам правит склеенное сообщение, появляется настоящая развилка без обрывков). Признак — часть `data-voice-mode` склеенного сообщения (`{ replaces: id }`), без миграции базы. Отметка голосового режима и подсказки режима сохраняются, кэш модели цел. Название чата, выведенное из заменённого сообщения, обновляется.
678
+ - `core`: `chatService.editMessage(userId, chatId, editedMessageId, message, options?)` принимает `{ voiceMode: true }`. `server`: `POST …/edit` принимает необязательное булево `voiceMode` (не булево — 400 `invalid`).
679
+ - `react`: у состояния чата появился `replaceLastVoiceMessage(text)`, у моста `DialogChatBridge` — необязательный `replaceLastMessage(text)`; `useVoiceDialog` его реализует.
680
+
681
+ Обновление ничего не требует: движок склеивает сам, если мост и сервер той же версии. Приложение со своим мостом чата без `replaceLastMessage` работает как раньше: новая фраза в ожидании ответа перебивает ход и уходит отдельным сообщением.
682
+ - 6b20d83: Голосовой режим («разговор»): человек говорит, слова сами уходят сообщением в чат, ответ агента звучит голосом, человека можно перебить. Новый пакет `@ykurilov/agent-chat-voice-dialog`: распознавание Soniox, озвучка ElevenLabs (голос по умолчанию «Профессиональный диктор для аудиокниг», модель `eleven_v4_turbo`), ключи только на сервере. Перебитый ответ остаётся в ленте с отметкой «Вы перебили: озвучено до «…»», она хранится и видна после перезагрузки. Расход на озвучку идёт в учёт и лимиты (`source: "speech"`). Человек выбирает голос в меню режима; выбор хранится на сервере.
683
+
684
+ Модель узнаёт о режиме двумя служебными пометками: одна при входе («ответы озвучиваются, отвечай коротко и разговорно»), одна при возврате к тексту («разговор снова текстом»). Они стоят в конце сообщения человека, где режим сменился, а не в каждом запросе. Сообщение из режима запоминается голосовым отметкой в самом сообщении (часть `data-voice-mode` в `parts`), поэтому миграции для этого нет, пометки выводятся из сохранённого и кэш модели цел. Тексты задают настройки агента `voiceModeHint` и `textModeNote` (есть умолчания).
685
+
686
+ Обновление ничего не ломает: без нового пакета чат работает как раньше. Диктовка в поле ввода (`@ykurilov/agent-chat-voice`) не меняется.
687
+
688
+ ### Как обновить приложение
689
+
690
+ Нужно, только если вы хотите голосовой режим.
691
+
692
+ 1. Поставьте пакет `@ykurilov/agent-chat-voice-dialog` той же версии, что и остальные пакеты SDK. Скин Тандем обновите вместе с SDK: договор скина теперь версии 10 (необязательный `dialog` у поля ввода, панель режима, меню голосов, отметка обрыва; свой скин может их не рисовать, тогда кнопки режима не будет).
693
+ 2. Сервер. Рядом с чатом подключите режим (нужен WebSocket; с Hono и `@hono/node-ws`):
694
+
695
+ ```ts
696
+ import { mountDialogRelay } from "@ykurilov/agent-chat-voice-dialog/hono";
697
+
698
+ mountDialogRelay(app, {
699
+ path: "/api/voice-dialog",
700
+ upgradeWebSocket,
701
+ storage,
702
+ resolveUser, // тот же вход, что у чата
703
+ spendingLimits, // по желанию
704
+ logError: (message) => console.error(message),
705
+ speech: {
706
+ voices: [{ id: "oE0n0S3wK5Mj9C62iehn", name: "Профессиональный диктор для аудиокниг" }],
707
+ defaultVoiceId: "oE0n0S3wK5Mj9C62iehn",
708
+ pricePerThousandChars: { eleven_v4_turbo: 0.11, eleven_v4: 0.22 }, // ваша цена, $ за 1000 знаков
709
+ },
710
+ });
711
+ ```
712
+
713
+ Ключи `ELEVENLABS_API_KEY` и `SONIOX_API_KEY` — в окружении сервера. Next.js: WebSocket нужен свой Node-сервер, см. README пакета (`createDialogRelay`).
714
+ 3. Браузер:
715
+
716
+ ```tsx
717
+ const voiceDialog = createVoiceDialogEngine({ basePath: "/api/voice-dialog" });
718
+ <AgentChat api="/api/chat" skin={tandemSkin} voiceDialog={voiceDialog} />
719
+ ```
720
+
721
+ 4. Настройки. Слова остановки и междометия по умолчанию только русские; для другого языка задайте `bargeIn.stopWords` и `bargeIn.ignoreWords` у движка и `language` на сервере. Строгая политика содержимого страницы: добавьте `worklet-src blob:`.
722
+ 5. Хранилище. SQLite получает миграцию 0008, PostgreSQL — 0007 (схема `agent_chat`) сами при открытии базы. Свой `ChatStorage`: добавьте необязательные методы `setVoiceCut`, `getVoiceChoice`, `setVoiceChoice` (без них отметка обрыва и выбор голоса живут только до перезагрузки) и значение `"speech"` в `UsageSource`, если учёт расхода у вас свой.
723
+ 6. Свой экран (не наш скин): части сообщения с типом `data-voice-mode` не рисуйте, показывайте только текстовые части.
724
+ 7. Проверка: `pnpm typecheck` проходит; в чате появилась кнопка режима, после нажатия виден статус «Слушаю», фраза уходит сообщением, ответ звучит.
725
+ - d12dcf3: Голосовой режим: звуки человека (смех, вздох, кашель…) доходят до модели.
726
+
727
+ - Звук с микрофона параллельно с Soniox уходит с нашего сервера в ElevenLabs Scribe (`scribe_v2`, `tag_audio_events`); слова Scribe не использует, ключ остаётся на сервере. Звук уходит кусками прямо во время фразы: каждые `sounds.chunkSeconds` (1,5 с) нового звука, с перекрытием `sounds.overlapSeconds` (0,5 с), на конце фразы — только хвост; повторы на перекрытии схлопываются. Тишина (тише `sounds.silenceRms`, 0,01) не отправляется. На конце фразы ждётся только хвост и ещё не вернувшиеся куски, не дольше `sounds.waitMs` (1000 мс, по замеру Scribe отвечает за 0,7–0,95 с): не успел — звуки приклеятся к следующей фразе. Куски не копятся в очередь (не больше двух запросов). Расход считается по фактически отправленным секундам, включая перекрытия. Фраза из одного смеха без слов ход модели не запускает.
728
+ - Звуки лежат в сообщении человека, в части `data-voice-mode` (`data: { sounds: ["laughter"] }`), уходят на сервер как `voiceSounds` вместе с `voiceMode` (значение не из закрытого списка — 400 `invalid`). Пометка для модели («были слышны его звуки: смех») выводится из сохранённого при сборке запроса: начало запроса от хода к ходу не меняется, кэш цел; склейка фраз сохраняет звуки обеих. На экране звуков нет. В пометке входа в режим появилось короткое правило про пометку звуков.
729
+ - Эхо: звук того же вида, пойманный, пока играл кусок озвучки агента с таким же звуком (тег «[laughs]», заполнитель, отдельное «Ха-ха!»), плюс короткий хвост на задержку микрофона (`soundEchoTailMs`, 0,6 с), звуком человека не считается; смех в ответ на шутку агента доходит.
730
+ - Ошибка или недоступность Scribe режим не ломает: разговор идёт без звуков, в журнал — предупреждение. Расход пишется записью `source: "sounds"` (`inputTokens` — секунды звука) и входит в лимиты расходов.
731
+ - Новое: `sounds` у `createDialogRelay` и `mountDialogRelay` (`pricePerHour` обязательна), `sendVoiceMessage(text, { sounds })` и `replaceLastVoiceMessage(text, { sounds })` (`react`, `DialogChatBridge.send/replaceLastMessage` получили `options`), `voiceSounds` у `SendMessageOptions` и в теле `…/messages`, `…/edit`, экспорты `core`: `VOICE_SOUNDS`, `isVoiceSound`, `uniqueVoiceSounds`, `voiceSoundsNote`, `soundsOfMessage`, `UsageSource` получил `"sounds"`; `react`: тип `VoiceSound`; `voice-dialog/server`: `createScribeSounds`, `createSoundsUsage`, `HUMAN_SOUND_KINDS`.
732
+
733
+ Как обновить приложение: ничего не требуется, пока `sounds` не задан. Чтобы включить, добавьте `sounds: { pricePerHour }` (цену Scribe берите из прайса ElevenLabs; v2 — 0,22 $ за час) в настройки режима; ключ тот же `ELEVENLABS_API_KEY`. Своё хранилище расходов должно принимать `source: "sounds"` (текстовое поле, миграций не нужно). Пометка входа в режим по умолчанию стала длиннее на одно правило: кэш модели у идущих голосовых чатов один раз промахнётся. Свой `agent.voiceModeHint` (строка) заменяет пометку входа целиком, правило про звуки в нём не появится, но пометка звуков у сообщений всё равно добавится.
734
+ - 366d785: Голосовой режим: свой набор тегов эмоций у каждого голоса.
735
+
736
+ - В описании голоса (`speech.voices[].tags`) можно задать `{ allowed, avoid? }`: какие теги голосу идут и какие нет. Модель получает список текущего голоса в пометке входа в режим. Голос без набора получает общий список, его пометка не меняется ни на байт.
737
+ - Голос человека сохраняется на его сообщении в части `data-voice-mode` (`data: { voice: id }`, без миграции базы). Если голос сменился посреди разговора, первое сообщение с новым голосом один раз получает пометку с его тегами; голоса с одинаковым списком пометки не получают. Пометки выводятся из сохранённых отметок: повтор ответа, правка, перезагрузка и возврат к тексту дают то же начало запроса, кэш модели цел.
738
+ - Новое: `agent.voices` у `createChatService` и `createChatHandler` (интерфейс `VoiceTagSource`), `speech.catalog` у `mountDialogRelay` и `createDialogRelay` (готовый каталог голосов вместо `voices` и `defaultVoiceId`), `VoiceCatalog.tagsOf`, экспорты `core`: `VoiceTagSet`, `VoiceTagSource`, `voiceModeHint`, `voiceChangeNote`, `assertVoiceTagSet`, `sameVoiceTagSet`, `voiceOfMessage`. Наборы проверяются при запуске по правилу тега с экрана; экрану в `GET …/voices` они не уходят.
739
+
740
+ Как обновить приложение: ничего не требуется, пока наборов нет. Чтобы задать наборы, создайте каталог `createVoiceCatalog({ voices, defaultVoiceId, storage })` и передайте его и чату (`agent.voices`), и режиму (`speech.catalog`); подробности — в README пакета, раздел «Свой набор тегов у каждого голоса». Если вы задавали свой `voiceModeHint` (строка), он по-прежнему заменяет пометку целиком, без пометок о тегах голоса.
741
+ - 946e5d8: Голосовой режим: теги эмоций и подачи голоса.
742
+
743
+ - Модель получает список тегов Eleven v4 («[laughs]», «[sighs]», «[whispers]», «[excited]» и других) и может ставить их в ответ; голос их отыгрывает, а на экране их нет: ни в тексте ответа, ни при копировании, ни в поиске по прошлым разговорам. Это касается только ответов голосовых ходов (сообщение человека с отметкой `data-voice-mode`): в текстовом режиме и в сводке сжатия скобки остаются как есть («[docs]», «[error]» там обычные слова). Обычные скобки («[1]», ссылки, чекбоксы, код) не трогаются. В истории для модели теги остаются, кэш цел.
744
+ - Одиночный тег больше не обрывает реплику: сервер не отправляет в озвучку текст без букв и цифр, а тег приклеивается к соседнему предложению; тег в конце ответа («Да. [laughs]») — к последнему.
745
+ - Смех и вздох агента в микрофоне не считаются перебиванием: звуки сверяются по шаблону («ха-ха-ха-ха», «ооох»), составные слова («Дай-ка») — по частям.
746
+ - Новые экспорты: `stripVoiceTags`, `splitVoiceTags` (`core` и `react`), `voiceAnswerIds` (`react`), `isVoiceMessage`, `VOICE_TAGS`, `DEFAULT_VOICE_MODE_HINT`, `DEFAULT_TEXT_MODE_NOTE` (`core`). `messageText` (`react`) и `searchableText` (`history-search`) получили параметр `{ voiceAnswer }`. `sendVoiceMessage` кладёт отметку `data-voice-mode` в сообщение сразу.
747
+
748
+ Как обновить приложение: ничего не требуется. Пометки по умолчанию обновятся сами; кэш модели у идущих голосовых чатов один раз промахнётся. Если вы задавали свои `voiceModeHint` и `textModeNote`, теги в них не появятся: добавьте их сами, если нужны. Свой скин, который сам выводит текст ответа, должен вырезать теги только у ответов голосовых ходов (`voiceAnswerIds`). Побочный эффект: в ответе голосового хода слово в скобках, похожее на тег («[Google]»), тоже не показывается.
749
+
750
+ ### Patch Changes
751
+
752
+ - 1402afe: Голосовой режим: исправления по ревью.
753
+
754
+ - Потолок знаков озвучки в минуту (`speech.maxCharsPerMinute`) теперь общий для всех вкладок человека, а не на каждое соединение. Следующая реплика ждёт записи расхода предыдущей, лимит её видит.
755
+ - Фразы, сказанные, пока останавливается прежний ответ, уходят одним сообщением и не пропадают.
756
+ - Конец и хвост перебитого ответа больше не закрывают и не озвучивают новую реплику. Голосовая отправка читает «занято» в момент вызова.
757
+ - Команды диктора не задерживают звук с микрофона и перебивание.
758
+ - Звук с микрофона ограничен реальным временем с запасом: больше — закрытие кодом 4413.
759
+ - Новая необязательная настройка `allowedOrigins` у `mountDialogRelay`: список страниц, которым можно открывать режим (чужая получает 403). Без неё всё как раньше; для сервера, доступного из браузера, рекомендуем задать.
760
+ - Новая необязательная настройка `recognition.context`: подсказка распознаванию (тема, термины, имена).
761
+ - Updated dependencies [4f33e85]
762
+ - Updated dependencies [15fbbcc]
763
+ - Updated dependencies [c09c1e2]
764
+ - Updated dependencies [41992d0]
765
+ - Updated dependencies [42d17cc]
766
+ - Updated dependencies [062ce36]
767
+ - Updated dependencies [5e99fb2]
768
+ - Updated dependencies [ecd63f8]
769
+ - Updated dependencies [656233a]
770
+ - Updated dependencies [96098be]
771
+ - Updated dependencies [b6f4855]
772
+ - Updated dependencies [278a718]
773
+ - Updated dependencies [c1581f4]
774
+ - Updated dependencies [213bcb3]
775
+ - Updated dependencies [927c02c]
776
+ - Updated dependencies [be77ee2]
777
+ - Updated dependencies [8b59096]
778
+ - Updated dependencies [7fbc105]
779
+ - Updated dependencies [84ad64f]
780
+ - Updated dependencies [5027963]
781
+ - Updated dependencies [c2769dd]
782
+ - Updated dependencies [0cdf102]
783
+ - Updated dependencies [ba16989]
784
+ - Updated dependencies [aba59fe]
785
+ - Updated dependencies [47a56ac]
786
+ - Updated dependencies [f9b6162]
787
+ - Updated dependencies [f9b6162]
788
+ - Updated dependencies [f9b6162]
789
+ - Updated dependencies [1b2f9f1]
790
+ - Updated dependencies [6335921]
791
+ - Updated dependencies [00965e1]
792
+ - Updated dependencies [0e8e0ae]
793
+ - Updated dependencies [6b20d83]
794
+ - Updated dependencies [1402afe]
795
+ - Updated dependencies [d12dcf3]
796
+ - Updated dependencies [366d785]
797
+ - Updated dependencies [946e5d8]
798
+ - @ykurilov/agent-chat-core@0.14.0
799
+ - @ykurilov/agent-chat-react@0.14.0
800
+ - @ykurilov/agent-chat-voice@0.14.0