@ykurilov/agent-chat-voice 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.
- package/CHANGELOG.md +610 -0
- package/LICENSE +21 -0
- package/README.md +298 -2
- package/dist/chunk-CAERXPTX.js +103 -0
- package/dist/chunk-CAERXPTX.js.map +1 -0
- package/dist/hono.js +45 -0
- package/dist/hono.js.map +1 -0
- package/dist/index.js +323 -0
- package/dist/index.js.map +1 -0
- package/dist/node.js +86 -0
- package/dist/node.js.map +1 -0
- package/dist/server.js +869 -0
- package/dist/server.js.map +1 -0
- package/dist/types/hono.d.ts +10 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/node.d.ts +30 -0
- package/dist/types/relay-close.d.ts +21 -0
- package/dist/types/request-session.d.ts +13 -0
- package/dist/types/server/access.d.ts +52 -0
- package/dist/types/server/language-hints.d.ts +5 -0
- package/dist/types/server/platform-websocket.d.ts +2 -0
- package/dist/types/server/polish.d.ts +73 -0
- package/dist/types/server/request-origin.d.ts +34 -0
- package/dist/types/server/soniox-session.d.ts +88 -0
- package/dist/types/server/temporary-key.d.ts +20 -0
- package/dist/types/server/transcribe-audio-file.d.ts +11 -0
- package/dist/types/server/voice-handler.d.ts +52 -0
- package/dist/types/server/voice-relay.d.ts +101 -0
- package/dist/types/server/voice-spending.d.ts +44 -0
- package/dist/types/server.d.ts +18 -0
- package/dist/types/soniox-messages.d.ts +74 -0
- package/dist/types/voice-errors.d.ts +20 -0
- package/dist/types/voice-input.d.ts +61 -0
- package/package.json +71 -3
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,610 @@
|
|
|
1
|
+
# @ykurilov/agent-chat-voice
|
|
2
|
+
|
|
3
|
+
## 0.55.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- cdc7dd7: Голос: расход в лимитах, причина отказа, Next.js, язык записи, предел из настройки.
|
|
8
|
+
|
|
9
|
+
- `UsageSource` открыт для своих видов приложения (`"font_download"` без приведения типа), штатные — в
|
|
10
|
+
`BUILT_IN_USAGE_SOURCES`, тип `BuiltInUsageSource`. Новые штатные виды `voice_input` (секунды распознавания,
|
|
11
|
+
`inputTokens` — секунды) и `voice_polish` (чистка текста). Миграций нет.
|
|
12
|
+
- `createVoiceRelay({ spending: { service, recognitionUsdPerHour, chatId? } })`: лимит до диктовки, секунды звука в журнал
|
|
13
|
+
расхода. Чистка: `polish: { askModel, model }` через службу чата; у Together — `pricing`; своя `clean` может вернуть
|
|
14
|
+
`{ text, usage }`. Расход чистки — вид `voice_polish`.
|
|
15
|
+
- Причина отказа доходит до браузера кодом закрытия (`RELAY_CLOSE`): 4401 не вошёл, 4402 лимит, 4403 нет доступа,
|
|
16
|
+
4413 слишком длинно, 4429 часто, 4502 недоступен, 1009 кусок больше предела. Отказ приложения `{ refused: { code } }`
|
|
17
|
+
переводится по `code`. Новые виды ошибок `limit`, `forbidden`, `too_long`; 4401 теперь `forbidden` (был
|
|
18
|
+
`service_unavailable`).
|
|
19
|
+
- `@ykurilov/agent-chat-voice/node`: `createVoiceUpgrade({ path, relay, maxFrameBytes })` — голос на своём HTTP-сервере
|
|
20
|
+
Node.js (Next.js custom server), `shareVoiceRelay` / `sharedVoiceRelay` — мостик внутри процесса. Нужен `ws`.
|
|
21
|
+
Кривой путь — 400, обрыв во время проверки входа не роняет процесс, `authorizeTimeoutMs` (10 с) — 503.
|
|
22
|
+
- Ретранслятор: `helloTimeoutMs` (10 с без приветствия — 4400, место свободно), `maxFrameBytes` (1 МиБ, 1009) — единый
|
|
23
|
+
для Hono и node. Чат расхода из `?chat=` — только свой (`service.assertOwnChat`), иначе `"voice"`.
|
|
24
|
+
`allowedLanguageHints` с регионом (`pt-BR`) разрешает язык `pt`. Относительный `relayUrl` снова работает.
|
|
25
|
+
- Язык каждой записи: `voice.start(listener, { chatId, language })`, `createVoiceInput({ languageHints })`; сервер
|
|
26
|
+
проверяет значение сам (`allowedLanguageHints`). `AgentChat` передаёт текущий чат и язык словаря.
|
|
27
|
+
- react: подпись `time_limit` — строка или функция от предела сервера («предел 3 минуты»); `onError(kind, details)`;
|
|
28
|
+
подписи `limit`, `forbidden`, `too_long` необязательные в своём словаре; `voiceErrorText`.
|
|
29
|
+
|
|
30
|
+
### Patch Changes
|
|
31
|
+
|
|
32
|
+
- Updated dependencies [51f7b38]
|
|
33
|
+
- Updated dependencies [cdc7dd7]
|
|
34
|
+
- @ykurilov/agent-chat-core@0.55.0
|
|
35
|
+
|
|
36
|
+
## 0.54.0
|
|
37
|
+
|
|
38
|
+
### Patch Changes
|
|
39
|
+
|
|
40
|
+
- Updated dependencies [fa90219]
|
|
41
|
+
- @ykurilov/agent-chat-core@0.54.0
|
|
42
|
+
|
|
43
|
+
## 0.53.0
|
|
44
|
+
|
|
45
|
+
### Patch Changes
|
|
46
|
+
|
|
47
|
+
- Updated dependencies [b6a7786]
|
|
48
|
+
- @ykurilov/agent-chat-core@0.53.0
|
|
49
|
+
|
|
50
|
+
## 0.52.0
|
|
51
|
+
|
|
52
|
+
### Patch Changes
|
|
53
|
+
|
|
54
|
+
- @ykurilov/agent-chat-core@0.52.0
|
|
55
|
+
|
|
56
|
+
## 0.51.0
|
|
57
|
+
|
|
58
|
+
### Patch Changes
|
|
59
|
+
|
|
60
|
+
- Updated dependencies [41b1726]
|
|
61
|
+
- @ykurilov/agent-chat-core@0.51.0
|
|
62
|
+
|
|
63
|
+
## 0.50.0
|
|
64
|
+
|
|
65
|
+
### Patch Changes
|
|
66
|
+
|
|
67
|
+
- @ykurilov/agent-chat-core@0.50.0
|
|
68
|
+
|
|
69
|
+
## 0.49.0
|
|
70
|
+
|
|
71
|
+
### Patch Changes
|
|
72
|
+
|
|
73
|
+
- Updated dependencies [084cef7]
|
|
74
|
+
- @ykurilov/agent-chat-core@0.49.0
|
|
75
|
+
|
|
76
|
+
## 0.48.0
|
|
77
|
+
|
|
78
|
+
### Patch Changes
|
|
79
|
+
|
|
80
|
+
- Updated dependencies [fa10d5a]
|
|
81
|
+
- @ykurilov/agent-chat-core@0.48.0
|
|
82
|
+
|
|
83
|
+
## 0.47.0
|
|
84
|
+
|
|
85
|
+
### Patch Changes
|
|
86
|
+
|
|
87
|
+
- Updated dependencies [5a59c33]
|
|
88
|
+
- @ykurilov/agent-chat-core@0.47.0
|
|
89
|
+
|
|
90
|
+
## 0.46.2
|
|
91
|
+
|
|
92
|
+
### Patch Changes
|
|
93
|
+
|
|
94
|
+
- Updated dependencies [3d0d2f2]
|
|
95
|
+
- @ykurilov/agent-chat-core@0.46.2
|
|
96
|
+
|
|
97
|
+
## 0.46.1
|
|
98
|
+
|
|
99
|
+
### Patch Changes
|
|
100
|
+
|
|
101
|
+
- @ykurilov/agent-chat-core@0.46.1
|
|
102
|
+
|
|
103
|
+
## 0.46.0
|
|
104
|
+
|
|
105
|
+
### Patch Changes
|
|
106
|
+
|
|
107
|
+
- Updated dependencies [56d7528]
|
|
108
|
+
- Updated dependencies [a1933fd]
|
|
109
|
+
- Updated dependencies [52cc67d]
|
|
110
|
+
- @ykurilov/agent-chat-core@0.46.0
|
|
111
|
+
|
|
112
|
+
## 0.45.0
|
|
113
|
+
|
|
114
|
+
### Patch Changes
|
|
115
|
+
|
|
116
|
+
- @ykurilov/agent-chat-core@0.45.0
|
|
117
|
+
|
|
118
|
+
## 0.44.0
|
|
119
|
+
|
|
120
|
+
### Patch Changes
|
|
121
|
+
|
|
122
|
+
- Updated dependencies [6a2b5d9]
|
|
123
|
+
- @ykurilov/agent-chat-core@0.44.0
|
|
124
|
+
|
|
125
|
+
## 0.43.0
|
|
126
|
+
|
|
127
|
+
### Patch Changes
|
|
128
|
+
|
|
129
|
+
- Updated dependencies [763f4c5]
|
|
130
|
+
- @ykurilov/agent-chat-core@0.43.0
|
|
131
|
+
|
|
132
|
+
## 0.42.0
|
|
133
|
+
|
|
134
|
+
### Patch Changes
|
|
135
|
+
|
|
136
|
+
- Updated dependencies [a385276]
|
|
137
|
+
- @ykurilov/agent-chat-core@0.42.0
|
|
138
|
+
|
|
139
|
+
## 0.41.0
|
|
140
|
+
|
|
141
|
+
### Patch Changes
|
|
142
|
+
|
|
143
|
+
- Updated dependencies [9472fcb]
|
|
144
|
+
- @ykurilov/agent-chat-core@0.41.0
|
|
145
|
+
|
|
146
|
+
## 0.40.0
|
|
147
|
+
|
|
148
|
+
### Patch Changes
|
|
149
|
+
|
|
150
|
+
- Updated dependencies [0e7aab3]
|
|
151
|
+
- @ykurilov/agent-chat-core@0.40.0
|
|
152
|
+
|
|
153
|
+
## 0.39.1
|
|
154
|
+
|
|
155
|
+
### Patch Changes
|
|
156
|
+
|
|
157
|
+
- @ykurilov/agent-chat-core@0.39.1
|
|
158
|
+
|
|
159
|
+
## 0.39.0
|
|
160
|
+
|
|
161
|
+
### Patch Changes
|
|
162
|
+
|
|
163
|
+
- Updated dependencies [3b90429]
|
|
164
|
+
- @ykurilov/agent-chat-core@0.39.0
|
|
165
|
+
|
|
166
|
+
## 0.38.0
|
|
167
|
+
|
|
168
|
+
### Patch Changes
|
|
169
|
+
|
|
170
|
+
- Updated dependencies [1cae504]
|
|
171
|
+
- Updated dependencies [4065a4a]
|
|
172
|
+
- @ykurilov/agent-chat-core@0.38.0
|
|
173
|
+
|
|
174
|
+
## 0.37.0
|
|
175
|
+
|
|
176
|
+
### Patch Changes
|
|
177
|
+
|
|
178
|
+
- Updated dependencies [7f49d12]
|
|
179
|
+
- Updated dependencies [ea78982]
|
|
180
|
+
- @ykurilov/agent-chat-core@0.37.0
|
|
181
|
+
|
|
182
|
+
## 0.36.0
|
|
183
|
+
|
|
184
|
+
### Patch Changes
|
|
185
|
+
|
|
186
|
+
- Updated dependencies [3487fb4]
|
|
187
|
+
- Updated dependencies [8c43b86]
|
|
188
|
+
- Updated dependencies [6f42418]
|
|
189
|
+
- Updated dependencies [5f13c74]
|
|
190
|
+
- @ykurilov/agent-chat-core@0.36.0
|
|
191
|
+
|
|
192
|
+
## 0.35.0
|
|
193
|
+
|
|
194
|
+
### Patch Changes
|
|
195
|
+
|
|
196
|
+
- Updated dependencies [2382026]
|
|
197
|
+
- @ykurilov/agent-chat-core@0.35.0
|
|
198
|
+
|
|
199
|
+
## 0.34.0
|
|
200
|
+
|
|
201
|
+
### Patch Changes
|
|
202
|
+
|
|
203
|
+
- Updated dependencies [d039ce4]
|
|
204
|
+
- @ykurilov/agent-chat-core@0.34.0
|
|
205
|
+
|
|
206
|
+
## 0.33.0
|
|
207
|
+
|
|
208
|
+
### Patch Changes
|
|
209
|
+
|
|
210
|
+
- Updated dependencies [4a72339]
|
|
211
|
+
- @ykurilov/agent-chat-core@0.33.0
|
|
212
|
+
|
|
213
|
+
## 0.32.0
|
|
214
|
+
|
|
215
|
+
### Patch Changes
|
|
216
|
+
|
|
217
|
+
- Updated dependencies [71c32b7]
|
|
218
|
+
- Updated dependencies [cae13bf]
|
|
219
|
+
- Updated dependencies [a94bda9]
|
|
220
|
+
- Updated dependencies [4e44492]
|
|
221
|
+
- Updated dependencies [ac9b7d3]
|
|
222
|
+
- Updated dependencies [27f4b1e]
|
|
223
|
+
- @ykurilov/agent-chat-core@0.32.0
|
|
224
|
+
|
|
225
|
+
## 0.31.2
|
|
226
|
+
|
|
227
|
+
### Patch Changes
|
|
228
|
+
|
|
229
|
+
- @ykurilov/agent-chat-core@0.31.2
|
|
230
|
+
|
|
231
|
+
## 0.31.1
|
|
232
|
+
|
|
233
|
+
### Patch Changes
|
|
234
|
+
|
|
235
|
+
- @ykurilov/agent-chat-core@0.31.1
|
|
236
|
+
|
|
237
|
+
## 0.31.0
|
|
238
|
+
|
|
239
|
+
### Patch Changes
|
|
240
|
+
|
|
241
|
+
- @ykurilov/agent-chat-core@0.31.0
|
|
242
|
+
|
|
243
|
+
## 0.30.0
|
|
244
|
+
|
|
245
|
+
### Patch Changes
|
|
246
|
+
|
|
247
|
+
- @ykurilov/agent-chat-core@0.30.0
|
|
248
|
+
|
|
249
|
+
## 0.29.0
|
|
250
|
+
|
|
251
|
+
### Patch Changes
|
|
252
|
+
|
|
253
|
+
- @ykurilov/agent-chat-core@0.29.0
|
|
254
|
+
|
|
255
|
+
## 0.28.0
|
|
256
|
+
|
|
257
|
+
### Patch Changes
|
|
258
|
+
|
|
259
|
+
- Updated dependencies [11c3c97]
|
|
260
|
+
- Updated dependencies [d63ccaa]
|
|
261
|
+
- Updated dependencies [6a2f903]
|
|
262
|
+
- Updated dependencies [189cba9]
|
|
263
|
+
- @ykurilov/agent-chat-core@0.28.0
|
|
264
|
+
|
|
265
|
+
## 0.27.0
|
|
266
|
+
|
|
267
|
+
### Patch Changes
|
|
268
|
+
|
|
269
|
+
- Updated dependencies [d8341b2]
|
|
270
|
+
- Updated dependencies [5e4ed28]
|
|
271
|
+
- Updated dependencies [e0bb519]
|
|
272
|
+
- @ykurilov/agent-chat-core@0.27.0
|
|
273
|
+
|
|
274
|
+
## 0.26.2
|
|
275
|
+
|
|
276
|
+
### Patch Changes
|
|
277
|
+
|
|
278
|
+
- Updated dependencies [f24858a]
|
|
279
|
+
- @ykurilov/agent-chat-core@0.26.2
|
|
280
|
+
|
|
281
|
+
## 0.26.1
|
|
282
|
+
|
|
283
|
+
### Patch Changes
|
|
284
|
+
|
|
285
|
+
- @ykurilov/agent-chat-core@0.26.1
|
|
286
|
+
|
|
287
|
+
## 0.26.0
|
|
288
|
+
|
|
289
|
+
### Patch Changes
|
|
290
|
+
|
|
291
|
+
- Updated dependencies [eb43e47]
|
|
292
|
+
- @ykurilov/agent-chat-core@0.26.0
|
|
293
|
+
|
|
294
|
+
## 0.25.0
|
|
295
|
+
|
|
296
|
+
### Patch Changes
|
|
297
|
+
|
|
298
|
+
- Updated dependencies [99d426e]
|
|
299
|
+
- Updated dependencies [d8201f6]
|
|
300
|
+
- @ykurilov/agent-chat-core@0.25.0
|
|
301
|
+
|
|
302
|
+
## 0.24.0
|
|
303
|
+
|
|
304
|
+
### Minor Changes
|
|
305
|
+
|
|
306
|
+
- 9b895cd: Ломает приложения: только исчерпывающие `switch` по видам ошибок сервера и событиям чата (новые значения) и код, который
|
|
307
|
+
сам читает ответ `resolveUser`. Без новых настроек поведение прежнее.
|
|
308
|
+
|
|
309
|
+
Агент внутри продукта: агент работает с объектами приложения — уроком, заказом, документом. Всё по желанию; без новых
|
|
310
|
+
настроек запрос к модели не меняется ни на байт. Подробно — `docs/in-product-agent.md`.
|
|
311
|
+
|
|
312
|
+
- **Проверка перед ходом.** `beforeTurn({ userId, chat, action, text? })` отказывает своими словами: 403 `turn_refused`
|
|
313
|
+
до любых записей и лимитов, на отправке, правке, повторе, переделке, подтверждении, виджете, служебных сообщениях, фоновой
|
|
314
|
+
задаче и в мессенджерах. `resolveUser` может вернуть `{ refused: { code, message, status? } }` → `access_refused` на всех
|
|
315
|
+
адресах чата, голоса, голосового режима (WebSocket 4401) и мессенджеров. React: `onTurnRefused`, текст отказа вместо «нет
|
|
316
|
+
связи», сообщение возвращается в поле. Ручная проверка — `service.assertTurnAllowed`.
|
|
317
|
+
- **Итог хода.** `afterTurn(turn)` после каждого хода с повторами и сроком (`afterTurnAttempts`, `afterTurnTimeoutMs`),
|
|
318
|
+
переживает перезапуск сервера. `TurnResult`: владелец и автор хода, текст, части, расход, действие, канал, объект,
|
|
319
|
+
сотрудник. События приложения `{ type, data? }` — из хука, из инструмента (`model.emitAppEvent`) и вне хода
|
|
320
|
+
(`service.publishAppEvent`); в React `appEvents` и `onAppEvent`, события переживают перезагрузку. Модели не уходят.
|
|
321
|
+
- **Чат объекта.** Ключ и данные объекта у чата, один чат на ключ у человека: `service.openSubjectChat`, на сервере
|
|
322
|
+
`subjectChats` (`POST …/subject`), в React `<AgentChat subject="lesson:42" />`. Данные объекта видят `beforeTurn`,
|
|
323
|
+
инструменты (`model.subject`) и `afterTurn`; в браузер и модели не уходят.
|
|
324
|
+
- **Приветствие.** `greeting: { text }` — первое сообщение от агента без вызова модели. Проверено на всех моделях каталога.
|
|
325
|
+
- **Лимит сообщений.** Окно лимитов с `limitMessages` вместо `limitUsd`, `exemptUsers` — люди без лимитов,
|
|
326
|
+
`onMessageThreshold` — пороги. Отказ — 429 с `unit: "messages"`.
|
|
327
|
+
- **Импорт старой переписки.** `service.importChat({ ownerId, chat, messages })` с датами и картинками
|
|
328
|
+
(`attachments.importFile`), без хода, памяти, расхода и лимитов.
|
|
329
|
+
- **Сотрудник проверяет чат человека.** Песочница с опцией `people`: админ видит чаты человека только на чтение и
|
|
330
|
+
проверяет ответы в копии у себя. Память человека в копии только читается, расход — на админа, человек ничего не видит.
|
|
331
|
+
Инструменты приложения получают `model.staff` и в копии в данные человека не пишут.
|
|
332
|
+
- **Свои кнопки у поля ввода.** `composerActions` с помощником `{ value, setValue, send, addFiles, busy, blocked, canSend }`.
|
|
333
|
+
Договор скина v19: `Composer.actions`; скин v18 работает без кнопок, Тандем готов.
|
|
334
|
+
- **Хранилища.** Миграции применяются сами: SQLite `0015`, PostgreSQL `0014` (ключ объекта, состояние хука итога).
|
|
335
|
+
|
|
336
|
+
### Что может сломаться
|
|
337
|
+
|
|
338
|
+
- **Исчерпывающие `switch` по закрытым спискам.** Новые значения: вид ошибки сервера `turn_refused` и `access_refused`
|
|
339
|
+
(`HandlerErrorKind`), события чата `after-turn-failed` и `app-event` (`ChatEvent`), `unit` у отказа лимита. Добавьте ветки
|
|
340
|
+
и надписи.
|
|
341
|
+
- **Список чатов без чатов объектов.** `listChats` и `GET {basePath}` по умолчанию не показывают чаты с ключом объекта.
|
|
342
|
+
Касается только приложений, которые начнут ими пользоваться; показать — `chatList: { subjectChats: true }` или
|
|
343
|
+
`listChats(userId, { subjects: "include" })`.
|
|
344
|
+
- **Свой `resolveUser` в обёртках.** Тип ответа — `ResolvedUser` (`{ id } | { refused } | null`). Код, который сам вызывает
|
|
345
|
+
`resolveUser` и читает `.id`, сначала проверяет `"refused" in user`.
|
|
346
|
+
- **Своё хранилище.** Для новых возможностей нужны необязательные методы (`findChatBySubject`, `importChat`,
|
|
347
|
+
`setAfterTurnState`, `listPendingAfterTurn`); без них эти возможности при включении дают ошибку при старте, остальное
|
|
348
|
+
работает. `listChats(ownerId, options?)` получил второй параметр — чаты с ключом скрывать по умолчанию.
|
|
349
|
+
- **Свой `ChatService`** (заглушки в тестах) добавляет новые методы: `openSubjectChat`, `importChat`, `assertTurnAllowed`, `peekHistory`,
|
|
350
|
+
`publishAppEvent`.
|
|
351
|
+
- **Своя реализация `SpendingLimits`** может добавить `takeMessage` — без него сообщения не считаются.
|
|
352
|
+
- **`AgentChat`: `chatId` стал необязательным** — нужен ровно один из `chatId` и `subject`; ни одного или оба — ошибка при
|
|
353
|
+
рендере. При смене `chatId` чат пересоздаётся: черновик и состояние прошлого чата не переносятся.
|
|
354
|
+
- **Окна лимитов: `limitUsd` стал необязательным** (у окна сообщений его нет). Код, который читает свои окна, проверяет
|
|
355
|
+
`limitMessages`.
|
|
356
|
+
- **Отказ сервера в React** (`ServerRefusal`) получил `kind` и `code`. 401 со словами приложения (`access_refused`) — это
|
|
357
|
+
отказ, а не «вход истёк».
|
|
358
|
+
- **«Пустой чат»** для «Нового чата»: чат объекта пустым не считается, обычный чат с одним приветствием — считается.
|
|
359
|
+
- Новый подпуть `@ykurilov/agent-chat-core/access` — помощники отказа в доступе для своих обработчиков.
|
|
360
|
+
|
|
361
|
+
### Как обновить приложение
|
|
362
|
+
|
|
363
|
+
1. `pnpm up "@ykurilov/agent-chat-*@^0.24.0"`. Миграции базы применяются сами при открытии хранилища.
|
|
364
|
+
2. Исчерпывающие `switch` по `HandlerErrorKind` (сервер) и `ChatEvent` (`chatEvents` ядра): найдите их поиском и добавьте
|
|
365
|
+
ветки `turn_refused`, `access_refused`, `after-turn-failed`, `app-event`. Обязательных надписей не прибавилось: текст
|
|
366
|
+
отказа приходит с сервера. Свой словарь для лимита сообщений — необязательные `spendingMessagesLeft`,
|
|
367
|
+
`spendingMessagesExhausted`, `editMessageLimit`.
|
|
368
|
+
|
|
369
|
+
Было: `switch (event.type) { case "tasks-changed": … case "notice-added": … default: assertNever(event) }`
|
|
370
|
+
Стало: те же ветки плюс `case "after-turn-failed": case "app-event": break;`
|
|
371
|
+
3. Свой код, который сам зовёт `resolveUser` и читает `.id`: сначала `if (user && "refused" in user) …`.
|
|
372
|
+
4. Ничего больше не нужно, если новые возможности не включать. Чтобы включить — `docs/in-product-agent.md`.
|
|
373
|
+
5. Свой скин: кнопки у поля появятся, когда `Composer` начнёт рисовать `actions` (договор v19, `docs/skin-v19.md`).
|
|
374
|
+
6. Проверка: `pnpm typecheck` без ошибок, чат открывается и отвечает как раньше.
|
|
375
|
+
|
|
376
|
+
### Patch Changes
|
|
377
|
+
|
|
378
|
+
- Updated dependencies [9b895cd]
|
|
379
|
+
- @ykurilov/agent-chat-core@0.24.0
|
|
380
|
+
|
|
381
|
+
## 0.23.0
|
|
382
|
+
|
|
383
|
+
No changes in this release.
|
|
384
|
+
|
|
385
|
+
## 0.22.0
|
|
386
|
+
|
|
387
|
+
No changes in this release.
|
|
388
|
+
|
|
389
|
+
## 0.21.0
|
|
390
|
+
|
|
391
|
+
No changes in this release.
|
|
392
|
+
|
|
393
|
+
## 0.20.0
|
|
394
|
+
|
|
395
|
+
### Minor Changes
|
|
396
|
+
|
|
397
|
+
- fd16b01: Вложения и голос можно подключить к мессенджерам. У маршрутов `@ykurilov/agent-chat-attachments` появился `ingestFile` — файл из мессенджера становится вложением чата. `@ykurilov/agent-chat-voice/server` отдаёт `transcribeAudioFile` — голосовое сообщение превращается в текст через Soniox. Примеры обёрток — в README `@ykurilov/agent-chat-messengers`.
|
|
398
|
+
|
|
399
|
+
Что сделать в приложении: ничего, пока мессенджеры не подключены.
|
|
400
|
+
|
|
401
|
+
## 0.19.0
|
|
402
|
+
|
|
403
|
+
No changes in this release.
|
|
404
|
+
|
|
405
|
+
## 0.18.6
|
|
406
|
+
|
|
407
|
+
No changes in this release.
|
|
408
|
+
|
|
409
|
+
## 0.18.5
|
|
410
|
+
|
|
411
|
+
No changes in this release.
|
|
412
|
+
|
|
413
|
+
## 0.18.4
|
|
414
|
+
|
|
415
|
+
No changes in this release.
|
|
416
|
+
|
|
417
|
+
## 0.18.3
|
|
418
|
+
|
|
419
|
+
No changes in this release.
|
|
420
|
+
|
|
421
|
+
## 0.18.2
|
|
422
|
+
|
|
423
|
+
No changes in this release.
|
|
424
|
+
|
|
425
|
+
## 0.18.1
|
|
426
|
+
|
|
427
|
+
No changes in this release.
|
|
428
|
+
|
|
429
|
+
## 0.18.0
|
|
430
|
+
|
|
431
|
+
No changes in this release.
|
|
432
|
+
|
|
433
|
+
## 0.17.0
|
|
434
|
+
|
|
435
|
+
No changes in this release.
|
|
436
|
+
|
|
437
|
+
## 0.16.0
|
|
438
|
+
|
|
439
|
+
No changes in this release.
|
|
440
|
+
|
|
441
|
+
## 0.15.0
|
|
442
|
+
|
|
443
|
+
### Minor Changes
|
|
444
|
+
|
|
445
|
+
- f05ad23: Встроенные провайдеры (OpenRouter, DeepSeek, Fireworks, Together) можно подключить через прокси: свой адрес `baseURL`
|
|
446
|
+
и заголовки `headers` к каждому запросу. Нужно серверу в России, откуда зарубежные провайдеры напрямую недоступны.
|
|
447
|
+
Через прокси идёт всё: ход агента, фоновые вызовы памяти и сжатия, сверка расхода OpenRouter. Меню моделей, цены и учёт
|
|
448
|
+
расходов те же. Значения заголовков вычищаются из ошибок и журналов, как ключи.
|
|
449
|
+
|
|
450
|
+
Новое: правка каталога `extendCatalog(…, { connectProviders: { openrouter: { baseURL, headers } } })` (провайдер остаётся
|
|
451
|
+
на своём месте, с прежними настройками), фабрики `createDeepSeekProvider`, `createFireworksProvider`,
|
|
452
|
+
`createTogetherProvider`, у `createOpenRouterProvider` — `baseURL` и `headers`, тип `ProviderConnection`, поля
|
|
453
|
+
`connection` и `connect` у `ProviderDescription` (необязательные). Голос: `headers` у чистки текста
|
|
454
|
+
(`polish: { provider: "together", baseUrl, headers }`) и у звуков человека (`sounds: { baseUrl, headers }`).
|
|
455
|
+
|
|
456
|
+
### Как обновить приложение
|
|
457
|
+
|
|
458
|
+
Ничего делать не нужно: без новых настроек запросы идут прямо к провайдерам, как раньше.
|
|
459
|
+
|
|
460
|
+
Чтобы пустить провайдера через прокси, в файле, где собирается каталог моделей (обычно рядом с `createChatHandler`):
|
|
461
|
+
|
|
462
|
+
```ts
|
|
463
|
+
import { extendCatalog, standardCatalog } from "@ykurilov/agent-chat-core";
|
|
464
|
+
|
|
465
|
+
const catalog = extendCatalog(standardCatalog, {
|
|
466
|
+
connectProviders: {
|
|
467
|
+
openrouter: {
|
|
468
|
+
baseURL: "https://fr-api-route.yeycourses.com/openrouter/api/v1",
|
|
469
|
+
headers: { "X-Proxy-Token": process.env.PROXY_TOKEN! },
|
|
470
|
+
},
|
|
471
|
+
},
|
|
472
|
+
});
|
|
473
|
+
|
|
474
|
+
createChatHandler({ /* … */ catalog });
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
Токен прокси — только в окружении сервера (`PROXY_TOKEN`), не в коде. Не задан `PROXY_TOKEN` — ошибка при старте
|
|
478
|
+
(у заголовка нет значения). Значение заголовка короче 8 знаков и заголовок `Authorization` — тоже ошибка при старте.
|
|
479
|
+
Прокси должен пробрасывать заголовок ответа `x-generation-id`, иначе расход OpenRouter останется оценкой. Проверка:
|
|
480
|
+
один ответ в чате приходит, в журнале прокси виден запрос.
|
|
481
|
+
|
|
482
|
+
## 0.14.0
|
|
483
|
+
|
|
484
|
+
### Minor Changes
|
|
485
|
+
|
|
486
|
+
- 96098be: Мелкие исправления (022). Символ с кодом ноль в первом сообщении больше не роняет отправку на Postgres: он выбрасывается из названия чата, из записей памяти и из сводки сжатия истории (иначе запись сжатия падала бы при каждой попытке); в самом тексте сообщения он лежит как раньше. Вложения отмечаются прикреплёнными до записи сообщения, а не после: если сервер упал между двумя шагами, чистка брошенных файлов не удалит их через сутки (файл, отмеченный зря, безвреден и уходит вместе с чатом). Во всех пакетах появилось поле `engines: { node: ">=22" }`; голосовой сервер (`createVoiceRelay`) и голосовой диалог (`createDialogRelay`) на Node 20 сразу при создании говорят понятной ошибкой, что нужен Node 22 (раньше падали при первом соединении; со своим `connectUpstream` проверки нет). В пакете вложений `react` и `@ykurilov/agent-chat-react` стали необязательными peer-зависимостями: серверу без экрана они больше не ставятся. Приложению, которое берёт `@ykurilov/agent-chat-attachments/react`, достаточно иметь их в проекте — для чата на экране они нужны и так; если они подтягивались только через вложения, добавьте их в зависимости приложения.
|
|
487
|
+
- 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 знаков, проходит).
|
|
488
|
+
- 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`.
|
|
489
|
+
|
|
490
|
+
**Изменение договора надписей:** в `ChatLabels` два новых обязательных ключа — `errors.forbidden_origin` и `editErrors.forbiddenOrigin`. Словарь на основе `{ ...russianLabels }` получает их сам; свой словарь целиком — дополните ими, иначе ошибка типов. Отдельного номера версии у договора надписей нет. Ещё: при отказе по месту хода (`too_many_turns`) или занятом чате файлы вложений больше не принимаются и не остаются ничьими; пока файлы принимаются, чат занят, и второе сообщение в него получает 409.
|
|
491
|
+
- 6b20d83: Голосовой режим («разговор»): человек говорит, слова сами уходят сообщением в чат, ответ агента звучит голосом, человека можно перебить. Новый пакет `@ykurilov/agent-chat-voice-dialog`: распознавание Soniox, озвучка ElevenLabs (голос по умолчанию «Профессиональный диктор для аудиокниг», модель `eleven_v4_turbo`), ключи только на сервере. Перебитый ответ остаётся в ленте с отметкой «Вы перебили: озвучено до «…»», она хранится и видна после перезагрузки. Расход на озвучку идёт в учёт и лимиты (`source: "speech"`). Человек выбирает голос в меню режима; выбор хранится на сервере.
|
|
492
|
+
|
|
493
|
+
Модель узнаёт о режиме двумя служебными пометками: одна при входе («ответы озвучиваются, отвечай коротко и разговорно»), одна при возврате к тексту («разговор снова текстом»). Они стоят в конце сообщения человека, где режим сменился, а не в каждом запросе. Сообщение из режима запоминается голосовым отметкой в самом сообщении (часть `data-voice-mode` в `parts`), поэтому миграции для этого нет, пометки выводятся из сохранённого и кэш модели цел. Тексты задают настройки агента `voiceModeHint` и `textModeNote` (есть умолчания).
|
|
494
|
+
|
|
495
|
+
Обновление ничего не ломает: без нового пакета чат работает как раньше. Диктовка в поле ввода (`@ykurilov/agent-chat-voice`) не меняется.
|
|
496
|
+
|
|
497
|
+
### Как обновить приложение
|
|
498
|
+
|
|
499
|
+
Нужно, только если вы хотите голосовой режим.
|
|
500
|
+
|
|
501
|
+
1. Поставьте пакет `@ykurilov/agent-chat-voice-dialog` той же версии, что и остальные пакеты SDK. Скин Тандем обновите вместе с SDK: договор скина теперь версии 10 (необязательный `dialog` у поля ввода, панель режима, меню голосов, отметка обрыва; свой скин может их не рисовать, тогда кнопки режима не будет).
|
|
502
|
+
2. Сервер. Рядом с чатом подключите режим (нужен WebSocket; с Hono и `@hono/node-ws`):
|
|
503
|
+
|
|
504
|
+
```ts
|
|
505
|
+
import { mountDialogRelay } from "@ykurilov/agent-chat-voice-dialog/hono";
|
|
506
|
+
|
|
507
|
+
mountDialogRelay(app, {
|
|
508
|
+
path: "/api/voice-dialog",
|
|
509
|
+
upgradeWebSocket,
|
|
510
|
+
storage,
|
|
511
|
+
resolveUser, // тот же вход, что у чата
|
|
512
|
+
spendingLimits, // по желанию
|
|
513
|
+
logError: (message) => console.error(message),
|
|
514
|
+
speech: {
|
|
515
|
+
voices: [{ id: "oE0n0S3wK5Mj9C62iehn", name: "Профессиональный диктор для аудиокниг" }],
|
|
516
|
+
defaultVoiceId: "oE0n0S3wK5Mj9C62iehn",
|
|
517
|
+
pricePerThousandChars: { eleven_v4_turbo: 0.11, eleven_v4: 0.22 }, // ваша цена, $ за 1000 знаков
|
|
518
|
+
},
|
|
519
|
+
});
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
Ключи `ELEVENLABS_API_KEY` и `SONIOX_API_KEY` — в окружении сервера. Next.js: WebSocket нужен свой Node-сервер, см. README пакета (`createDialogRelay`).
|
|
523
|
+
3. Браузер:
|
|
524
|
+
|
|
525
|
+
```tsx
|
|
526
|
+
const voiceDialog = createVoiceDialogEngine({ basePath: "/api/voice-dialog" });
|
|
527
|
+
<AgentChat api="/api/chat" skin={tandemSkin} voiceDialog={voiceDialog} />
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
4. Настройки. Слова остановки и междометия по умолчанию только русские; для другого языка задайте `bargeIn.stopWords` и `bargeIn.ignoreWords` у движка и `language` на сервере. Строгая политика содержимого страницы: добавьте `worklet-src blob:`.
|
|
531
|
+
5. Хранилище. SQLite получает миграцию 0008, PostgreSQL — 0007 (схема `agent_chat`) сами при открытии базы. Свой `ChatStorage`: добавьте необязательные методы `setVoiceCut`, `getVoiceChoice`, `setVoiceChoice` (без них отметка обрыва и выбор голоса живут только до перезагрузки) и значение `"speech"` в `UsageSource`, если учёт расхода у вас свой.
|
|
532
|
+
6. Свой экран (не наш скин): части сообщения с типом `data-voice-mode` не рисуйте, показывайте только текстовые части.
|
|
533
|
+
7. Проверка: `pnpm typecheck` проходит; в чате появилась кнопка режима, после нажатия виден статус «Слушаю», фраза уходит сообщением, ответ звучит.
|
|
534
|
+
|
|
535
|
+
## 0.13.0
|
|
536
|
+
|
|
537
|
+
No changes in this release.
|
|
538
|
+
|
|
539
|
+
## 0.12.0
|
|
540
|
+
|
|
541
|
+
No changes in this release.
|
|
542
|
+
|
|
543
|
+
## 0.11.0
|
|
544
|
+
|
|
545
|
+
### Minor Changes
|
|
546
|
+
|
|
547
|
+
- 9d510b8: **Ломает приложения:** только если вы сами собрали словарь надписей целиком (без `{ ...russianLabels, … }`): в `ChatLabels` появилась надпись `voicePolishing`. Кроме того, клиент голоса `mode: "relay"` теперь шлёт серверу команду `finalize`, которую старый сервер relay не знает (закрывает соединение кодом 4400): сервер обновляйте раньше клиента или вместе с ним.
|
|
548
|
+
|
|
549
|
+
Голос стал точнее и быстрее, а основной путь — через ваш сервер.
|
|
550
|
+
|
|
551
|
+
Что изменилось:
|
|
552
|
+
|
|
553
|
+
- **Через сервер — основной путь.** Ключ Soniox не уходит в браузер даже в виде временного. В документации relay первый и рекомендуемый; прямой режим (`createVoiceHandler`) работает как раньше, но помечен «не рекомендуется».
|
|
554
|
+
- **Soniox `stt-rt-v5`.** Включено определение конца фразы. По «стоп» клиент шлёт `finalize`, Soniox закрепляет всё сказанное и присылает метку `<fin>`; после неё текст готов. Не ответил за `stopTimeoutMs` (3 с) — остаётся то, что пришло, без ошибки.
|
|
555
|
+
- **Чистка текста моделью (по желанию, только relay):** `createVoiceRelay({ polish: { provider: "together" } })` (ключ `TOGETHER_API_KEY`, модель по умолчанию `deepseek-ai/DeepSeek-V4.1-Flash`) или `polish: { clean: async (text) => … }`. После «стоп» сервер убирает «э-э», повторы и оговорки, расставляет знаки и заглавные. Заменяется только надиктованный кусок: набранное руками и правка во время чистки не теряются. Сбой или тишина дольше 5 секунд — остаётся текст Soniox. Пока идёт чистка, кнопка микрофона крутится (`VoiceInputView.polishing`, подпись `voicePolishing`). Ответ, похожий на ответ на вопрос или отказ (мало слов из исходника, слишком короткий или длинный), отбрасывается. Текст уходит в модель чистки (Together), ключ остаётся на сервере. Лимиты расходов (`@ykurilov/agent-chat-limits`) чистку не учитывают; у неё свой лимит `polishRateLimit` (6 в минуту на человека, `false` — выключить). Новый `maxConnectionsPerUser` (по умолчанию 2 соединения на человека, `false` — выключить).
|
|
556
|
+
- Серверная сессия Soniox вынесена в `createSonioxSession` (`@ykurilov/agent-chat-voice/server`): её можно использовать без поля ввода.
|
|
557
|
+
- Исправлено: два сообщения Soniox подряд могли продублировать хвост фразы в поле; при длинной диктовке поле теперь прокручивается к последним словам.
|
|
558
|
+
|
|
559
|
+
### Как обновить приложение
|
|
560
|
+
|
|
561
|
+
1. Сначала обновите сервер, потом клиент (или оба вместе): `pnpm update "@ykurilov/agent-chat-*" --latest`.
|
|
562
|
+
2. Только если словарь надписей собран целиком: добавьте `voicePolishing: "Приводим текст в порядок…"`.
|
|
563
|
+
3. Хотите основной путь: замените `createVoiceHandler` на `createVoiceRelay` + `mountVoiceRelay` и `createVoiceInput({ api: "/api/voice", mode: "relay" })` (код — в README пакета `voice`). Нужен WebSocket на сервере и (если есть прокси) `ws: true`.
|
|
564
|
+
4. Хотите чистку: добавьте `polish: { provider: "together" }` в `createVoiceRelay` и `TOGETHER_API_KEY` в окружение сервера.
|
|
565
|
+
5. Проверка: `pnpm typecheck`; продиктуйте фразу с «э-э» и нажмите «стоп»: текст должен замениться на исправленный.
|
|
566
|
+
|
|
567
|
+
## 0.10.0
|
|
568
|
+
|
|
569
|
+
No changes in this release.
|
|
570
|
+
|
|
571
|
+
## 0.9.0
|
|
572
|
+
|
|
573
|
+
No changes in this release.
|
|
574
|
+
|
|
575
|
+
## 0.8.0
|
|
576
|
+
|
|
577
|
+
No changes in this release.
|
|
578
|
+
|
|
579
|
+
## 0.7.0
|
|
580
|
+
|
|
581
|
+
### Minor Changes
|
|
582
|
+
|
|
583
|
+
- e741e6d: Новый пакет `@ykurilov/agent-chat-voice`: голосовой ввод через Soniox. В поле ввода появляется кнопка микрофона, слова видны по ходу речи, человек правит и отправляет сам. Главный ключ Soniox остаётся на сервере, браузеру выдаётся временный.
|
|
584
|
+
|
|
585
|
+
Что изменилось:
|
|
586
|
+
|
|
587
|
+
- `@ykurilov/agent-chat-voice/server`: `createVoiceHandler({ basePath, resolveUser })` — адрес `POST /api/voice/session`, ключ из `SONIOX_API_KEY`. Адреса Soniox настраиваются (`apiBaseUrl`, `apiHeaders`, `websocketUrl`) — для сервера в России.
|
|
588
|
+
- `@ykurilov/agent-chat-voice`: `createVoiceInput({ api })` — микрофон и соединение с Soniox в браузере. Формат записи выбирается явно (webm/opus → ogg/opus → mp4/AAC).
|
|
589
|
+
- Режим «звук через наш сервер»: `createVoiceInput({ api, mode: "relay" })` в браузере, `createVoiceRelay` в `…/voice/server` и `mountVoiceRelay` в новом подпути `…/voice/hono` (Hono на Node через `@hono/node-ws`). Нужен там, где Soniox недоступен из браузера; адрес и заголовки прокси настраиваются (`websocketUrl`, `upstreamHeaders`). Next.js WebSocket в route handlers не держит — нужен отдельный Node-сервер.
|
|
590
|
+
- Ограничение частоты: `rateLimit` (по умолчанию 10 диктовок в минуту на человека, в памяти процесса; общие лимиты — на приложении). Ответ с ключом идёт с `Cache-Control: no-store`; исключение из `resolveUser` даёт 503 и запись в `logError`.
|
|
591
|
+
- Предел диктовки 5 минут: запись останавливается за две секунды до него, человек видит причину.
|
|
592
|
+
- Отправка сообщения во время диктовки останавливает диктовку.
|
|
593
|
+
- Ручная правка посреди слова, которое Soniox ещё не закрепил, больше не портит текст: сказанное учитывается только по закреплённой части.
|
|
594
|
+
- `AgentChat` принимает необязательное свойство `voice`; без него кнопки нет. Договор скина версии 5: `Composer` получает необязательное `voice` (`VoiceInputView`). Скин Тандема рисует кнопку сам (`TandemVoiceButton`).
|
|
595
|
+
- В словаре надписей новые ключи: `voiceStart`, `voiceStop`, `voiceConnecting`, `voiceErrors` (виды ошибок, в том числе `rate_limited` и `time_limit`).
|
|
596
|
+
- `mountChat` и `createNextRouteHandlers` теперь принимают любой объект с `basePath` и `fetch`, а не только обработчик чата — так подключается и голос.
|
|
597
|
+
|
|
598
|
+
### Как обновить приложение
|
|
599
|
+
|
|
600
|
+
Если голос не нужен, ничего делать не нужно, кроме одного случая:
|
|
601
|
+
|
|
602
|
+
1. **Только если словарь надписей написан целиком** (не через `{ ...russianLabels, … }`): добавьте ключи `voiceStart`, `voiceStop`, `voiceConnecting` и `voiceErrors` (по видам `permission_denied`, `no_microphone`, `unsupported`, `network`, `service_unavailable`, `rate_limited`, `time_limit`, `other`). Значения — в `russianLabels` из `@ykurilov/agent-chat-react`.
|
|
603
|
+
|
|
604
|
+
Чтобы включить голос:
|
|
605
|
+
|
|
606
|
+
1. `pnpm add @ykurilov/agent-chat-voice`, ключ Soniox положите в окружение сервера как `SONIOX_API_KEY`.
|
|
607
|
+
2. На сервере рядом с чатом: `mountChat(app, createVoiceHandler({ basePath: "/api/voice", resolveUser }))` (в Next.js — второй файл маршрута `app/api/voice/[[...path]]/route.ts`).
|
|
608
|
+
3. В браузере: `<AgentChat … voice={createVoiceInput({ api: "/api/voice" })} />`, объект создаётся один раз.
|
|
609
|
+
4. Если скин свой: `Composer` получает `voice`; нет его — кнопку не рисовать.
|
|
610
|
+
5. Проверка: кнопка «Диктовать» есть в поле ввода, слова появляются по ходу речи.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Yury Kurilov
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|