@ykurilov/agent-chat-react 0.55.0 → 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 CHANGED
@@ -1,5 +1,23 @@
1
1
  # @ykurilov/agent-chat-react
2
2
 
3
+ ## 0.56.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 1eadba9: Библиотека готовых картинок: новый пакет `@ykurilov/agent-chat-image-library` с инструментами `find_images` и
8
+ `show_image` поверх каталога приложения. Картинка показывается по ширине ответа с подписью, по нажатию — окно просмотра.
9
+
10
+ - `images` у `AgentChat`, `ChatWorkspace`, `AgentPanel` принимает и список клиентов: `images={[imagesClient, imageLibraryClient]}`.
11
+ Одиночный клиент работает как раньше.
12
+ - Договор скина версии 26: у `GeneratedImages` необязательные `wide` и `caption`. Тандем их рисует. Скин версии 25
13
+ работает без правок: картинка будет плиткой ближайшей обычной пропорции (1:1, 3:2, 2:3, 16:9, 9:16) без подписи.
14
+
15
+ Подробно и как подключить — `docs/image-library.md`.
16
+
17
+ Отказ `show_image`, `show_video` и недоступный каталог в `find_images`, `find_videos` теперь ошибка инструмента (`ImageLibraryError`, `VideoLibraryError` с полем `kind`).
18
+ В ленте строка «ошибка» вместо зелёной галочки, модель получает тот же текст. Код, который читал `{ отказ }` из
19
+ результата `show_video` или `find_videos`, должен смотреть на `state: "output-error"` у части сообщения.
20
+
3
21
  ## 0.55.0
4
22
 
5
23
  ### Minor Changes
package/README.md CHANGED
@@ -35,6 +35,10 @@ import { AgentChat, ChatLabelsProvider, russianLabels } from "@ykurilov/agent-ch
35
35
  (`text`, `staffName`) — не пузырём человека. Договор скина версии 25; скин версии 24 работает без правок: реплика
36
36
  показывается ответом агента с подписью `labels.notices.staffSaid` («Сотрудник Ольга») —
