@ykurilov/agent-chat-web-tools 0.0.0-stage → 0.56.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 ADDED
@@ -0,0 +1,713 @@
1
+ # @ykurilov/agent-chat-web-tools
2
+
3
+ ## 0.56.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 24c313e: Новый пакет `@ykurilov/agent-chat-mcp`: серверы MCP, которые подключает админ приложения.
8
+
9
+ - `createMcpServers({ store, secretKey, isAdmin, proxy?, spending?, limits?, syncIntervalMs? })` → `mcp.tools(model, appTools?)`
10
+ для `agent.tools` (первым; при одинаковом имени побеждает инструмент приложения), `mcp.admin`, `mcp.reload()`, `mcp.sync()`, `mcp.close()`. «Только админы» — по `model.viewer.isAdmin`;
11
+ `isAdmin` (может быть асинхронной) — для экрана. Правка доходит до всех копий сервера по отметке версии в хранилище. Только удалённые серверы (Streamable HTTP, SSE). Инструменты — из
12
+ сохранённого снимка списка: запрос к модели стабилен, упавший сервер не ломает начало запроса. Соединение — на
13
+ проверенный адрес DNS; заголовки прокси — только на `proxy.origin`.
14
+ - `createMcpAdminHandler({ mcp, resolveUser, allowedOrigins })` — адреса `/api/mcp`, не админу 404.
15
+ - Хранилища: `createMemoryMcpStore`, `/sqlite` `createSqliteMcpStore`, `/postgres` `createPostgresMcpStore`; миграции сами.
16
+ - `/react`: `McpAdmin`, `useMcpAdmin`, договор скина `McpSkin` v1 (с формой правки `McpServerCardView.edit`), надписи ru/en. Скин Тандема: `./mcp` → `tandemMcpSkin`.
17
+ - Ядро: штатный вид расхода `mcp_tool`; `agent.viewer` — права человека раз в начале хода, полем `viewer` в
18
+ `contextBlocks` и `AgentToolsModel`. Песочница: права тестового чата — по владельцу чата. web-tools: наружу `dnsHostResolver`.
19
+
20
+ ### Patch Changes
21
+
22
+ - Updated dependencies [24c313e]
23
+ - @ykurilov/agent-chat-core@0.56.0
24
+
25
+ ## 0.55.0
26
+
27
+ ### Patch Changes
28
+
29
+ - Updated dependencies [51f7b38]
30
+ - Updated dependencies [cdc7dd7]
31
+ - @ykurilov/agent-chat-core@0.55.0
32
+
33
+ ## 0.54.0
34
+
35
+ ### Patch Changes
36
+
37
+ - Updated dependencies [fa90219]
38
+ - @ykurilov/agent-chat-core@0.54.0
39
+
40
+ ## 0.53.0
41
+
42
+ ### Patch Changes
43
+
44
+ - Updated dependencies [b6a7786]
45
+ - @ykurilov/agent-chat-core@0.53.0
46
+
47
+ ## 0.52.0
48
+
49
+ ### Patch Changes
50
+
51
+ - @ykurilov/agent-chat-core@0.52.0
52
+
53
+ ## 0.51.0
54
+
55
+ ### Patch Changes
56
+
57
+ - Updated dependencies [41b1726]
58
+ - @ykurilov/agent-chat-core@0.51.0
59
+
60
+ ## 0.50.0
61
+
62
+ ### Patch Changes
63
+
64
+ - @ykurilov/agent-chat-core@0.50.0
65
+
66
+ ## 0.49.0
67
+
68
+ ### Minor Changes
69
+
70
+ - 084cef7: **Ломает приложения (типы и своё хранилище сценариев):** у типа поля сценария `FlowFieldType` появилось значение `"boolean"`, у источника
71
+ расхода `UsageSource` — `"first_message"`, у `SteerResult.status` — `"held"`. Исчерпывающий `switch` по ним перестанет
72
+ собираться. Своё хранилище сценариев (`FlowStore`) должно реализовать новый `renewLease()` и третий аргумент `setDue`.
73
+
74
+ Сценарии для приложений: программа по дням (ночь, касания, рамки дня, «срок вышел»), своя служба чата и доставка с
75
+ исходами, пауза сотрудника, конец разговора с итогом, карточка и пояс человека в базе приложения, попутные задачи.
76
+ Проверка готового ответа: «чужие слова» и «выдуманные ссылки». Подробно — `docs/flows.md`, `docs/reply-check.md`,
77
+ раздел 0.49.0 в `CHANGES.md`.
78
+
79
+ - **flows**: формат сценария версии 2 (`schedule`, `nudges`, таймер `state_days`, поле `boolean`, `sideTasks`,
80
+ `afterEnd`; версия 1 читается сама); `attach({ portFor, deliver })`, `admit`, `pause`/`resume`/`noteStaffReply`,
81
+ `reportDelivery`, `onFinish`, `clientCard`, `people`, `settled`, `now`; причина перехода `reason`; перенос чата
82
+ через `loadFlow` (`stateId`, `startedAt`, `enteredAt`); заголовки судьи `judge.openrouter.headers`; встроенная задача
83
+ «узнать город»; `checkFlow(flow, catalog, { checks })` и `FlowAppChecks` из `/format`; в редакторе панели дней,
84
+ касаний, рамок и попутных задач, `catalog.fields`, кнопка «К началу следующего дня» (`advanceToNextDay`). Новые
85
+ таблицы `flow_people`, `flow_side_tasks` и колонки `flow_chats` создаются сами.
86
+ - **core**: `replyChecks` (список или `{ checks, web: "replace" | "hold" }`), `now`, `markUndelivered`, ответы
87
+ `beforeTurn` `{ hold: true }` и `{ reply: { text } }`, `deliverNotices({ timeZone, awaitAnswer, usageSource })`,
88
+ источник расхода `first_message`.
89
+ - **flows, надёжность**: обход таймеров до 5 ходов одновременно; копия продлевает аренду чата перед ходом и во время
90
+ него. В `FlowStore` новые `renewLease()` и `setDue(…, { unlessDelivery })`. Недоставленное касание (`failed`,
91
+ `window_closed`) не засчитывается — тот же шаг через свой срок от отказа; в `FlowRun` новое поле `touch`. «Окно
92
+ закрыто» снимает любое сообщение человека; «не завершил» считает тишину и от конца паузы сотрудника; пока ждёт
93
+ повтор доставки, срок не затирается и новых ходов нет.
94
+ - **server**: `createChatServer` передаёт службе `replyChecks` и `now`.
95
+ - **messengers**: `onAnswerDelivery` — исход доставки каждого ответа; закрытое окно ВК (950) —
96
+ `MessengerWindowClosedError` и исход `window_closed`; с `replyChecks` уходит только проверенный текст.
97
+ - **web-tools**: `createPersonLinkTool` — инструмент `person_link_view`, агент смотрит ссылку, которую прислал человек
98
+ (адрес из почты ссылкой не считается).
99
+ - **reply-check** (новый пакет): `foreignWords` и `unknownLinks`; ответ из одной выдуманной ссылки заменяется запасной
100
+ фразой `labels.linkOnlyReply` (`russianReplyCheckLabels`, `englishReplyCheckLabels`, `ReplyCheckLabels`).
101
+ - **react**: договор скина версии 24 — необязательное `undelivered` у ответа агента и надпись `answerUndelivered`
102
+ («Не доставлено»). Скин версии 23 работает без правок.
103
+
104
+ ### Как обновить приложение
105
+
106
+ 1. Поднимите все пакеты `@ykurilov/agent-chat-*` до этой версии вместе.
107
+ 2. Найдите в коде приложения исчерпывающие `switch` и словари по этим типам и добавьте ветки:
108
+ - по `FlowFieldType` (поля карточки сценария) — `"boolean"`, «да/нет», значения `true`/`false`;
109
+ - по `UsageSource` (отчёты расходов) — `"first_message"`, «агент написал первым»;
110
+ - по `SteerResult.status` — `"held"`, «сообщение записано, хода нет».
111
+ 3. Своё хранилище сценариев (свой `FlowStore`) — добавьте `renewLease({ chatId, owner, now, leaseMs }): Promise<boolean>`
112
+ (продлить аренду до `now + leaseMs`; `false` — чат уже не ваш) и третий аргумент `setDue(chatId, due, { unlessDelivery })`
113
+ (при `unlessDelivery` не писать срок, пока чат ждёт повтора доставки). Готовые хранилища SDK это уже умеют.
114
+ 4. Сценарии сохраняются версией 2, а 0.48 её не откроет. Перед откатом на 0.48 держите копии сценариев версии 1.
115
+ 5. Новое по желанию: каналы SDK и сценарий — `createMessengers({ onAnswerDelivery: (report) => flow.reportDelivery(report) })`;
116
+ проверка ответа — `pnpm add @ykurilov/agent-chat-reply-check` и `replyChecks` в `createChatServer`.
117
+ 6. Проверка: `pnpm typecheck` проходит, чат отвечает, сценарий версии 1 открывается в редакторе.
118
+
119
+ ### Patch Changes
120
+
121
+ - Updated dependencies [084cef7]
122
+ - @ykurilov/agent-chat-core@0.49.0
123
+
124
+ ## 0.48.0
125
+
126
+ ### Patch Changes
127
+
128
+ - Updated dependencies [fa10d5a]
129
+ - @ykurilov/agent-chat-core@0.48.0
130
+
131
+ ## 0.47.0
132
+
133
+ ### Patch Changes
134
+
135
+ - Updated dependencies [5a59c33]
136
+ - @ykurilov/agent-chat-core@0.47.0
137
+
138
+ ## 0.46.2
139
+
140
+ ### Patch Changes
141
+
142
+ - Updated dependencies [3d0d2f2]
143
+ - @ykurilov/agent-chat-core@0.46.2
144
+
145
+ ## 0.46.1
146
+
147
+ ### Patch Changes
148
+
149
+ - @ykurilov/agent-chat-core@0.46.1
150
+
151
+ ## 0.46.0
152
+
153
+ ### Patch Changes
154
+
155
+ - Updated dependencies [56d7528]
156
+ - Updated dependencies [a1933fd]
157
+ - Updated dependencies [52cc67d]
158
+ - @ykurilov/agent-chat-core@0.46.0
159
+
160
+ ## 0.45.0
161
+
162
+ ### Minor Changes
163
+
164
+ - eb74c58: Простой вид работы агента: свойство экрана `workView="simple"` — пока ход идёт, одна живая строка с текущим шагом
165
+ («Рисую календарь…»); после хода шаги свёрнуты в «Сделано N шагов» со списком понятных фраз, без кода и «Думал N сек».
166
+ По умолчанию `workView="detailed"` — всё как раньше. Фразы задаёт приложение (`stepPhrases`: имя инструмента →
167
+ `{ running, done, failed? }` или функция от вызова); встроенные пакеты дают свои во входе `./labels`
168
+ (`webToolStepPhrases`, `memoryStepPhrases`, `historySearchStepPhrases`, `backgroundStepPhrases`, и английские).
169
+ Договор скина 23: необязательный `ChatSkin.WorkSteps`; скин 22 работает без правок. Подробно — docs/work-view.md.
170
+
171
+ ### Как обновить приложение
172
+
173
+ Ничего не требуется. Чтобы включить простой вид:
174
+
175
+ ```tsx
176
+ import { webToolStepPhrases } from "@ykurilov/agent-chat-web-tools/labels";
177
+
178
+ <ChatWorkspace
179
+ workView="simple"
180
+ stepPhrases={{
181
+ ...webToolStepPhrases,
182
+ write_file: ({ input }) => ((input as { path?: string } | undefined)?.path ? { running: "Пишу файл", done: "Написал файл" } : undefined),
183
+ check_app: { running: "Проверяю приложение", done: "Проверил приложение" },
184
+ }}
185
+ …
186
+ />;
187
+ ```
188
+
189
+ Свой скин может нарисовать простой вид сам — `WorkSteps` по docs/work-view.md (`WorkStepsView`: `live` с фразой или
190
+ `done` со `steps`, `count`, `open`). Без него шаги рисуются строкой `ToolCallRow`: «Сделано N шагов» в `title`, входа нет,
191
+ а список понятных фраз приходит в `output` строкой — скин покажет его как обычный результат вызова.
192
+
193
+ ### Patch Changes
194
+
195
+ - @ykurilov/agent-chat-core@0.45.0
196
+
197
+ ## 0.44.0
198
+
199
+ ### Minor Changes
200
+
201
+ - 6a2b5d9: Живые демонстрации: блок ```html-demo в ответе запускается в изолированной рамке (`sandbox="allow-scripts"`, строгий CSP,
202
+ наружу только высота). `agent.liveDemos` на сервере — одна постоянная строка инструкции; `liveDemos` у `AgentChat`,
203
+ `ChatWorkspace` и `AgentPanel`. Договор скина v22: необязательные `AgentText.renderDemo` и `ChatSkin.demoColors`, Тандем
204
+ умеет. Мессенджеры вместо блока пишут `liveDemoOnSite`, если у службы чата `liveDemos` (новое необязательное поле `ChatService.liveDemos`).
205
+ Код живёт в рамке внутри рамки: уйти на чужой адрес он не может, WebRTC убран. Выключатель: в чате с чужим текстом (веб-инструменты, файл человека, инструмент с `metadata: { externalContent: true }`)
206
+ демонстрации не запускаются — признак `ChatHistory.externalContent` и кусок потока `data-external-content`. Вложенные рамки
207
+ и `<link rel=preconnect>` в документе демонстрации запрещены. Всё необязательное, ломающих изменений нет. Как обновить
208
+ приложение — в CHANGES.md, раздел 0.44.0.
209
+
210
+ ### Patch Changes
211
+
212
+ - Updated dependencies [6a2b5d9]
213
+ - @ykurilov/agent-chat-core@0.44.0
214
+
215
+ ## 0.43.0
216
+
217
+ ### Patch Changes
218
+
219
+ - Updated dependencies [763f4c5]
220
+ - @ykurilov/agent-chat-core@0.43.0
221
+
222
+ ## 0.42.0
223
+
224
+ ### Patch Changes
225
+
226
+ - Updated dependencies [a385276]
227
+ - @ykurilov/agent-chat-core@0.42.0
228
+
229
+ ## 0.41.0
230
+
231
+ ### Minor Changes
232
+
233
+ - 9472fcb: Поправка на лету и английский интерфейс.
234
+
235
+ - `onTurnFinished` в `AgentChat` приходит и для ответа, закрытого ради поправки, — перед ответом на поправку. Раньше
236
+ событие получал только последний ответ, и действия под первым (например, «Вернуть эту версию») не появлялись.
237
+ Событие есть, даже если продолжение по поправке не стартовало (лимит расходов, чужие ходы, чат закрыт).
238
+ **Внимание:** при поправке на ходу `onTurnFinished` теперь приходит на каждый ответ — обработчик, который сохраняет
239
+ снимок или считает ходы, увидит 2 события и больше.
240
+ - Продолжение после поправки получает `place` самой свежей поправки, где он есть, иначе начала хода: служебная заметка
241
+ приложения уже новая, а поправка только с `tabId` место не стирает. Вкладка и пояс — от последней поправки: браузерные
242
+ инструменты продолжения идут на её вкладку. Кэш цел — блок места ложится в хвост поправки.
243
+ - `englishLabels` — полный английский словарь чата. `englishAttachmentsLabels`, `englishWebToolTitles`,
244
+ `englishHistorySearchTitles`, `englishMemoryToolTitles` (два последних — и из корня пакета); `withWebToolTitles` и
245
+ соседи берут словарь названий вторым аргументом (по умолчанию русский).
246
+
247
+ Как обновить: поднять версию. Английский интерфейс — `<ChatLabelsProvider labels={englishLabels}>` и
248
+ `createAttachmentsClient(englishAttachmentsLabels)` вместо своих словарей.
249
+
250
+ ### Patch Changes
251
+
252
+ - Updated dependencies [9472fcb]
253
+ - @ykurilov/agent-chat-core@0.41.0
254
+
255
+ ## 0.40.0
256
+
257
+ ### Patch Changes
258
+
259
+ - Updated dependencies [0e7aab3]
260
+ - @ykurilov/agent-chat-core@0.40.0
261
+
262
+ ## 0.39.1
263
+
264
+ ### Patch Changes
265
+
266
+ - @ykurilov/agent-chat-core@0.39.1
267
+
268
+ ## 0.39.0
269
+
270
+ ### Patch Changes
271
+
272
+ - Updated dependencies [3b90429]
273
+ - @ykurilov/agent-chat-core@0.39.0
274
+
275
+ ## 0.38.0
276
+
277
+ ### Minor Changes
278
+
279
+ - 4065a4a: Картинки для моделей без зрения. Зрение модели теперь решается для пары «модель + провайдер»: в профиле
280
+ `acceptsImagesByProvider: { together: false }` главнее `acceptsImages`, решение даёт `modelAcceptsImages(profile, providerId)`
281
+ из ядра, по нему меню моделей и вложения. В стандартном каталоге DeepSeek 4.1 Flash и GLM 5.3 Flash через Together
282
+ отмечены без зрения (у Together они только текстовые) — картинка туда больше не уходит, модель получает пометку.
283
+
284
+ Во вложениях:
285
+
286
+ - `createAttachments({ imagesForBlindModels: { toolName, marker?, always? } })` — модели без зрения вместо картинки идёт
287
+ постоянная плашка `[Картинка «shot.png», вложение <id>. Посмотреть: <toolName>.]`; к инструкции вложений дописывается
288
+ строка про неё. Без настройки — прежняя пометка «картинка не показана».
289
+ - `attachments.readChatImage({ chatId, attachmentId })` — картинка только этого чата для инструмента приложения
290
+ (`chatId` — из `AgentToolsModel.chatId`); чужое, не картинка, неверный номер — `undefined`.
291
+ - `createAttachments({ acceptedMediaTypes: ["image/png", "image/jpeg", "image/webp"] })` — файл другого типа отклоняется
292
+ `unsupported_type` до разбора и записи; поле ввода получает список из настроек и отказывает до загрузки.
293
+ Решает тип, с которым файл пришёл (поле записи `sourceMediaType`): ужатый в JPEG PNG при `["image/png"]` проходит.
294
+ Импорт чата вместо картинки неподходящего типа пишет «[картинка: имя]».
295
+ - `isAttachmentId` — из публичного входа.
296
+ - Снимок страницы (`page_screenshot`) тоже решает по паре «модель + провайдер».
297
+
298
+ Ничего не ломает: приложениям без этих настроек делать ничего не нужно. Как убрать свой обход — в CHANGES.md,
299
+ раздел 0.38.0 «Как обновить приложение».
300
+
301
+ ### Patch Changes
302
+
303
+ - Updated dependencies [1cae504]
304
+ - Updated dependencies [4065a4a]
305
+ - @ykurilov/agent-chat-core@0.38.0
306
+
307
+ ## 0.37.0
308
+
309
+ ### Patch Changes
310
+
311
+ - Updated dependencies [7f49d12]
312
+ - Updated dependencies [ea78982]
313
+ - @ykurilov/agent-chat-core@0.37.0
314
+
315
+ ## 0.36.0
316
+
317
+ ### Patch Changes
318
+
319
+ - Updated dependencies [3487fb4]
320
+ - Updated dependencies [8c43b86]
321
+ - Updated dependencies [6f42418]
322
+ - Updated dependencies [5f13c74]
323
+ - @ykurilov/agent-chat-core@0.36.0
324
+
325
+ ## 0.35.0
326
+
327
+ ### Patch Changes
328
+
329
+ - Updated dependencies [2382026]
330
+ - @ykurilov/agent-chat-core@0.35.0
331
+
332
+ ## 0.34.0
333
+
334
+ ### Patch Changes
335
+
336
+ - Updated dependencies [d039ce4]
337
+ - @ykurilov/agent-chat-core@0.34.0
338
+
339
+ ## 0.33.0
340
+
341
+ ### Patch Changes
342
+
343
+ - Updated dependencies [4a72339]
344
+ - @ykurilov/agent-chat-core@0.33.0
345
+
346
+ ## 0.32.0
347
+
348
+ ### Patch Changes
349
+
350
+ - Updated dependencies [71c32b7]
351
+ - Updated dependencies [cae13bf]
352
+ - Updated dependencies [a94bda9]
353
+ - Updated dependencies [4e44492]
354
+ - Updated dependencies [ac9b7d3]
355
+ - Updated dependencies [27f4b1e]
356
+ - @ykurilov/agent-chat-core@0.32.0
357
+
358
+ ## 0.31.2
359
+
360
+ ### Patch Changes
361
+
362
+ - @ykurilov/agent-chat-core@0.31.2
363
+
364
+ ## 0.31.1
365
+
366
+ ### Patch Changes
367
+
368
+ - @ykurilov/agent-chat-core@0.31.1
369
+
370
+ ## 0.31.0
371
+
372
+ ### Patch Changes
373
+
374
+ - @ykurilov/agent-chat-core@0.31.0
375
+
376
+ ## 0.30.0
377
+
378
+ ### Patch Changes
379
+
380
+ - @ykurilov/agent-chat-core@0.30.0
381
+
382
+ ## 0.29.0
383
+
384
+ ### Patch Changes
385
+
386
+ - @ykurilov/agent-chat-core@0.29.0
387
+
388
+ ## 0.28.0
389
+
390
+ ### Patch Changes
391
+
392
+ - Updated dependencies [11c3c97]
393
+ - Updated dependencies [d63ccaa]
394
+ - Updated dependencies [6a2f903]
395
+ - Updated dependencies [189cba9]
396
+ - @ykurilov/agent-chat-core@0.28.0
397
+
398
+ ## 0.27.0
399
+
400
+ ### Patch Changes
401
+
402
+ - Updated dependencies [d8341b2]
403
+ - Updated dependencies [5e4ed28]
404
+ - Updated dependencies [e0bb519]
405
+ - @ykurilov/agent-chat-core@0.27.0
406
+
407
+ ## 0.26.2
408
+
409
+ ### Patch Changes
410
+
411
+ - Updated dependencies [f24858a]
412
+ - @ykurilov/agent-chat-core@0.26.2
413
+
414
+ ## 0.26.1
415
+
416
+ ### Patch Changes
417
+
418
+ - @ykurilov/agent-chat-core@0.26.1
419
+
420
+ ## 0.26.0
421
+
422
+ ### Patch Changes
423
+
424
+ - Updated dependencies [eb43e47]
425
+ - @ykurilov/agent-chat-core@0.26.0
426
+
427
+ ## 0.25.0
428
+
429
+ ### Patch Changes
430
+
431
+ - Updated dependencies [99d426e]
432
+ - Updated dependencies [d8201f6]
433
+ - @ykurilov/agent-chat-core@0.25.0
434
+
435
+ ## 0.24.0
436
+
437
+ ### Patch Changes
438
+
439
+ - Updated dependencies [9b895cd]
440
+ - @ykurilov/agent-chat-core@0.24.0
441
+
442
+ ## 0.23.0
443
+
444
+ ### Patch Changes
445
+
446
+ - @ykurilov/agent-chat-core@0.23.0
447
+
448
+ ## 0.22.0
449
+
450
+ ### Patch Changes
451
+
452
+ - @ykurilov/agent-chat-core@0.22.0
453
+
454
+ ## 0.21.0
455
+
456
+ ### Patch Changes
457
+
458
+ - Updated dependencies [7c3bcc4]
459
+ - @ykurilov/agent-chat-core@0.21.0
460
+
461
+ ## 0.20.0
462
+
463
+ ### Patch Changes
464
+
465
+ - Updated dependencies [fd16b01]
466
+ - @ykurilov/agent-chat-core@0.20.0
467
+
468
+ ## 0.19.0
469
+
470
+ ### Patch Changes
471
+
472
+ - Updated dependencies [fde2297]
473
+ - Updated dependencies [aa0fd51]
474
+ - Updated dependencies [9f94dbe]
475
+ - Updated dependencies [2013f15]
476
+ - Updated dependencies [aa0fd51]
477
+ - Updated dependencies [05e258b]
478
+ - Updated dependencies [aa0fd51]
479
+ - @ykurilov/agent-chat-core@0.19.0
480
+
481
+ ## 0.18.6
482
+
483
+ ### Patch Changes
484
+
485
+ - @ykurilov/agent-chat-core@0.18.6
486
+
487
+ ## 0.18.5
488
+
489
+ ### Patch Changes
490
+
491
+ - @ykurilov/agent-chat-core@0.18.5
492
+
493
+ ## 0.18.4
494
+
495
+ ### Patch Changes
496
+
497
+ - @ykurilov/agent-chat-core@0.18.4
498
+
499
+ ## 0.18.3
500
+
501
+ ### Patch Changes
502
+
503
+ - @ykurilov/agent-chat-core@0.18.3
504
+
505
+ ## 0.18.2
506
+
507
+ ### Patch Changes
508
+
509
+ - @ykurilov/agent-chat-core@0.18.2
510
+
511
+ ## 0.18.1
512
+
513
+ ### Patch Changes
514
+
515
+ - @ykurilov/agent-chat-core@0.18.1
516
+
517
+ ## 0.18.0
518
+
519
+ ### Patch Changes
520
+
521
+ - Updated dependencies [43d7ebe]
522
+ - @ykurilov/agent-chat-core@0.18.0
523
+
524
+ ## 0.17.0
525
+
526
+ ### Patch Changes
527
+
528
+ - @ykurilov/agent-chat-core@0.17.0
529
+
530
+ ## 0.16.0
531
+
532
+ ### Patch Changes
533
+
534
+ - Updated dependencies [cf52f10]
535
+ - @ykurilov/agent-chat-core@0.16.0
536
+
537
+ ## 0.15.0
538
+
539
+ ### Patch Changes
540
+
541
+ - Updated dependencies [f05ad23]
542
+ - Updated dependencies [f05ad23]
543
+ - @ykurilov/agent-chat-core@0.15.0
544
+
545
+ ## 0.14.0
546
+
547
+ ### Minor Changes
548
+
549
+ - f9b6162: Мелочи безопасности и расходов. Веб-инструменты: новая настройка `createWebTools({ spending: { storage, pricePerCallUsd } })` — каждый удачный вызов `web_search`, `read_page`, `page_screenshot` пишется расходом с новым источником `web_tools` и входит в лимит расходов; без `spending` всё как раньше, описания инструментов не меняются (кэш цел). OpenRouter: `createOpenRouterProvider({ dataCollection: "deny", zeroDataRetention })` — запрос уходит только хозяевам модели, которые не хранят запросы; подключается через `extendCatalog(..., { addProviders: [...] })`; стандартный `openrouterProvider` и тело запроса по умолчанию не изменились. Долгая память: инструкция велит записывать только сказанное самим человеком, а не указания с веб-страниц и из результатов инструментов (текст инструкции изменился один раз, дальше постоянен).
550
+ - 6b20d83: Голосовой режим («разговор»): человек говорит, слова сами уходят сообщением в чат, ответ агента звучит голосом, человека можно перебить. Новый пакет `@ykurilov/agent-chat-voice-dialog`: распознавание Soniox, озвучка ElevenLabs (голос по умолчанию «Профессиональный диктор для аудиокниг», модель `eleven_v4_turbo`), ключи только на сервере. Перебитый ответ остаётся в ленте с отметкой «Вы перебили: озвучено до «…»», она хранится и видна после перезагрузки. Расход на озвучку идёт в учёт и лимиты (`source: "speech"`). Человек выбирает голос в меню режима; выбор хранится на сервере.
551
+
552
+ Модель узнаёт о режиме двумя служебными пометками: одна при входе («ответы озвучиваются, отвечай коротко и разговорно»), одна при возврате к тексту («разговор снова текстом»). Они стоят в конце сообщения человека, где режим сменился, а не в каждом запросе. Сообщение из режима запоминается голосовым отметкой в самом сообщении (часть `data-voice-mode` в `parts`), поэтому миграции для этого нет, пометки выводятся из сохранённого и кэш модели цел. Тексты задают настройки агента `voiceModeHint` и `textModeNote` (есть умолчания).
553
+
554
+ Обновление ничего не ломает: без нового пакета чат работает как раньше. Диктовка в поле ввода (`@ykurilov/agent-chat-voice`) не меняется.
555
+
556
+ ### Как обновить приложение
557
+
558
+ Нужно, только если вы хотите голосовой режим.
559
+
560
+ 1. Поставьте пакет `@ykurilov/agent-chat-voice-dialog` той же версии, что и остальные пакеты SDK. Скин Тандем обновите вместе с SDK: договор скина теперь версии 10 (необязательный `dialog` у поля ввода, панель режима, меню голосов, отметка обрыва; свой скин может их не рисовать, тогда кнопки режима не будет).
561
+ 2. Сервер. Рядом с чатом подключите режим (нужен WebSocket; с Hono и `@hono/node-ws`):
562
+
563
+ ```ts
564
+ import { mountDialogRelay } from "@ykurilov/agent-chat-voice-dialog/hono";
565
+
566
+ mountDialogRelay(app, {
567
+ path: "/api/voice-dialog",
568
+ upgradeWebSocket,
569
+ storage,
570
+ resolveUser, // тот же вход, что у чата
571
+ spendingLimits, // по желанию
572
+ logError: (message) => console.error(message),
573
+ speech: {
574
+ voices: [{ id: "oE0n0S3wK5Mj9C62iehn", name: "Профессиональный диктор для аудиокниг" }],
575
+ defaultVoiceId: "oE0n0S3wK5Mj9C62iehn",
576
+ pricePerThousandChars: { eleven_v4_turbo: 0.11, eleven_v4: 0.22 }, // ваша цена, $ за 1000 знаков
577
+ },
578
+ });
579
+ ```
580
+
581
+ Ключи `ELEVENLABS_API_KEY` и `SONIOX_API_KEY` — в окружении сервера. Next.js: WebSocket нужен свой Node-сервер, см. README пакета (`createDialogRelay`).
582
+ 3. Браузер:
583
+
584
+ ```tsx
585
+ const voiceDialog = createVoiceDialogEngine({ basePath: "/api/voice-dialog" });
586
+ <AgentChat api="/api/chat" skin={tandemSkin} voiceDialog={voiceDialog} />
587
+ ```
588
+
589
+ 4. Настройки. Слова остановки и междометия по умолчанию только русские; для другого языка задайте `bargeIn.stopWords` и `bargeIn.ignoreWords` у движка и `language` на сервере. Строгая политика содержимого страницы: добавьте `worklet-src blob:`.
590
+ 5. Хранилище. SQLite получает миграцию 0008, PostgreSQL — 0007 (схема `agent_chat`) сами при открытии базы. Свой `ChatStorage`: добавьте необязательные методы `setVoiceCut`, `getVoiceChoice`, `setVoiceChoice` (без них отметка обрыва и выбор голоса живут только до перезагрузки) и значение `"speech"` в `UsageSource`, если учёт расхода у вас свой.
591
+ 6. Свой экран (не наш скин): части сообщения с типом `data-voice-mode` не рисуйте, показывайте только текстовые части.
592
+ 7. Проверка: `pnpm typecheck` проходит; в чате появилась кнопка режима, после нажатия виден статус «Слушаю», фраза уходит сообщением, ответ звучит.
593
+
594
+ ### Patch Changes
595
+
596
+ - 96098be: Мелкие исправления (022). Символ с кодом ноль в первом сообщении больше не роняет отправку на Postgres: он выбрасывается из названия чата, из записей памяти и из сводки сжатия истории (иначе запись сжатия падала бы при каждой попытке); в самом тексте сообщения он лежит как раньше. Вложения отмечаются прикреплёнными до записи сообщения, а не после: если сервер упал между двумя шагами, чистка брошенных файлов не удалит их через сутки (файл, отмеченный зря, безвреден и уходит вместе с чатом). Во всех пакетах появилось поле `engines: { node: ">=22" }`; голосовой сервер (`createVoiceRelay`) и голосовой диалог (`createDialogRelay`) на Node 20 сразу при создании говорят понятной ошибкой, что нужен Node 22 (раньше падали при первом соединении; со своим `connectUpstream` проверки нет). В пакете вложений `react` и `@ykurilov/agent-chat-react` стали необязательными peer-зависимостями: серверу без экрана они больше не ставятся. Приложению, которое берёт `@ykurilov/agent-chat-attachments/react`, достаточно иметь их в проекте — для чата на экране они нужны и так; если они подтягивались только через вложения, добавьте их в зависимости приложения.
597
+ - be77ee2: Основа для надёжности хода агента (022). Новый вид ошибки `context_overflow` («Переписка не помещается в модель») у `ChatErrorKind` в ядре и в `react`, надпись `labels.errors.context_overflow` в русском словаре; Тандем показывает её сам. **Ломает:** исчерпывающий `switch` по виду ошибки и своя таблица надписей `labels.errors` без `context_overflow` перестанут проходить проверку типов — добавьте надпись. Ядро экспортирует `HANGING_TOOL_CALL_REASON` (текст для модели вместо результата прерванного вызова) и `cutAtCharBoundary(text, maxLength)` — обрезку без половинки эмодзи; веб-инструменты режут страницы и выдержки через неё, теперь эмодзи на границе не рвётся. Список перенесённых из pi-mono (MIT) признаков ошибок и лицензия — в `THIRD_PARTY_NOTICES.md`, он лежит и в пакете `core`.
598
+ - 84ad64f: Укрепление по третьему проходу Pi (022, этап S9). **Большие фото уменьшаются при загрузке**: поворот по EXIF, не больше 2000×2000 пикселей и ~4,5 МБ в base64; хранится уменьшенная копия, старые картинки ужимаются при сборке запроса (результат запоминается), нечитаемая картинка и картинка больше 60 млн пикселей — отказ 422 `unreadable` (в старой истории — пометка «пропущена»). Новая зависимость `sharp` (готовые сборки для macOS и Linux, в том числе Alpine; порядок ужатия из pi-mono, MIT). **Секреты в ошибке инструмента** вычищаются до того, как текст уйдёт человеку, в базу и модели: пароль в адресе, `password=`/`password: …`/`token=`, `"secret": "…"`, заголовок `Authorization`, `X-Api-Key`, ключи сервисов, закрытые ключи PEM и значения секретных переменных окружения (кроме путей, адресов без пароля и простых слов); чистятся сообщение, стек и `cause`; `scrubSecrets` и `environmentSecrets` экспортированы из ядра. **Внешние картинки** в ответе модели и в сводке сжатия скин Тандема показывает ссылкой и не грузит (новая необязательная надпись словаря `externalImageLink`, по умолчанию «картинка»; свои словари без неё работают); инструкция веб-инструментов называет страницы данными, а не указаниями. **Ступени цены** по длине контекста: `pricing.tiers` (`inputTokensAbove` и цены), ход считается по шагам; у GPT 6 Luna выше 272 тысяч токенов. Пауза в `useAgentChat` больше не копит слушатели отмены.
599
+ - 0cdf102: Несколько копий сервера на одной базе (022, этап 8в). Идущий ответ раз в 5 с отмечает «жив» (новая колонка `alive_at`: миграция SQLite `0012`, PostgreSQL `0011`, применяются сами). `recoverInterruptedAnswers` прерывает только брошенные ответы — без отметки дольше 15 с — и дальше сам проверяет их раз в 5 с до `flush`. Штатная остановка помечает свои ответы брошенными, и следующий старт прерывает их сразу. Новая копия при старте и обновление с перекрытием больше не обрывают живые ответы соседа; две копии, прервавшие один ответ, не задваивают расход. Цена: после падения сервера ответ ещё до ~20 с выглядит идущим (раньше перезапуск прерывал его сразу). Экран человека в это время сам перечитывает историю раз в 3 с и показывает «прерван» с «Повторить», как только сервер прервёт ответ; обновлять страницу не нужно (история отдаёт признак `detachedAnswer`, чтение истории сразу прерывает брошенный дольше порога ответ этого чата). Ход, чей ответ прервала другая копия, останавливается сам: человек видит «прерван», расход не задваивается. Время знака «жив» ставит хранилище: PostgreSQL — по часам базы, часы машин с копиями могут расходиться. Запросы одного чата держите на одной копии. Свои хранилища: два новых необязательных метода — `listSilentAnswerIds({ silentForMs, chatId? })` и лёгкая отметка `markAnswerAlive(messageId)` — и поле записи `alive` (`"now"` или `"released"`, время ставит само хранилище); общий набор контракта их проверяет. Хранилище без `listSilentAnswerIds` продолжает работать только с одной копией сервера: при старте `recoverInterruptedAnswers` прерывает все идущие ответы, проверок брошенных ответов дальше нет, а в журнал сервера пишется предупреждение. Без `markAnswerAlive` знак в тишине идёт полной записью ответа. Поле `alive` приходит в `insertMessage`, `updateStreamingMessage` и `updateAwaitingMessage`: если хранилище не ведёт знак, уберите поле перед записью, а не передавайте его в базу целиком. Переход на эту версию — один раз без перекрытия копий: старые копии не отмечают «жив», и новая прервала бы их ответы старше 15 с; сначала остановите все старые копии, потом запускайте новые. Дальше перекрытие безопасно. Если запрос истории попал не на ту копию, экран через 30 с сам покажет «прерван», хотя ответ идёт: держите запросы одного чата на одной копии. Сбой базы при конечной записи ответа повторяется через 1 и 3 с, а если не вышло — ответ остаётся для восстановления вместо вечного «идёт»; если запись прошла, а потерялся только ответ базы, повтор узнаёт свой итог и считает его удачным. Инструмент «по очереди», не слушающий отмену, после обрыва попытки держит очередь не дольше своего срока; очередь одна на чат, так что «Стоп» и сразу «Повторить» не запустят его второй раз параллельно. Восстановление пропускает ответ, на котором упало, с записью в журнал сервера, и прерывает остальные: битая запись не мешает серверу стартовать. Мелочи: адрес ответа вкладки на браузерный инструмент отвечает 413 `too_large` на слишком большое тело; неотвеченный запрос подтверждения закрывается только после сохранения нового сообщения, а если закрыть не вышло — повтор того же сообщения или «Повторить» доводят дело до конца; вызов веб-инструмента, оборванный «Стопом» или сбоем после отправки запроса, пишется в расход `web_tools`; картинки при загрузке ужимаются через очередь — разом не больше половины ядер (`limits.maxParallelImageFits`).
600
+ - Updated dependencies [4f33e85]
601
+ - Updated dependencies [15fbbcc]
602
+ - Updated dependencies [c09c1e2]
603
+ - Updated dependencies [062ce36]
604
+ - Updated dependencies [656233a]
605
+ - Updated dependencies [96098be]
606
+ - Updated dependencies [b6f4855]
607
+ - Updated dependencies [278a718]
608
+ - Updated dependencies [c1581f4]
609
+ - Updated dependencies [213bcb3]
610
+ - Updated dependencies [927c02c]
611
+ - Updated dependencies [be77ee2]
612
+ - Updated dependencies [8b59096]
613
+ - Updated dependencies [7fbc105]
614
+ - Updated dependencies [84ad64f]
615
+ - Updated dependencies [5027963]
616
+ - Updated dependencies [c2769dd]
617
+ - Updated dependencies [0cdf102]
618
+ - Updated dependencies [ba16989]
619
+ - Updated dependencies [aba59fe]
620
+ - Updated dependencies [47a56ac]
621
+ - Updated dependencies [f9b6162]
622
+ - Updated dependencies [f9b6162]
623
+ - Updated dependencies [f9b6162]
624
+ - Updated dependencies [1b2f9f1]
625
+ - Updated dependencies [0e8e0ae]
626
+ - Updated dependencies [6b20d83]
627
+ - Updated dependencies [d12dcf3]
628
+ - Updated dependencies [366d785]
629
+ - Updated dependencies [946e5d8]
630
+ - @ykurilov/agent-chat-core@0.14.0
631
+
632
+ ## 0.13.0
633
+
634
+ No changes in this release.
635
+
636
+ ## 0.12.0
637
+
638
+ No changes in this release.
639
+
640
+ ## 0.11.0
641
+
642
+ No changes in this release.
643
+
644
+ ## 0.10.0
645
+
646
+ No changes in this release.
647
+
648
+ ## 0.9.0
649
+
650
+ No changes in this release.
651
+
652
+ ## 0.8.0
653
+
654
+ No changes in this release.
655
+
656
+ ## 0.7.0
657
+
658
+ No changes in this release.
659
+
660
+ ## 0.6.0
661
+
662
+ No changes in this release.
663
+
664
+ ## 0.5.0
665
+
666
+ ### Minor Changes
667
+
668
+ - 2deeab3: Веб-инструменты стали строже к адресам, а лента показывает их результаты удобнее.
669
+
670
+ - Скачивание снимка страницы (его делает сервер приложения) больше не идёт по переходам вслепую: переходы выполняются вручную, не больше трёх, и каждый проходит проверку адреса. Имя дополнительно разрешается по DNS: если хоть один адрес частный, снимок не скачивается.
671
+ - Проверка адреса закрывает IPv4 внутри IPv6 (`[::7f00:1]`, `::ffff:`, `64:ff9b::`), `fec0::/10`, `100.64.0.0/10`, `192.0.0.0/24`, `198.18.0.0/15` и служебные диапазоны. Для чтения страниц проверяется только адрес до вызова Firecrawl (README пакета описывает границы честно).
672
+ - Снимки кэшируются в памяти сервера (до 20 штук, до 20 МБ, час): повторные ходы не качают одно и то же. Новая необязательная опция `resolveHost` у `createWebTools` (по умолчанию системный DNS).
673
+ - В результаты поиска и чтения попадают только адреса `http(s)`.
674
+ - Скин Тандем: ссылки в развёрнутой строке веб-инструмента кликабельны (только `http(s)`, новая вкладка, `rel="noopener noreferrer"`), снимок страницы рисуется картинкой (ленивая загрузка, ограниченный размер; при ошибке — текст и ссылка на страницу).
675
+ - В словарь `ChatLabels` добавлены два ключа: `screenshotAlt` и `screenshotUnavailable`.
676
+
677
+ ### Как обновить приложение
678
+
679
+ 1. Поднимите все пакеты `@ykurilov/agent-chat-*` до одной версии.
680
+ 2. Если приложение задаёт словарь надписей целиком, а не поверх `russianLabels`, добавьте в него `screenshotAlt` («Снимок страницы») и `screenshotUnavailable` («Снимок не загрузился.»); иначе `pnpm typecheck` покажет ошибку. Словарь вида `{ ...russianLabels, … }` ничего не требует.
681
+ 3. Если своя строка вызова (`ToolCallRow`) показывает результат веб-инструментов, при желании сделайте так же: ссылки только `http(s)` с `rel="noopener noreferrer"`, снимок картинкой с запасным текстом. Готовый пример — `skins/tandem/src/tool-call-row.tsx`.
682
+ 4. Для сервера, у которого во внутренней сети есть что-то ценное, запретите исходящие соединения в частные сети на уровне сети: окно DNS rebinding между проверкой и запросом остаётся.
683
+ - 61717c6: У агента появились веб-инструменты: поиск в интернете, чтение страницы и скриншот страницы. Они вынесены в новый необязательный пакет; приложение, которому они не нужны, его не ставит и ничего не получает.
684
+
685
+ - Новый пакет `@ykurilov/agent-chat-web-tools`: `createWebTools({ search, reader, screenshots? })` и готовые сервисы на Firecrawl `createFirecrawlServices({ apiKey, baseUrl?, headers? })` из подпути `@ykurilov/agent-chat-web-tools/firecrawl`. Сервис заменяется без правки инструментов (интерфейсы `WebSearchService`, `PageReaderService`, `PageScreenshotService`). Ключ и адрес сервиса остаются на сервере; `baseUrl` и `headers` позволяют идти через прокси. Подписи вызовов для ленты — `withWebToolTitles(russianLabels)` из подпути `@ykurilov/agent-chat-web-tools/labels`.
686
+ - Скриншот получают только модели с `acceptsImages: true`, у которых в профиле отмечено, что через выбранного провайдера они видят картинку в результате инструмента (`toolResultImageProviders`, см. запись про модели). Отмеченные в стандартном наборе: GPT 6 Luna и Gemini 3.8 Flash через OpenRouter.
687
+ - В `@ykurilov/agent-chat-core` `agent.tools` может быть функцией от выбранной модели: `(model: { profile, providerId }) => ToolSet`. Так набор инструментов зависит от модели. Обычный набор работает как раньше; экспортируются типы `AgentToolsSource` и `AgentToolsModel`.
688
+
689
+ ### Как обновить приложение
690
+
691
+ Только если нужны веб-инструменты. Остальным обновление ничего не требует.
692
+
693
+ 1. Поставьте пакет той же версии, что остальные: `pnpm add @ykurilov/agent-chat-web-tools`.
694
+ 2. На сервере (там, где `createChatHandler`) добавьте инструменты и инструкцию к ним. Ключ Firecrawl — в переменной окружения сервера, не в браузерной части:
695
+
696
+ ```ts
697
+ import { createWebTools, webToolsInstructions } from "@ykurilov/agent-chat-web-tools";
698
+ import { createFirecrawlServices } from "@ykurilov/agent-chat-web-tools/firecrawl";
699
+
700
+ const firecrawl = createFirecrawlServices({ apiKey: process.env.FIRECRAWL_API_KEY!, baseUrl: process.env.FIRECRAWL_BASE_URL });
701
+ const webTools = createWebTools(firecrawl);
702
+
703
+ createChatHandler({
704
+ // …
705
+ agent: {
706
+ instructions: `${appInstructions}\n${webToolsInstructions}`,
707
+ tools: (model) => ({ ...appTools, ...webTools(model) }),
708
+ },
709
+ });
710
+ ```
711
+
712
+ 3. В браузерной части подключите подписи: `<ChatLabelsProvider labels={withWebToolTitles(russianLabels)}>` вокруг `AgentChat` (`withWebToolTitles` — из `@ykurilov/agent-chat-web-tools/labels`).
713
+ 4. Проверьте: `pnpm typecheck`; спросите агента «Найди в интернете последнюю версию Node.js» — в ленте появятся строки «Поиск в интернете: готово» и «Чтение страницы: готово», в ответе — ссылка на источник.