37
37
  [docs/skin-v25.md](https://github.com/ykurilov/agent-chat-sdk/blob/main/docs/skin-v25.md).
38
+ - Картинка библиотеки (`show_image`, пакет `@ykurilov/agent-chat-image-library`) приходит в `GeneratedImages` с
39
+ необязательными `wide` (по ширине ответа со своей пропорцией) и `caption` (подпись под картинкой). Договор скина
40
+ версии 26; скин версии 25 работает без правок: плитка ближайшей обычной пропорции без подписи —
41
+ [docs/skin-v26.md](https://github.com/ykurilov/agent-chat-sdk/blob/main/docs/skin-v26.md).
38
42
  - `ChatWorkspace` — список чатов и открытый чат вместе: создать, переименовать, удалить (нужен `chatList: true` на сервере). Хук — `useChatList`. Скину дополнительно нужны `ChatWorkspace` и `ChatList` (`ChatListSkin`, договор версии 7).
39
43
  - `AgentMemory` — экран долгой памяти агента: записи по разделам, добавить, изменить, удалить, «Стереть всю память» (нужна опция `memory` на сервере, пакет `@ykurilov/agent-chat-memory`). `api` — `createMemoryApi({ api: "/api/chat" })`, создавать один раз; `skin` — `MemorySkin` (`tandemMemorySkin`). Хук — `useMemoryNotes`. Без памяти на сервере экран пишет, что память не включена. Договор скина версии 11 — отдельный `MemorySkin`, `ChatSkin` не менялся ([contracts/memory.md](../../specs/017-long-term-memory/contracts/memory.md)).
40
44
  - Панель агента: вход `@ykurilov/agent-chat-react/panel`; основной вход его не подтягивает. `AgentPanelProvider` ставится в корневой макет выше страниц (`api`, `userKey`, `browserTools`, `mode` — `overlay` или `push`, `width`, `onDataChanged`, `fetch` — свой `fetch` только для списка чатов), `AgentPanel` рисует кнопку, рамку и чат через скин. Хуки: `useAgentPanel` (`open`, `openChat`, `openNewChat({ draft })`, `pageInset` — отступ страницы в режиме `push`, на экране ≤ 640 px он 0, `busy`), `useAgentPlace({ description, data? })` (где человек; модель видит только описание, `data` — только инструменты), `useAgentDataChanges(tag, handler)` (страница узнаёт, что инструмент изменил данные). Браузерные инструменты — функции в `browserTools` с теми же именами, что описания на сервере (`BrowserToolImplementations`); нет функции — модель получает «Инструмент недоступен на этой странице» (надпись `agentPanelToolUnavailable`). Подробно — [docs/getting-started.md](../../docs/getting-started.md#панель-агента-в-приложении-по-желанию). Общие части: `AgentAppBridge` (связь чата с приложением; `appBridge` в `AgentChat`, `useAgentChat`, `ChatWorkspace`), `initialDraft` (текст в поле ввода при открытии чата), `rememberKey` в `useChatList` (свой ключ запомненного чата). Договор скина версии 12 — отдельный `AgentPanelSkin` (`AgentPanelLauncher`, `AgentPanel`), надписи `agentPanel…` в словаре; `ChatSkin`, `ChatListSkin` и `MemorySkin` не менялись ([contracts/skin.md](../../specs/021-agent-panel/contracts/skin.md)).
@@ -4682,9 +4682,11 @@ function describeWithViewer(describe, open) {
4682
4682
  // src/media-viewer/generated-images.ts
4683
4683
  import { getToolName as getToolName2, isToolUIPart } from "ai";
4684
4684
  var noOpen2 = () => void 0;
4685
+ var imageClientsOf = (images) => images === void 0 ? [] : Array.isArray(images) ? images : [images];
4685
4686
  function describeGeneratedImages(images, call) {
4686
4687
  const openImage = call.open ?? noOpen2;
4687
- return (part) => getToolName2(part) === images.toolName ? images.describe({ part, api: call.api, chatId: call.chatId, openImage }) : void 0;
4688
+ const byTool = new Map(imageClientsOf(images).map((client) => [client.toolName, client]));
4689
+ return (part) => byTool.get(getToolName2(part))?.describe({ part, api: call.api, chatId: call.chatId, openImage });
4688
4690
  }
4689
4691
  function generatedViewerItems(describe) {
4690
4692
  return (message) => {
@@ -5740,18 +5742,19 @@ function AgentChatBody({ api, chatId, skin, liveness, voice, voiceDialog, attach
5740
5742
  const dialog = useVoiceDialog({ engine: voiceDialog, chatId, chat, ...videos && { videos } });
5741
5743
  const attachments = attachmentsPlugin?.useController({ api, chatId, modelSeesImages: chatModelSeesImages });
5742
5744
  const describeFiles = attachments?.describe;
5745
+ const imageClients = useSameList(imageClientsOf(images));
5743
5746
  const extensions = useMemo15(
5744
5747
  () => ({
5745
5748
  ...widgets && { widgets },
5746
5749
  ...diagrams && { diagrams },
5747
5750
  ...liveDemos && { liveDemos },
5748
- ...images && { images },
5751
+ ...imageClients.length > 0 && { images: imageClients },
5749
5752
  ...videos && { videos },
5750
5753
  ...appEvents && { appEvents },
5751
5754
  ...workView && { workView },
5752
5755
  ...stepPhrases && { stepPhrases }
5753
5756
  }),
5754
- [widgets, diagrams, liveDemos, images, videos, appEvents, workView, stepPhrases]
5757
+ [widgets, diagrams, liveDemos, imageClients, videos, appEvents, workView, stepPhrases]
5755
5758
  );
5756
5759
  const scrollRef = useRef16(null);
5757
5760
  const feedRef = useRef16(null);
@@ -5821,7 +5824,7 @@ function AgentChatBody({ api, chatId, skin, liveness, voice, voiceDialog, attach
5821
5824
  const [editingAnswerId, setEditingAnswerId] = useState17(null);
5822
5825
  const saving = useRef16(false);
5823
5826
  const [feedView, setFeedView] = useState17({ epoch: 0 });
5824
- const imagesShown = images && skin.GeneratedImages ? images : void 0;
5827
+ const imagesShown = imageClients.length > 0 && skin.GeneratedImages ? imageClients : void 0;
5825
5828
  const viewerImages = useMemo15(() => imagesShown && generatedViewerItems(describeGeneratedImages(imagesShown, { api, chatId })), [imagesShown, api, chatId]);
5826
5829
  const getViewerItems = useCallback16(
5827
5830
  () => collectViewerItems({ messages: chat.messages, describeAttachments: describeFiles, extraItems: viewerImages }),
@@ -6558,6 +6561,11 @@ function approvalProps(part, controls) {
6558
6561
  if (part.state === "output-denied" || approval.approved === false) return { approval: { state: "denied" } };
6559
6562
  return { approval: { state: approval.reason === ALWAYS_IN_CHAT ? "always" : "allowed" } };
6560
6563
  }
6564
+ function useSameList(list) {
6565
+ const kept = useRef16(list);
6566
+ if (kept.current.length !== list.length || kept.current.some((item, index) => item !== list[index])) kept.current = list;
6567
+ return kept.current;
6568
+ }
6561
6569
 
6562
6570
  // src/chat-list/use-chat-list.ts
6563
6571
  import { useCallback as useCallback17, useEffect as useEffect15, useRef as useRef17, useState as useState18 } from "react";
@@ -6956,4 +6964,4 @@ export {
6956
6964
  activeChatTitle,
6957
6965
  useWorkspaceListSync
6958
6966
  };
6959
- //# sourceMappingURL=chunk-JZQ7ZOJI.js.map
6967
+ //# sourceMappingURL=chunk-7DVTSVKQ.js.map