@gravity-ui/aikit 2.24.1-beta.883c85d04b93d8521b2733baa3e86da20249b4e7.0 → 2.25.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 (118) hide show
  1. package/build/cjs/components/molecules/PromptInputBody/PromptInputBody.d.ts +1 -0
  2. package/build/cjs/components/molecules/PromptInputBody/PromptInputBody.js +2 -8
  3. package/build/cjs/components/molecules/PromptInputBody/PromptInputBody.js.map +1 -1
  4. package/build/cjs/components/organisms/PromptInput/PromptInput.css +37 -0
  5. package/build/cjs/components/organisms/PromptInput/PromptInput.d.ts +13 -2
  6. package/build/cjs/components/organisms/PromptInput/PromptInput.js +64 -3
  7. package/build/cjs/components/organisms/PromptInput/PromptInput.js.map +1 -1
  8. package/build/cjs/components/organisms/PromptInput/PromptInputCommands.d.ts +9 -0
  9. package/build/cjs/components/organisms/PromptInput/PromptInputCommands.js +39 -0
  10. package/build/cjs/components/organisms/PromptInput/PromptInputCommands.js.map +1 -0
  11. package/build/cjs/components/organisms/PromptInput/PromptInputFull.d.ts +2 -0
  12. package/build/cjs/components/organisms/PromptInput/PromptInputFull.js +4 -4
  13. package/build/cjs/components/organisms/PromptInput/PromptInputFull.js.map +1 -1
  14. package/build/cjs/components/organisms/PromptInput/PromptInputSimple.d.ts +2 -0
  15. package/build/cjs/components/organisms/PromptInput/PromptInputSimple.js +3 -3
  16. package/build/cjs/components/organisms/PromptInput/PromptInputSimple.js.map +1 -1
  17. package/build/cjs/components/organisms/PromptInput/commandUtils.d.ts +13 -0
  18. package/build/cjs/components/organisms/PromptInput/commandUtils.js +27 -0
  19. package/build/cjs/components/organisms/PromptInput/commandUtils.js.map +1 -0
  20. package/build/cjs/components/organisms/PromptInput/i18n/en.json +8 -0
  21. package/build/cjs/components/organisms/PromptInput/i18n/index.d.ts +13 -0
  22. package/build/cjs/components/organisms/PromptInput/i18n/index.js +10 -0
  23. package/build/cjs/components/organisms/PromptInput/i18n/index.js.map +1 -0
  24. package/build/cjs/components/organisms/PromptInput/i18n/ru.json +8 -0
  25. package/build/cjs/components/organisms/PromptInput/index.d.ts +2 -1
  26. package/build/cjs/components/organisms/PromptInput/index.js.map +1 -1
  27. package/build/cjs/components/organisms/PromptInput/types.d.ts +1 -0
  28. package/build/cjs/components/organisms/PromptInput/types.js.map +1 -1
  29. package/build/cjs/components/organisms/PromptInput/usePromptCommands.d.ts +41 -0
  30. package/build/cjs/components/organisms/PromptInput/usePromptCommands.js +222 -0
  31. package/build/cjs/components/organisms/PromptInput/usePromptCommands.js.map +1 -0
  32. package/build/cjs/components/organisms/PromptInput/usePromptInput.d.ts +10 -1
  33. package/build/cjs/components/organisms/PromptInput/usePromptInput.js +100 -11
  34. package/build/cjs/components/organisms/PromptInput/usePromptInput.js.map +1 -1
  35. package/build/cjs/components/pages/AIStudioChat/AIStudioChat.js +139 -52
  36. package/build/cjs/components/pages/AIStudioChat/AIStudioChat.js.map +1 -1
  37. package/build/cjs/components/pages/AIStudioChat/request.d.ts +4 -0
  38. package/build/cjs/components/pages/AIStudioChat/request.js +11 -0
  39. package/build/cjs/components/pages/AIStudioChat/request.js.map +1 -0
  40. package/build/cjs/components/pages/AIStudioChat/types.d.ts +5 -5
  41. package/build/cjs/components/pages/AIStudioChat/types.js.map +1 -1
  42. package/build/cjs/components/pages/ChatContainer/ChatContainer.js +10 -4
  43. package/build/cjs/components/pages/ChatContainer/ChatContainer.js.map +1 -1
  44. package/build/cjs/components/pages/ChatContainer/types.d.ts +1 -1
  45. package/build/cjs/components/pages/ChatContainer/types.js.map +1 -1
  46. package/build/cjs/components/pages/ChatContainer/useChatContainer.d.ts +1 -0
  47. package/build/cjs/components/pages/ChatContainer/useChatContainer.js +5 -1
  48. package/build/cjs/components/pages/ChatContainer/useChatContainer.js.map +1 -1
  49. package/build/cjs/package.json +1 -1
  50. package/build/cjs/types/index.d.ts +1 -0
  51. package/build/cjs/types/index.js +1 -0
  52. package/build/cjs/types/index.js.map +1 -1
  53. package/build/cjs/types/messages.d.ts +3 -0
  54. package/build/cjs/types/messages.js.map +1 -1
  55. package/build/cjs/types/promptCommands.d.ts +44 -0
  56. package/build/cjs/types/promptCommands.js +3 -0
  57. package/build/cjs/types/promptCommands.js.map +1 -0
  58. package/build/docs/components/molecules/PromptInputBody.md +16 -15
  59. package/build/docs/components/organisms/PromptInput.md +151 -0
  60. package/build/docs/components/pages/AIStudioChat.md +38 -0
  61. package/build/esm/components/molecules/PromptInputBody/PromptInputBody.d.ts +1 -0
  62. package/build/esm/components/molecules/PromptInputBody/PromptInputBody.js +2 -8
  63. package/build/esm/components/molecules/PromptInputBody/PromptInputBody.js.map +1 -1
  64. package/build/esm/components/organisms/PromptInput/PromptInput.css +37 -0
  65. package/build/esm/components/organisms/PromptInput/PromptInput.d.ts +13 -2
  66. package/build/esm/components/organisms/PromptInput/PromptInput.js +65 -4
  67. package/build/esm/components/organisms/PromptInput/PromptInput.js.map +1 -1
  68. package/build/esm/components/organisms/PromptInput/PromptInputCommands.d.ts +9 -0
  69. package/build/esm/components/organisms/PromptInput/PromptInputCommands.js +36 -0
  70. package/build/esm/components/organisms/PromptInput/PromptInputCommands.js.map +1 -0
  71. package/build/esm/components/organisms/PromptInput/PromptInputFull.d.ts +2 -0
  72. package/build/esm/components/organisms/PromptInput/PromptInputFull.js +4 -4
  73. package/build/esm/components/organisms/PromptInput/PromptInputFull.js.map +1 -1
  74. package/build/esm/components/organisms/PromptInput/PromptInputSimple.d.ts +2 -0
  75. package/build/esm/components/organisms/PromptInput/PromptInputSimple.js +3 -3
  76. package/build/esm/components/organisms/PromptInput/PromptInputSimple.js.map +1 -1
  77. package/build/esm/components/organisms/PromptInput/commandUtils.d.ts +13 -0
  78. package/build/esm/components/organisms/PromptInput/commandUtils.js +23 -0
  79. package/build/esm/components/organisms/PromptInput/commandUtils.js.map +1 -0
  80. package/build/esm/components/organisms/PromptInput/i18n/en.json +8 -0
  81. package/build/esm/components/organisms/PromptInput/i18n/index.d.ts +13 -0
  82. package/build/esm/components/organisms/PromptInput/i18n/index.js +6 -0
  83. package/build/esm/components/organisms/PromptInput/i18n/index.js.map +1 -0
  84. package/build/esm/components/organisms/PromptInput/i18n/ru.json +8 -0
  85. package/build/esm/components/organisms/PromptInput/index.d.ts +2 -1
  86. package/build/esm/components/organisms/PromptInput/index.js.map +1 -1
  87. package/build/esm/components/organisms/PromptInput/types.d.ts +1 -0
  88. package/build/esm/components/organisms/PromptInput/types.js.map +1 -1
  89. package/build/esm/components/organisms/PromptInput/usePromptCommands.d.ts +41 -0
  90. package/build/esm/components/organisms/PromptInput/usePromptCommands.js +219 -0
  91. package/build/esm/components/organisms/PromptInput/usePromptCommands.js.map +1 -0
  92. package/build/esm/components/organisms/PromptInput/usePromptInput.d.ts +10 -1
  93. package/build/esm/components/organisms/PromptInput/usePromptInput.js +101 -12
  94. package/build/esm/components/organisms/PromptInput/usePromptInput.js.map +1 -1
  95. package/build/esm/components/pages/AIStudioChat/AIStudioChat.js +139 -52
  96. package/build/esm/components/pages/AIStudioChat/AIStudioChat.js.map +1 -1
  97. package/build/esm/components/pages/AIStudioChat/request.d.ts +4 -0
  98. package/build/esm/components/pages/AIStudioChat/request.js +8 -0
  99. package/build/esm/components/pages/AIStudioChat/request.js.map +1 -0
  100. package/build/esm/components/pages/AIStudioChat/types.d.ts +5 -5
  101. package/build/esm/components/pages/AIStudioChat/types.js.map +1 -1
  102. package/build/esm/components/pages/ChatContainer/ChatContainer.js +12 -6
  103. package/build/esm/components/pages/ChatContainer/ChatContainer.js.map +1 -1
  104. package/build/esm/components/pages/ChatContainer/types.d.ts +1 -1
  105. package/build/esm/components/pages/ChatContainer/types.js.map +1 -1
  106. package/build/esm/components/pages/ChatContainer/useChatContainer.d.ts +1 -0
  107. package/build/esm/components/pages/ChatContainer/useChatContainer.js +5 -1
  108. package/build/esm/components/pages/ChatContainer/useChatContainer.js.map +1 -1
  109. package/build/esm/package.json +1 -1
  110. package/build/esm/types/index.d.ts +1 -0
  111. package/build/esm/types/index.js +1 -0
  112. package/build/esm/types/index.js.map +1 -1
  113. package/build/esm/types/messages.d.ts +3 -0
  114. package/build/esm/types/messages.js.map +1 -1
  115. package/build/esm/types/promptCommands.d.ts +44 -0
  116. package/build/esm/types/promptCommands.js +2 -0
  117. package/build/esm/types/promptCommands.js.map +1 -0
  118. package/package.json +1 -1
@@ -1,6 +1,7 @@
1
1
  import { __rest } from "tslib";
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
4
+ import { useForkRef } from '@gravity-ui/uikit';
4
5
  import { v4 as uuidv4 } from 'uuid';
5
6
  import { fetchResponseToStreamEvents, useOpenAIStreamAdapter } from "../../../adapters/openai/index.js";
6
7
  import { BaseMessageActionType } from "../../../types/index.js";
@@ -8,6 +9,7 @@ import { createMessageRendererRegistry, mergeMessageRendererRegistries, register
8
9
  import { InputContextProvider, useInputContext } from "../../molecules/InputContext/index.js";
9
10
  import { ChatContainer } from "../ChatContainer/index.js";
10
11
  import { McpToolRenderer } from "./McpToolRenderer.js";
12
+ import { serializeChatRequest } from "./request.js";
11
13
  import { normalizeMcpCallIds, omitMcpListToolsEvents } from "./transforms/index.js";
12
14
  function isFileAttachment(value) {
13
15
  if (!value || typeof value !== 'object')
@@ -74,9 +76,21 @@ export function AIStudioChat(props) {
74
76
  return (_jsx(InputContextProvider, { fileUpload: fileUpload, fileDialogTitle: fileDialogTitle, children: _jsx(AIStudioChatInner, Object.assign({}, rest)) }));
75
77
  }
76
78
  function AIStudioChatInner(props) {
77
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
78
- const { apiUrl, initialMessages = [], showHistory = false, showNewChat = showHistory, systemPrompt, requestInit, extraRequestParams, trackTokenUsage = true, onBeforeSend } = props, chatContainerProps = __rest(props, ["apiUrl", "initialMessages", "showHistory", "showNewChat", "systemPrompt", "requestInit", "extraRequestParams", "trackTokenUsage", "onBeforeSend"]);
79
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
80
+ const { apiUrl, initialMessages = [], showHistory = false, showNewChat = showHistory, systemPrompt, requestInit, extraRequestParams, trackTokenUsage = true, onBeforeSend, transformRequest } = props, chatContainerProps = __rest(props, ["apiUrl", "initialMessages", "showHistory", "showNewChat", "systemPrompt", "requestInit", "extraRequestParams", "trackTokenUsage", "onBeforeSend", "transformRequest"]);
79
81
  const { prepareFilesForSend, reset, contextItems, attachmentContent } = useInputContext();
82
+ const promptApiRef = useRef(null);
83
+ const mergedPromptApiRef = useForkRef(promptApiRef, (_a = chatContainerProps.promptInputProps) === null || _a === void 0 ? void 0 : _a.apiRef);
84
+ const fileDraftKey = JSON.stringify(contextItems.map((item) => item.id));
85
+ const latestFileDraftKey = useRef(fileDraftKey);
86
+ latestFileDraftKey.current = fileDraftKey;
87
+ const failedFileDraftKey = useRef();
88
+ // Keep the exact mapped request for retry, independently of later draft selections.
89
+ const sentRequests = useRef(new Map());
90
+ const sendEpoch = useRef(0);
91
+ const [commandsResetKey, setCommandsResetKey] = useState(0);
92
+ const [sendError, setSendError] = useState(null);
93
+ const [failedAttempt, setFailedAttempt] = useState(null);
80
94
  // Current chat messages
81
95
  const [messages, setMessages] = useState(initialMessages);
82
96
  // Multi-chat state (used when showHistory=true)
@@ -111,8 +125,8 @@ function AIStudioChatInner(props) {
111
125
  }
112
126
  }, []);
113
127
  const streamResult = useOpenAIStreamAdapter(streamSource, {
114
- initialMessages: (_a = streamOptions === null || streamOptions === void 0 ? void 0 : streamOptions.initialMessages) !== null && _a !== void 0 ? _a : [],
115
- assistantMessageId: (_b = streamOptions === null || streamOptions === void 0 ? void 0 : streamOptions.assistantMessageId) !== null && _b !== void 0 ? _b : 'assistant-idle',
128
+ initialMessages: (_b = streamOptions === null || streamOptions === void 0 ? void 0 : streamOptions.initialMessages) !== null && _b !== void 0 ? _b : [],
129
+ assistantMessageId: (_c = streamOptions === null || streamOptions === void 0 ? void 0 : streamOptions.assistantMessageId) !== null && _c !== void 0 ? _c : 'assistant-idle',
116
130
  onStreamEnd: handleStreamEnd,
117
131
  trackTokenUsage,
118
132
  });
@@ -123,43 +137,35 @@ function AIStudioChatInner(props) {
123
137
  }
124
138
  }, [streamResult.responseId]);
125
139
  const hasSource = Boolean(streamSource);
126
- const displayMessages = hasSource && streamResult.messages.length > 0 ? streamResult.messages : messages;
140
+ const pendingMessages = failedAttempt ? [...messages, failedAttempt.message] : messages;
141
+ const displayMessages = hasSource && streamResult.messages.length > 0 ? streamResult.messages : pendingMessages;
127
142
  const status = useMemo(() => {
128
143
  if (!hasSource) {
129
- return isFetching ? 'submitted' : 'ready';
144
+ if (isFetching)
145
+ return 'submitted';
146
+ return sendError ? 'error' : 'ready';
130
147
  }
131
148
  if (streamResult.status === 'streaming')
132
149
  return 'streaming';
133
150
  if (streamResult.status === 'error')
134
151
  return 'error';
135
152
  return 'ready';
136
- }, [hasSource, isFetching, streamResult.status]);
153
+ }, [hasSource, isFetching, streamResult.status, sendError]);
137
154
  /**
138
155
  * Core send function. Takes an already-resolved set of previous messages and
139
156
  * pre-converted base64 images so it can be called both from handleSendMessage
140
157
  * (which converts File objects) and from handleRetry (which reuses stored images).
141
158
  */
142
- const performSend = useCallback(async ({ previousMessages, content, base64Images = [], perSendParams = {}, }) => {
143
- // Auto-create a chat when history is enabled and no chat is active yet
144
- if (showHistory && !activeChatRef.current) {
145
- const newChat = {
146
- id: uuidv4(),
147
- name: deriveChatName(content),
148
- createTime: new Date().toISOString(),
149
- };
150
- chatMessagesRef.current[newChat.id] = [];
151
- activeChatRef.current = newChat;
152
- setActiveChat(newChat);
153
- setChats((prev) => [newChat, ...prev]);
154
- }
159
+ const performSend = useCallback(async ({ previousMessages, content, base64Images = [], perSendParams = {}, submitData, retryRequest, }) => {
155
160
  const rawFileIds = Array.isArray(perSendParams.fileIds)
156
161
  ? perSendParams.fileIds
157
162
  : undefined;
158
163
  const rawFileAttachments = Array.isArray(perSendParams.fileAttachments)
159
164
  ? perSendParams.fileAttachments.filter(isFileAttachment)
160
165
  : undefined;
166
+ const userMessageId = uuidv4();
161
167
  const userMessage = {
162
- id: uuidv4(),
168
+ id: userMessageId,
163
169
  role: 'user',
164
170
  content,
165
171
  images: base64Images.length > 0 ? base64Images : undefined,
@@ -167,8 +173,10 @@ function AIStudioChatInner(props) {
167
173
  };
168
174
  const messagesWithUser = [...previousMessages, userMessage];
169
175
  const assistantMessageId = uuidv4();
170
- setMessages(messagesWithUser);
176
+ const epoch = sendEpoch.current;
171
177
  setIsFetching(true);
178
+ setSendError(null);
179
+ setFailedAttempt(null);
172
180
  const abortController = new AbortController();
173
181
  setController(abortController);
174
182
  try {
@@ -192,61 +200,114 @@ function AIStudioChatInner(props) {
192
200
  })),
193
201
  { role: 'user', content: lastUserContent },
194
202
  ];
195
- const response = await fetch(apiUrl, Object.assign(Object.assign({}, requestInit), { method: 'POST', headers: Object.assign({ 'Content-Type': 'application/json', Accept: 'text/event-stream' }, requestInit === null || requestInit === void 0 ? void 0 : requestInit.headers), body: JSON.stringify(Object.assign(Object.assign(Object.assign({ messages: apiMessages }, extraRequestParams), perSendParams), (responseIdRef.current
196
- ? { previousResponseId: responseIdRef.current }
197
- : {}))), signal: abortController.signal }));
203
+ const baseRequest = Object.assign(Object.assign(Object.assign({ messages: apiMessages }, extraRequestParams), perSendParams), (responseIdRef.current ? { previousResponseId: responseIdRef.current } : {}));
204
+ const body = await serializeChatRequest(baseRequest, submitData !== null && submitData !== void 0 ? submitData : { content }, transformRequest, retryRequest);
205
+ if (body === false || epoch !== sendEpoch.current)
206
+ return false;
207
+ sentRequests.current.set(userMessageId, body);
208
+ // Auto-create a chat when history is enabled and no chat is active yet
209
+ if (showHistory && !activeChatRef.current) {
210
+ const newChat = {
211
+ id: uuidv4(),
212
+ name: deriveChatName(content),
213
+ createTime: new Date().toISOString(),
214
+ };
215
+ chatMessagesRef.current[newChat.id] = [];
216
+ activeChatRef.current = newChat;
217
+ setActiveChat(newChat);
218
+ setChats((prev) => [newChat, ...prev]);
219
+ }
220
+ setMessages(messagesWithUser);
221
+ const response = await fetch(apiUrl, Object.assign(Object.assign({}, requestInit), { method: 'POST', headers: Object.assign({ 'Content-Type': 'application/json', Accept: 'text/event-stream' }, requestInit === null || requestInit === void 0 ? void 0 : requestInit.headers), body, signal: abortController.signal }));
222
+ if (epoch !== sendEpoch.current)
223
+ return false;
198
224
  if (!response.ok) {
199
225
  throw new Error(`API error: ${response.status} ${response.statusText}`);
200
226
  }
201
227
  setStreamSource(normalizeMcpCallIds(omitMcpListToolsEvents(fetchResponseToStreamEvents(response))));
202
228
  setStreamOptions({ initialMessages: messagesWithUser, assistantMessageId });
229
+ return true;
203
230
  }
204
231
  catch (error) {
232
+ if (epoch !== sendEpoch.current)
233
+ return false;
234
+ // Roll back the optimistic attempt; errors and failed messages are UI state only.
235
+ setMessages(previousMessages);
205
236
  if (error.name !== 'AbortError') {
206
- const errorMessage = {
207
- id: uuidv4(),
208
- role: 'assistant',
209
- content: error.message,
210
- };
211
- setMessages((prev) => {
212
- const filtered = prev.filter((msg) => msg.role !== 'assistant' || getMessageTextContent(msg) !== '');
213
- return [...filtered, errorMessage];
237
+ setSendError(error instanceof Error ? error : new Error(String(error)));
238
+ setFailedAttempt({
239
+ message: userMessage,
240
+ request: {
241
+ previousMessages,
242
+ content,
243
+ base64Images,
244
+ perSendParams,
245
+ submitData,
246
+ retryRequest: sentRequests.current.get(userMessageId),
247
+ },
214
248
  });
215
249
  }
216
250
  setStreamSource(null);
217
251
  setStreamOptions(null);
252
+ return false;
218
253
  }
219
254
  finally {
220
- setIsFetching(false);
221
- setController(null);
255
+ if (epoch === sendEpoch.current) {
256
+ setIsFetching(false);
257
+ setController(null);
258
+ }
222
259
  }
223
- }, [showHistory, systemPrompt, requestInit, apiUrl, extraRequestParams]);
260
+ }, [showHistory, systemPrompt, requestInit, apiUrl, extraRequestParams, transformRequest]);
224
261
  const handleSendMessage = useCallback(async (data) => {
262
+ const epoch = sendEpoch.current;
225
263
  // Call onBeforeSend hook — allows caller to inject per-request params or cancel send
226
264
  let perSendParams = {};
227
265
  if (onBeforeSend) {
228
- const result = await onBeforeSend({ content: data.content });
266
+ const result = await onBeforeSend(data);
229
267
  if (result === false || result === null)
230
- return;
268
+ return false;
231
269
  if (result)
232
270
  perSendParams = result;
233
271
  }
234
272
  const { base64Images, perSendFileParams } = await prepareFilesForSend(data.attachments);
235
- await performSend({
273
+ if (epoch !== sendEpoch.current)
274
+ return false;
275
+ const accepted = await performSend({
276
+ submitData: data,
236
277
  previousMessages: messages,
237
278
  content: data.content,
238
279
  base64Images,
239
280
  perSendParams: Object.assign(Object.assign({}, perSendParams), perSendFileParams),
240
281
  });
282
+ if (epoch !== sendEpoch.current)
283
+ return false;
284
+ if (!accepted) {
285
+ failedFileDraftKey.current = fileDraftKey;
286
+ return false;
287
+ }
241
288
  reset();
242
- }, [messages, onBeforeSend, performSend, prepareFilesForSend, reset]);
289
+ return undefined;
290
+ }, [messages, onBeforeSend, performSend, prepareFilesForSend, reset, fileDraftKey]);
243
291
  const handleCancel = useCallback(async () => {
292
+ sendEpoch.current++;
293
+ setIsFetching(false);
244
294
  controller === null || controller === void 0 ? void 0 : controller.abort();
245
295
  setStreamSource(null);
246
296
  setStreamOptions(null);
247
297
  }, [controller]);
248
298
  const handleRetry = useCallback(async () => {
249
- var _a;
299
+ var _a, _b;
300
+ if (failedAttempt) {
301
+ const epoch = sendEpoch.current;
302
+ const accepted = await performSend(failedAttempt.request);
303
+ if (accepted &&
304
+ epoch === sendEpoch.current &&
305
+ latestFileDraftKey.current === failedFileDraftKey.current &&
306
+ ((_a = promptApiRef.current) === null || _a === void 0 ? void 0 : _a.clearFailedDraft())) {
307
+ reset();
308
+ }
309
+ return;
310
+ }
250
311
  const lastUserMsg = [...messages]
251
312
  .reverse()
252
313
  .find((m) => m.role === 'user');
@@ -256,12 +317,22 @@ function AIStudioChatInner(props) {
256
317
  const trimmedMessages = messages.slice(0, lastUserIndex);
257
318
  await performSend({
258
319
  previousMessages: trimmedMessages,
320
+ retryRequest: lastUserMsg.id ? sentRequests.current.get(lastUserMsg.id) : undefined,
259
321
  content: lastUserMsg.content,
322
+ perSendParams: { fileAttachments: lastUserMsg.fileAttachments },
260
323
  // Reuse images stored on the original message — no FileReader needed
261
- base64Images: (_a = lastUserMsg.images) !== null && _a !== void 0 ? _a : [],
324
+ base64Images: (_b = lastUserMsg.images) !== null && _b !== void 0 ? _b : [],
262
325
  });
263
- }, [messages, performSend]);
326
+ }, [messages, performSend, failedAttempt, reset]);
264
327
  const handleCreateChat = useCallback(() => {
328
+ setCommandsResetKey((key) => key + 1);
329
+ setFailedAttempt(null);
330
+ setSendError(null);
331
+ sendEpoch.current++;
332
+ controller === null || controller === void 0 ? void 0 : controller.abort();
333
+ setIsFetching(false);
334
+ setStreamSource(null);
335
+ setStreamOptions(null);
265
336
  const current = activeChatRef.current;
266
337
  if (current) {
267
338
  chatMessagesRef.current[current.id] = messages;
@@ -277,9 +348,17 @@ function AIStudioChatInner(props) {
277
348
  setActiveChat(newChat);
278
349
  setMessages([]);
279
350
  reset();
280
- }, [messages, reset]);
351
+ }, [messages, reset, controller]);
281
352
  const handleSelectChat = useCallback((chat) => {
282
353
  var _a;
354
+ setCommandsResetKey((key) => key + 1);
355
+ setFailedAttempt(null);
356
+ setSendError(null);
357
+ sendEpoch.current++;
358
+ controller === null || controller === void 0 ? void 0 : controller.abort();
359
+ setIsFetching(false);
360
+ setStreamSource(null);
361
+ setStreamOptions(null);
283
362
  const current = activeChatRef.current;
284
363
  if (current) {
285
364
  chatMessagesRef.current[current.id] = messages;
@@ -288,18 +367,26 @@ function AIStudioChatInner(props) {
288
367
  setActiveChat(chat);
289
368
  setMessages((_a = chatMessagesRef.current[chat.id]) !== null && _a !== void 0 ? _a : []);
290
369
  reset();
291
- }, [messages, reset]);
370
+ }, [messages, reset, controller]);
292
371
  const handleDeleteChat = useCallback(async (chat) => {
293
372
  var _a;
294
373
  delete chatMessagesRef.current[chat.id];
295
374
  setChats((prev) => prev.filter((c) => c.id !== chat.id));
296
375
  if (((_a = activeChatRef.current) === null || _a === void 0 ? void 0 : _a.id) === chat.id) {
376
+ setCommandsResetKey((key) => key + 1);
377
+ setFailedAttempt(null);
378
+ setSendError(null);
379
+ sendEpoch.current++;
380
+ controller === null || controller === void 0 ? void 0 : controller.abort();
381
+ setIsFetching(false);
382
+ setStreamSource(null);
383
+ setStreamOptions(null);
297
384
  responseIdRef.current = null;
298
385
  setActiveChat(null);
299
386
  setMessages([]);
300
387
  reset();
301
388
  }
302
- }, [reset]);
389
+ }, [reset, controller]);
303
390
  /**
304
391
  * Update `userRating` on an assistant message inside the internal store.
305
392
  * Mirrors the change into the per-chat history map so it survives chat switches.
@@ -352,13 +439,13 @@ function AIStudioChatInner(props) {
352
439
  });
353
440
  return Object.assign(Object.assign({}, original), { assistantActions: wrappedAssistantActions, messageRendererRegistry });
354
441
  }, [chatContainerProps.messageListConfig, setUserRating]);
355
- return (_jsx(ChatContainer, Object.assign({}, chatContainerProps, { messageListConfig: messageListConfig, messages: displayMessages, status: status, error: streamResult.error, onSendMessage: handleSendMessage, onCancel: handleCancel, onRetry: handleRetry, chats: showHistory ? chats : undefined, activeChat: showHistory ? activeChat : undefined, onSelectChat: showHistory ? handleSelectChat : undefined, onCreateChat: showHistory ? handleCreateChat : undefined, onDeleteChat: showHistory ? handleDeleteChat : undefined, showHistory: showHistory, showNewChat: showNewChat, promptInputProps: Object.assign(Object.assign({}, chatContainerProps.promptInputProps), { view: 'full', headerProps: ((_d = (_c = chatContainerProps.promptInputProps) === null || _c === void 0 ? void 0 : _c.headerProps) === null || _d === void 0 ? void 0 : _d.topContent)
442
+ return (_jsx(ChatContainer, Object.assign({}, chatContainerProps, { messageListConfig: messageListConfig, messages: displayMessages, status: status, error: sendError !== null && sendError !== void 0 ? sendError : streamResult.error, onSendMessage: handleSendMessage, onCancel: handleCancel, onRetry: handleRetry, chats: showHistory ? chats : undefined, activeChat: showHistory ? activeChat : undefined, onSelectChat: showHistory ? handleSelectChat : undefined, onCreateChat: showHistory ? handleCreateChat : undefined, onDeleteChat: showHistory ? handleDeleteChat : undefined, showHistory: showHistory, showNewChat: showNewChat, promptInputProps: Object.assign(Object.assign({}, chatContainerProps.promptInputProps), { apiRef: mergedPromptApiRef, commandsResetKey, view: 'full', headerProps: ((_e = (_d = chatContainerProps.promptInputProps) === null || _d === void 0 ? void 0 : _d.headerProps) === null || _e === void 0 ? void 0 : _e.topContent)
356
443
  ? chatContainerProps.promptInputProps.headerProps
357
444
  : {
358
- qa: (_f = (_e = chatContainerProps.promptInputProps) === null || _e === void 0 ? void 0 : _e.headerProps) === null || _f === void 0 ? void 0 : _f.qa,
359
- showContextIndicator: (_h = (_g = chatContainerProps.promptInputProps) === null || _g === void 0 ? void 0 : _g.headerProps) === null || _h === void 0 ? void 0 : _h.showContextIndicator,
360
- contextIndicatorProps: (_k = (_j = chatContainerProps.promptInputProps) === null || _j === void 0 ? void 0 : _j.headerProps) === null || _k === void 0 ? void 0 : _k.contextIndicatorProps,
361
- contextItems: (_o = (_m = (_l = chatContainerProps.promptInputProps) === null || _l === void 0 ? void 0 : _l.headerProps) === null || _m === void 0 ? void 0 : _m.contextItems) !== null && _o !== void 0 ? _o : contextItems,
362
- }, footerProps: Object.assign(Object.assign({}, (_p = chatContainerProps.promptInputProps) === null || _p === void 0 ? void 0 : _p.footerProps), { attachmentContent: (_s = (_r = (_q = chatContainerProps.promptInputProps) === null || _q === void 0 ? void 0 : _q.footerProps) === null || _r === void 0 ? void 0 : _r.attachmentContent) !== null && _s !== void 0 ? _s : attachmentContent }) }) })));
445
+ qa: (_g = (_f = chatContainerProps.promptInputProps) === null || _f === void 0 ? void 0 : _f.headerProps) === null || _g === void 0 ? void 0 : _g.qa,
446
+ showContextIndicator: (_j = (_h = chatContainerProps.promptInputProps) === null || _h === void 0 ? void 0 : _h.headerProps) === null || _j === void 0 ? void 0 : _j.showContextIndicator,
447
+ contextIndicatorProps: (_l = (_k = chatContainerProps.promptInputProps) === null || _k === void 0 ? void 0 : _k.headerProps) === null || _l === void 0 ? void 0 : _l.contextIndicatorProps,
448
+ contextItems: (_p = (_o = (_m = chatContainerProps.promptInputProps) === null || _m === void 0 ? void 0 : _m.headerProps) === null || _o === void 0 ? void 0 : _o.contextItems) !== null && _p !== void 0 ? _p : contextItems,
449
+ }, footerProps: Object.assign(Object.assign({}, (_q = chatContainerProps.promptInputProps) === null || _q === void 0 ? void 0 : _q.footerProps), { attachmentContent: (_t = (_s = (_r = chatContainerProps.promptInputProps) === null || _r === void 0 ? void 0 : _r.footerProps) === null || _s === void 0 ? void 0 : _s.attachmentContent) !== null && _t !== void 0 ? _t : attachmentContent }) }) })));
363
450
  }
364
451
  //# sourceMappingURL=AIStudioChat.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"AIStudioChat.js","sourceRoot":"../../../../../src","sources":["components/pages/AIStudioChat/AIStudioChat.tsx"],"names":[],"mappings":"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","sourcesContent":["import {useCallback, useEffect, useMemo, useRef, useState} from 'react';\n\nimport {v4 as uuidv4} from 'uuid';\n\nimport {fetchResponseToStreamEvents, useOpenAIStreamAdapter} from '../../../adapters/openai';\nimport type {OpenAIStreamSource} from '../../../adapters/openai';\nimport {BaseMessageActionType} from '../../../types';\nimport type {\n ChatStatus,\n ChatType,\n DefaultMessageAction,\n FileAttachment,\n TAssistantMessage,\n TChatMessage,\n TSubmitData,\n TUserMessage,\n UserRating,\n} from '../../../types';\nimport type {ToolMessageContent} from '../../../types/messages';\nimport {\n createMessageRendererRegistry,\n mergeMessageRendererRegistries,\n registerMessageRenderer,\n} from '../../../utils/messageTypeRegistry';\nimport {InputContextProvider, useInputContext} from '../../molecules/InputContext';\nimport type {MessageListConfig} from '../ChatContainer';\nimport {ChatContainer} from '../ChatContainer';\n\nimport {McpToolRenderer} from './McpToolRenderer';\nimport {normalizeMcpCallIds, omitMcpListToolsEvents} from './transforms';\nimport type {AIStudioChatProps} from './types';\n\nfunction isFileAttachment(value: unknown): value is FileAttachment {\n if (!value || typeof value !== 'object') return false;\n const v = value as Record<string, unknown>;\n return typeof v.id === 'string' && typeof v.name === 'string';\n}\n\nfunction resolveFileAttachments(\n attachments: FileAttachment[] | undefined,\n fileIds: string[] | undefined,\n): FileAttachment[] | undefined {\n if (attachments && attachments.length > 0) return attachments;\n if (fileIds && fileIds.length > 0) return fileIds.map((id) => ({id, name: id}));\n return undefined;\n}\n\ntype ApiMessageContentPart =\n | {type: 'text'; text: string}\n | {type: 'image_url'; image_url: {url: string}};\n\ntype ApiMessage = {\n role: 'user' | 'assistant' | 'system';\n content: string | ApiMessageContentPart[];\n};\n\ntype StreamOptions = {\n initialMessages: TChatMessage[];\n assistantMessageId: string;\n};\n\n/**\n * Extracts plain text content from any TChatMessage variant.\n */\nfunction getMessageTextContent(message: TChatMessage): string {\n if (message.role === 'user') {\n return typeof message.content === 'string' ? message.content : '';\n }\n\n const {content} = message as TAssistantMessage;\n\n if (typeof content === 'string') {\n return content;\n }\n\n if (Array.isArray(content)) {\n return content\n .map((item) => {\n if (typeof item === 'string') return item;\n if (item.type === 'text' && item.data?.text) return item.data.text;\n return '';\n })\n .join('\\n');\n }\n\n if (content && typeof content === 'object' && 'type' in content) {\n if (content.type === 'text' && content.data?.text) {\n return content.data.text;\n }\n }\n\n return '';\n}\n\n/**\n * Derives a human-readable chat name from the first user message.\n */\nfunction deriveChatName(content: string): string {\n const trimmed = content.trim();\n return trimmed.length > 40 ? `${trimmed.slice(0, 40)}...` : trimmed || 'New chat';\n}\n\ntype AIStudioChatInnerProps = Omit<AIStudioChatProps, 'fileUpload' | 'fileDialogTitle'>;\n\n/**\n * AIStudioChat - a ready-to-use chat component with built-in OpenAI streaming support.\n *\n * Wraps ChatContainer and handles all state internally: streaming, message history,\n * multi-chat management, and cancellation. Requires only an `apiUrl` to start working.\n *\n * @param props - component props\n * @returns React component\n */\nexport function AIStudioChat(props: AIStudioChatProps) {\n const {fileUpload, fileDialogTitle, ...rest} = props;\n return (\n <InputContextProvider fileUpload={fileUpload} fileDialogTitle={fileDialogTitle}>\n <AIStudioChatInner {...rest} />\n </InputContextProvider>\n );\n}\n\nfunction AIStudioChatInner(props: AIStudioChatInnerProps) {\n const {\n apiUrl,\n initialMessages = [],\n showHistory = false,\n showNewChat = showHistory,\n systemPrompt,\n requestInit,\n extraRequestParams,\n trackTokenUsage = true,\n onBeforeSend,\n ...chatContainerProps\n } = props;\n\n const {prepareFilesForSend, reset, contextItems, attachmentContent} = useInputContext();\n\n // Current chat messages\n const [messages, setMessages] = useState<TChatMessage[]>(initialMessages);\n\n // Multi-chat state (used when showHistory=true)\n const [chats, setChats] = useState<ChatType[]>([]);\n const [activeChat, setActiveChat] = useState<ChatType | null>(null);\n\n // Per-chat message store (ref to avoid unnecessary re-renders on switch)\n const chatMessagesRef = useRef<Record<string, TChatMessage[]>>({});\n\n // Always-current reference to activeChat for use inside async callbacks\n // (intentionally mutable ref — not a forgotten dependency)\n const activeChatRef = useRef<ChatType | null>(null);\n activeChatRef.current = activeChat;\n\n // Tracks the last response id for conversation continuity (previous_response_id)\n const responseIdRef = useRef<string | null>(null);\n\n // Streaming state\n const [controller, setController] = useState<AbortController | null>(null);\n const [isFetching, setIsFetching] = useState(false);\n const [streamSource, setStreamSource] = useState<OpenAIStreamSource | null>(null);\n const [streamOptions, setStreamOptions] = useState<StreamOptions | null>(null);\n\n const handleStreamEnd = useCallback((finalMessages: TChatMessage[]) => {\n const committed = finalMessages.filter(\n (msg) => msg.role !== 'assistant' || getMessageTextContent(msg) !== '',\n );\n\n setMessages(committed);\n setStreamSource(null);\n setStreamOptions(null);\n\n // Persist messages and update the last message preview in history\n const chat = activeChatRef.current;\n if (chat) {\n chatMessagesRef.current[chat.id] = committed;\n\n const lastMsg = committed[committed.length - 1];\n if (lastMsg) {\n setChats((prev) =>\n prev.map((c) =>\n c.id === chat.id ? {...c, lastMessage: getMessageTextContent(lastMsg)} : c,\n ),\n );\n }\n }\n }, []);\n\n const streamResult = useOpenAIStreamAdapter(streamSource, {\n initialMessages: streamOptions?.initialMessages ?? [],\n assistantMessageId: streamOptions?.assistantMessageId ?? 'assistant-idle',\n onStreamEnd: handleStreamEnd,\n trackTokenUsage,\n });\n\n // Sync latest responseId to ref so next request can use it as previousResponseId\n useEffect(() => {\n if (streamResult.responseId) {\n responseIdRef.current = streamResult.responseId;\n }\n }, [streamResult.responseId]);\n\n const hasSource = Boolean(streamSource);\n\n const displayMessages =\n hasSource && streamResult.messages.length > 0 ? streamResult.messages : messages;\n\n const status = useMemo((): ChatStatus => {\n if (!hasSource) {\n return isFetching ? 'submitted' : 'ready';\n }\n if (streamResult.status === 'streaming') return 'streaming';\n if (streamResult.status === 'error') return 'error';\n return 'ready';\n }, [hasSource, isFetching, streamResult.status]);\n\n /**\n * Core send function. Takes an already-resolved set of previous messages and\n * pre-converted base64 images so it can be called both from handleSendMessage\n * (which converts File objects) and from handleRetry (which reuses stored images).\n */\n const performSend = useCallback(\n async ({\n previousMessages,\n content,\n base64Images = [],\n perSendParams = {},\n }: {\n previousMessages: TChatMessage[];\n content: string;\n base64Images?: string[];\n perSendParams?: Record<string, unknown>;\n }) => {\n // Auto-create a chat when history is enabled and no chat is active yet\n if (showHistory && !activeChatRef.current) {\n const newChat: ChatType = {\n id: uuidv4(),\n name: deriveChatName(content),\n createTime: new Date().toISOString(),\n };\n chatMessagesRef.current[newChat.id] = [];\n activeChatRef.current = newChat;\n setActiveChat(newChat);\n setChats((prev) => [newChat, ...prev]);\n }\n\n const rawFileIds = Array.isArray(perSendParams.fileIds)\n ? (perSendParams.fileIds as string[])\n : undefined;\n const rawFileAttachments = Array.isArray(perSendParams.fileAttachments)\n ? (perSendParams.fileAttachments as unknown[]).filter(isFileAttachment)\n : undefined;\n const userMessage: TUserMessage = {\n id: uuidv4(),\n role: 'user',\n content,\n images: base64Images.length > 0 ? base64Images : undefined,\n fileAttachments: resolveFileAttachments(rawFileAttachments, rawFileIds),\n };\n const messagesWithUser: TChatMessage[] = [...previousMessages, userMessage];\n const assistantMessageId = uuidv4();\n\n setMessages(messagesWithUser);\n setIsFetching(true);\n\n const abortController = new AbortController();\n setController(abortController);\n\n try {\n // Last user message: plain text or multipart (text + images)\n const lastUserContent: ApiMessage['content'] =\n base64Images.length > 0\n ? [\n {type: 'text', text: content},\n ...base64Images.map((url) => ({\n type: 'image_url' as const,\n image_url: {url},\n })),\n ]\n : content;\n\n const apiMessages: ApiMessage[] = [\n ...(systemPrompt ? [{role: 'system' as const, content: systemPrompt}] : []),\n ...previousMessages\n .filter(\n (msg) => msg.role !== 'assistant' || getMessageTextContent(msg) !== '',\n )\n .map((msg) => ({\n role: msg.role as 'user' | 'assistant',\n content: getMessageTextContent(msg),\n })),\n {role: 'user' as const, content: lastUserContent},\n ];\n\n const response = await fetch(apiUrl, {\n ...requestInit,\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'text/event-stream',\n ...requestInit?.headers,\n },\n body: JSON.stringify({\n messages: apiMessages,\n ...extraRequestParams,\n ...perSendParams,\n ...(responseIdRef.current\n ? {previousResponseId: responseIdRef.current}\n : {}),\n }),\n signal: abortController.signal,\n });\n\n if (!response.ok) {\n throw new Error(`API error: ${response.status} ${response.statusText}`);\n }\n\n setStreamSource(\n normalizeMcpCallIds(\n omitMcpListToolsEvents(fetchResponseToStreamEvents(response)),\n ),\n );\n setStreamOptions({initialMessages: messagesWithUser, assistantMessageId});\n } catch (error) {\n if ((error as Error).name !== 'AbortError') {\n const errorMessage: TAssistantMessage = {\n id: uuidv4(),\n role: 'assistant',\n content: (error as Error).message,\n };\n setMessages((prev) => {\n const filtered = prev.filter(\n (msg) => msg.role !== 'assistant' || getMessageTextContent(msg) !== '',\n );\n return [...filtered, errorMessage];\n });\n }\n setStreamSource(null);\n setStreamOptions(null);\n } finally {\n setIsFetching(false);\n setController(null);\n }\n },\n [showHistory, systemPrompt, requestInit, apiUrl, extraRequestParams],\n );\n\n const handleSendMessage = useCallback(\n async (data: TSubmitData) => {\n // Call onBeforeSend hook — allows caller to inject per-request params or cancel send\n let perSendParams: Record<string, unknown> = {};\n if (onBeforeSend) {\n const result = await onBeforeSend({content: data.content});\n if (result === false || result === null) return;\n if (result) perSendParams = result;\n }\n\n const {base64Images, perSendFileParams} = await prepareFilesForSend(data.attachments);\n\n await performSend({\n previousMessages: messages,\n content: data.content,\n base64Images,\n perSendParams: {\n ...perSendParams,\n ...perSendFileParams,\n },\n });\n\n reset();\n },\n [messages, onBeforeSend, performSend, prepareFilesForSend, reset],\n );\n\n const handleCancel = useCallback(async () => {\n controller?.abort();\n setStreamSource(null);\n setStreamOptions(null);\n }, [controller]);\n\n const handleRetry = useCallback(async () => {\n const lastUserMsg = [...messages]\n .reverse()\n .find((m): m is TUserMessage => m.role === 'user');\n if (!lastUserMsg) return;\n\n const lastUserIndex = messages.lastIndexOf(lastUserMsg);\n const trimmedMessages = messages.slice(0, lastUserIndex);\n\n await performSend({\n previousMessages: trimmedMessages,\n content: lastUserMsg.content,\n // Reuse images stored on the original message — no FileReader needed\n base64Images: lastUserMsg.images ?? [],\n });\n }, [messages, performSend]);\n\n const handleCreateChat = useCallback(() => {\n const current = activeChatRef.current;\n if (current) {\n chatMessagesRef.current[current.id] = messages;\n }\n\n responseIdRef.current = null;\n\n const newChat: ChatType = {\n id: uuidv4(),\n name: 'New chat',\n createTime: new Date().toISOString(),\n };\n chatMessagesRef.current[newChat.id] = [];\n setChats((prev) => [newChat, ...prev]);\n setActiveChat(newChat);\n setMessages([]);\n reset();\n }, [messages, reset]);\n\n const handleSelectChat = useCallback(\n (chat: ChatType) => {\n const current = activeChatRef.current;\n if (current) {\n chatMessagesRef.current[current.id] = messages;\n }\n\n responseIdRef.current = null;\n setActiveChat(chat);\n setMessages(chatMessagesRef.current[chat.id] ?? []);\n reset();\n },\n [messages, reset],\n );\n\n const handleDeleteChat = useCallback(\n async (chat: ChatType) => {\n delete chatMessagesRef.current[chat.id];\n setChats((prev) => prev.filter((c) => c.id !== chat.id));\n\n if (activeChatRef.current?.id === chat.id) {\n responseIdRef.current = null;\n setActiveChat(null);\n setMessages([]);\n reset();\n }\n },\n [reset],\n );\n\n /**\n * Update `userRating` on an assistant message inside the internal store.\n * Mirrors the change into the per-chat history map so it survives chat switches.\n */\n const setUserRating = useCallback((messageId: string, rating: UserRating | undefined) => {\n const updateRating = (msgs: TChatMessage[]): TChatMessage[] =>\n msgs.map((msg) =>\n msg.role === 'assistant' && msg.id === messageId\n ? {...msg, userRating: rating}\n : msg,\n );\n\n setMessages(updateRating);\n\n const chat = activeChatRef.current;\n if (chat && chatMessagesRef.current[chat.id]) {\n chatMessagesRef.current[chat.id] = updateRating(chatMessagesRef.current[chat.id]);\n }\n }, []);\n\n /**\n * Build the final messageListConfig:\n * - Wrap consumer-provided Like/Dislike actions so the library toggles `userRating`\n * automatically before delegating to the original `onClick`. Other actions and\n * non-default (ReactNode) entries pass through unchanged.\n * - Inject a custom 'tool' renderer that renders MCP request/response sections when\n * `mcpRequest`/`mcpResponse` are present in the tool content. A consumer-provided\n * `messageRendererRegistry` wins on overlap.\n */\n const messageListConfig = useMemo<MessageListConfig | undefined>(() => {\n const original = chatContainerProps.messageListConfig;\n\n const baseRegistry = createMessageRendererRegistry();\n registerMessageRenderer<ToolMessageContent>(baseRegistry, 'tool', {\n component: McpToolRenderer,\n });\n const messageRendererRegistry = mergeMessageRendererRegistries(\n baseRegistry,\n original?.messageRendererRegistry ?? {},\n );\n\n const originalAssistantActions = original?.assistantActions;\n if (!originalAssistantActions) {\n return {...original, messageRendererRegistry};\n }\n\n const wrappedAssistantActions = originalAssistantActions.map((action) => {\n const typed = action as DefaultMessageAction<TAssistantMessage>;\n const isLike = typed.type === BaseMessageActionType.Like;\n const isDislike = typed.type === BaseMessageActionType.Dislike;\n if (!isLike && !isDislike) return action;\n\n const targetRating: UserRating = isLike ? 'like' : 'dislike';\n const originalOnClick = typed.onClick;\n\n return {\n ...typed,\n onClick: (message: TAssistantMessage) => {\n if (message.id) {\n const nextRating =\n message.userRating === targetRating ? undefined : targetRating;\n setUserRating(message.id, nextRating);\n }\n originalOnClick(message);\n },\n };\n });\n\n return {\n ...original,\n assistantActions: wrappedAssistantActions,\n messageRendererRegistry,\n };\n }, [chatContainerProps.messageListConfig, setUserRating]);\n\n return (\n <ChatContainer\n {...chatContainerProps}\n messageListConfig={messageListConfig}\n messages={displayMessages}\n status={status}\n error={streamResult.error}\n onSendMessage={handleSendMessage}\n onCancel={handleCancel}\n onRetry={handleRetry}\n chats={showHistory ? chats : undefined}\n activeChat={showHistory ? activeChat : undefined}\n onSelectChat={showHistory ? handleSelectChat : undefined}\n onCreateChat={showHistory ? handleCreateChat : undefined}\n onDeleteChat={showHistory ? handleDeleteChat : undefined}\n showHistory={showHistory}\n showNewChat={showNewChat}\n promptInputProps={{\n ...chatContainerProps.promptInputProps,\n view: 'full',\n headerProps: chatContainerProps.promptInputProps?.headerProps?.topContent\n ? chatContainerProps.promptInputProps.headerProps\n : {\n qa: chatContainerProps.promptInputProps?.headerProps?.qa,\n showContextIndicator:\n chatContainerProps.promptInputProps?.headerProps\n ?.showContextIndicator,\n contextIndicatorProps:\n chatContainerProps.promptInputProps?.headerProps\n ?.contextIndicatorProps,\n contextItems:\n chatContainerProps.promptInputProps?.headerProps?.contextItems ??\n contextItems,\n },\n footerProps: {\n ...chatContainerProps.promptInputProps?.footerProps,\n attachmentContent:\n chatContainerProps.promptInputProps?.footerProps?.attachmentContent ??\n attachmentContent,\n },\n }}\n />\n );\n}\n"]}
1
+ {"version":3,"file":"AIStudioChat.js","sourceRoot":"../../../../../src","sources":["components/pages/AIStudioChat/AIStudioChat.tsx"],"names":[],"mappings":"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","sourcesContent":["import {useCallback, useEffect, useMemo, useRef, useState} from 'react';\n\nimport {useForkRef} from '@gravity-ui/uikit';\nimport {v4 as uuidv4} from 'uuid';\n\nimport {fetchResponseToStreamEvents, useOpenAIStreamAdapter} from '../../../adapters/openai';\nimport type {OpenAIStreamSource} from '../../../adapters/openai';\nimport {BaseMessageActionType} from '../../../types';\nimport type {\n ChatStatus,\n ChatType,\n DefaultMessageAction,\n FileAttachment,\n TAssistantMessage,\n TChatMessage,\n TSubmitData,\n TUserMessage,\n UserRating,\n} from '../../../types';\nimport type {ToolMessageContent} from '../../../types/messages';\nimport {\n createMessageRendererRegistry,\n mergeMessageRendererRegistries,\n registerMessageRenderer,\n} from '../../../utils/messageTypeRegistry';\nimport {InputContextProvider, useInputContext} from '../../molecules/InputContext';\nimport type {PromptInputHandle} from '../../organisms/PromptInput';\nimport type {MessageListConfig} from '../ChatContainer';\nimport {ChatContainer} from '../ChatContainer';\n\nimport {McpToolRenderer} from './McpToolRenderer';\nimport {serializeChatRequest} from './request';\nimport {normalizeMcpCallIds, omitMcpListToolsEvents} from './transforms';\nimport type {AIStudioChatProps} from './types';\n\nfunction isFileAttachment(value: unknown): value is FileAttachment {\n if (!value || typeof value !== 'object') return false;\n const v = value as Record<string, unknown>;\n return typeof v.id === 'string' && typeof v.name === 'string';\n}\n\nfunction resolveFileAttachments(\n attachments: FileAttachment[] | undefined,\n fileIds: string[] | undefined,\n): FileAttachment[] | undefined {\n if (attachments && attachments.length > 0) return attachments;\n if (fileIds && fileIds.length > 0) return fileIds.map((id) => ({id, name: id}));\n return undefined;\n}\n\ntype ApiMessageContentPart =\n | {type: 'text'; text: string}\n | {type: 'image_url'; image_url: {url: string}};\n\ntype ApiMessage = {\n role: 'user' | 'assistant' | 'system';\n content: string | ApiMessageContentPart[];\n};\n\ntype SendRequest = {\n previousMessages: TChatMessage[];\n content: string;\n base64Images?: string[];\n perSendParams?: Record<string, unknown>;\n submitData?: TSubmitData;\n retryRequest?: string;\n};\n\ntype StreamOptions = {\n initialMessages: TChatMessage[];\n assistantMessageId: string;\n};\n\n/**\n * Extracts plain text content from any TChatMessage variant.\n */\nfunction getMessageTextContent(message: TChatMessage): string {\n if (message.role === 'user') {\n return typeof message.content === 'string' ? message.content : '';\n }\n\n const {content} = message as TAssistantMessage;\n\n if (typeof content === 'string') {\n return content;\n }\n\n if (Array.isArray(content)) {\n return content\n .map((item) => {\n if (typeof item === 'string') return item;\n if (item.type === 'text' && item.data?.text) return item.data.text;\n return '';\n })\n .join('\\n');\n }\n\n if (content && typeof content === 'object' && 'type' in content) {\n if (content.type === 'text' && content.data?.text) {\n return content.data.text;\n }\n }\n\n return '';\n}\n\n/**\n * Derives a human-readable chat name from the first user message.\n */\nfunction deriveChatName(content: string): string {\n const trimmed = content.trim();\n return trimmed.length > 40 ? `${trimmed.slice(0, 40)}...` : trimmed || 'New chat';\n}\n\ntype AIStudioChatInnerProps = Omit<AIStudioChatProps, 'fileUpload' | 'fileDialogTitle'>;\n\n/**\n * AIStudioChat - a ready-to-use chat component with built-in OpenAI streaming support.\n *\n * Wraps ChatContainer and handles all state internally: streaming, message history,\n * multi-chat management, and cancellation. Requires only an `apiUrl` to start working.\n *\n * @param props - component props\n * @returns React component\n */\nexport function AIStudioChat(props: AIStudioChatProps) {\n const {fileUpload, fileDialogTitle, ...rest} = props;\n return (\n <InputContextProvider fileUpload={fileUpload} fileDialogTitle={fileDialogTitle}>\n <AIStudioChatInner {...rest} />\n </InputContextProvider>\n );\n}\n\nfunction AIStudioChatInner(props: AIStudioChatInnerProps) {\n const {\n apiUrl,\n initialMessages = [],\n showHistory = false,\n showNewChat = showHistory,\n systemPrompt,\n requestInit,\n extraRequestParams,\n trackTokenUsage = true,\n onBeforeSend,\n transformRequest,\n ...chatContainerProps\n } = props;\n\n const {prepareFilesForSend, reset, contextItems, attachmentContent} = useInputContext();\n const promptApiRef = useRef<PromptInputHandle>(null);\n const mergedPromptApiRef = useForkRef(\n promptApiRef,\n chatContainerProps.promptInputProps?.apiRef,\n );\n const fileDraftKey = JSON.stringify(contextItems.map((item) => item.id));\n const latestFileDraftKey = useRef(fileDraftKey);\n latestFileDraftKey.current = fileDraftKey;\n const failedFileDraftKey = useRef<string>();\n\n // Keep the exact mapped request for retry, independently of later draft selections.\n const sentRequests = useRef(new Map<string, string>());\n const sendEpoch = useRef(0);\n const [commandsResetKey, setCommandsResetKey] = useState(0);\n const [sendError, setSendError] = useState<Error | null>(null);\n const [failedAttempt, setFailedAttempt] = useState<{\n message: TUserMessage;\n request: SendRequest;\n } | null>(null);\n\n // Current chat messages\n const [messages, setMessages] = useState<TChatMessage[]>(initialMessages);\n\n // Multi-chat state (used when showHistory=true)\n const [chats, setChats] = useState<ChatType[]>([]);\n const [activeChat, setActiveChat] = useState<ChatType | null>(null);\n\n // Per-chat message store (ref to avoid unnecessary re-renders on switch)\n const chatMessagesRef = useRef<Record<string, TChatMessage[]>>({});\n\n // Always-current reference to activeChat for use inside async callbacks\n // (intentionally mutable ref — not a forgotten dependency)\n const activeChatRef = useRef<ChatType | null>(null);\n activeChatRef.current = activeChat;\n\n // Tracks the last response id for conversation continuity (previous_response_id)\n const responseIdRef = useRef<string | null>(null);\n\n // Streaming state\n const [controller, setController] = useState<AbortController | null>(null);\n const [isFetching, setIsFetching] = useState(false);\n const [streamSource, setStreamSource] = useState<OpenAIStreamSource | null>(null);\n const [streamOptions, setStreamOptions] = useState<StreamOptions | null>(null);\n\n const handleStreamEnd = useCallback((finalMessages: TChatMessage[]) => {\n const committed = finalMessages.filter(\n (msg) => msg.role !== 'assistant' || getMessageTextContent(msg) !== '',\n );\n\n setMessages(committed);\n setStreamSource(null);\n setStreamOptions(null);\n\n // Persist messages and update the last message preview in history\n const chat = activeChatRef.current;\n if (chat) {\n chatMessagesRef.current[chat.id] = committed;\n\n const lastMsg = committed[committed.length - 1];\n if (lastMsg) {\n setChats((prev) =>\n prev.map((c) =>\n c.id === chat.id ? {...c, lastMessage: getMessageTextContent(lastMsg)} : c,\n ),\n );\n }\n }\n }, []);\n\n const streamResult = useOpenAIStreamAdapter(streamSource, {\n initialMessages: streamOptions?.initialMessages ?? [],\n assistantMessageId: streamOptions?.assistantMessageId ?? 'assistant-idle',\n onStreamEnd: handleStreamEnd,\n trackTokenUsage,\n });\n\n // Sync latest responseId to ref so next request can use it as previousResponseId\n useEffect(() => {\n if (streamResult.responseId) {\n responseIdRef.current = streamResult.responseId;\n }\n }, [streamResult.responseId]);\n\n const hasSource = Boolean(streamSource);\n\n const pendingMessages = failedAttempt ? [...messages, failedAttempt.message] : messages;\n const displayMessages =\n hasSource && streamResult.messages.length > 0 ? streamResult.messages : pendingMessages;\n\n const status = useMemo((): ChatStatus => {\n if (!hasSource) {\n if (isFetching) return 'submitted';\n return sendError ? 'error' : 'ready';\n }\n if (streamResult.status === 'streaming') return 'streaming';\n if (streamResult.status === 'error') return 'error';\n return 'ready';\n }, [hasSource, isFetching, streamResult.status, sendError]);\n\n /**\n * Core send function. Takes an already-resolved set of previous messages and\n * pre-converted base64 images so it can be called both from handleSendMessage\n * (which converts File objects) and from handleRetry (which reuses stored images).\n */\n const performSend = useCallback(\n async ({\n previousMessages,\n content,\n base64Images = [],\n perSendParams = {},\n submitData,\n retryRequest,\n }: SendRequest) => {\n const rawFileIds = Array.isArray(perSendParams.fileIds)\n ? (perSendParams.fileIds as string[])\n : undefined;\n const rawFileAttachments = Array.isArray(perSendParams.fileAttachments)\n ? (perSendParams.fileAttachments as unknown[]).filter(isFileAttachment)\n : undefined;\n const userMessageId = uuidv4();\n const userMessage: TUserMessage = {\n id: userMessageId,\n role: 'user',\n content,\n images: base64Images.length > 0 ? base64Images : undefined,\n fileAttachments: resolveFileAttachments(rawFileAttachments, rawFileIds),\n };\n const messagesWithUser: TChatMessage[] = [...previousMessages, userMessage];\n const assistantMessageId = uuidv4();\n\n const epoch = sendEpoch.current;\n setIsFetching(true);\n setSendError(null);\n setFailedAttempt(null);\n\n const abortController = new AbortController();\n setController(abortController);\n\n try {\n // Last user message: plain text or multipart (text + images)\n const lastUserContent: ApiMessage['content'] =\n base64Images.length > 0\n ? [\n {type: 'text', text: content},\n ...base64Images.map((url) => ({\n type: 'image_url' as const,\n image_url: {url},\n })),\n ]\n : content;\n\n const apiMessages: ApiMessage[] = [\n ...(systemPrompt ? [{role: 'system' as const, content: systemPrompt}] : []),\n ...previousMessages\n .filter(\n (msg) => msg.role !== 'assistant' || getMessageTextContent(msg) !== '',\n )\n .map((msg) => ({\n role: msg.role as 'user' | 'assistant',\n content: getMessageTextContent(msg),\n })),\n {role: 'user' as const, content: lastUserContent},\n ];\n\n const baseRequest = {\n messages: apiMessages,\n ...extraRequestParams,\n ...perSendParams,\n ...(responseIdRef.current ? {previousResponseId: responseIdRef.current} : {}),\n };\n const body = await serializeChatRequest(\n baseRequest,\n submitData ?? {content},\n transformRequest,\n retryRequest,\n );\n if (body === false || epoch !== sendEpoch.current) return false;\n sentRequests.current.set(userMessageId, body);\n // Auto-create a chat when history is enabled and no chat is active yet\n if (showHistory && !activeChatRef.current) {\n const newChat: ChatType = {\n id: uuidv4(),\n name: deriveChatName(content),\n createTime: new Date().toISOString(),\n };\n chatMessagesRef.current[newChat.id] = [];\n activeChatRef.current = newChat;\n setActiveChat(newChat);\n setChats((prev) => [newChat, ...prev]);\n }\n\n setMessages(messagesWithUser);\n\n const response = await fetch(apiUrl, {\n ...requestInit,\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'text/event-stream',\n ...requestInit?.headers,\n },\n body,\n signal: abortController.signal,\n });\n\n if (epoch !== sendEpoch.current) return false;\n if (!response.ok) {\n throw new Error(`API error: ${response.status} ${response.statusText}`);\n }\n\n setStreamSource(\n normalizeMcpCallIds(\n omitMcpListToolsEvents(fetchResponseToStreamEvents(response)),\n ),\n );\n setStreamOptions({initialMessages: messagesWithUser, assistantMessageId});\n return true;\n } catch (error) {\n if (epoch !== sendEpoch.current) return false;\n // Roll back the optimistic attempt; errors and failed messages are UI state only.\n setMessages(previousMessages);\n if ((error as Error).name !== 'AbortError') {\n setSendError(error instanceof Error ? error : new Error(String(error)));\n setFailedAttempt({\n message: userMessage,\n request: {\n previousMessages,\n content,\n base64Images,\n perSendParams,\n submitData,\n retryRequest: sentRequests.current.get(userMessageId),\n },\n });\n }\n setStreamSource(null);\n setStreamOptions(null);\n return false;\n } finally {\n if (epoch === sendEpoch.current) {\n setIsFetching(false);\n setController(null);\n }\n }\n },\n [showHistory, systemPrompt, requestInit, apiUrl, extraRequestParams, transformRequest],\n );\n\n const handleSendMessage = useCallback(\n async (data: TSubmitData): Promise<void | false> => {\n const epoch = sendEpoch.current;\n // Call onBeforeSend hook — allows caller to inject per-request params or cancel send\n let perSendParams: Record<string, unknown> = {};\n if (onBeforeSend) {\n const result = await onBeforeSend(data);\n if (result === false || result === null) return false;\n if (result) perSendParams = result;\n }\n\n const {base64Images, perSendFileParams} = await prepareFilesForSend(data.attachments);\n\n if (epoch !== sendEpoch.current) return false;\n const accepted = await performSend({\n submitData: data,\n previousMessages: messages,\n content: data.content,\n base64Images,\n perSendParams: {\n ...perSendParams,\n ...perSendFileParams,\n },\n });\n\n if (epoch !== sendEpoch.current) return false;\n if (!accepted) {\n failedFileDraftKey.current = fileDraftKey;\n return false;\n }\n reset();\n return undefined;\n },\n [messages, onBeforeSend, performSend, prepareFilesForSend, reset, fileDraftKey],\n );\n\n const handleCancel = useCallback(async () => {\n sendEpoch.current++;\n setIsFetching(false);\n controller?.abort();\n setStreamSource(null);\n setStreamOptions(null);\n }, [controller]);\n\n const handleRetry = useCallback(async () => {\n if (failedAttempt) {\n const epoch = sendEpoch.current;\n const accepted = await performSend(failedAttempt.request);\n if (\n accepted &&\n epoch === sendEpoch.current &&\n latestFileDraftKey.current === failedFileDraftKey.current &&\n promptApiRef.current?.clearFailedDraft()\n ) {\n reset();\n }\n return;\n }\n const lastUserMsg = [...messages]\n .reverse()\n .find((m): m is TUserMessage => m.role === 'user');\n if (!lastUserMsg) return;\n\n const lastUserIndex = messages.lastIndexOf(lastUserMsg);\n const trimmedMessages = messages.slice(0, lastUserIndex);\n\n await performSend({\n previousMessages: trimmedMessages,\n retryRequest: lastUserMsg.id ? sentRequests.current.get(lastUserMsg.id) : undefined,\n content: lastUserMsg.content,\n perSendParams: {fileAttachments: lastUserMsg.fileAttachments},\n // Reuse images stored on the original message — no FileReader needed\n base64Images: lastUserMsg.images ?? [],\n });\n }, [messages, performSend, failedAttempt, reset]);\n\n const handleCreateChat = useCallback(() => {\n setCommandsResetKey((key) => key + 1);\n setFailedAttempt(null);\n setSendError(null);\n sendEpoch.current++;\n controller?.abort();\n setIsFetching(false);\n setStreamSource(null);\n setStreamOptions(null);\n const current = activeChatRef.current;\n if (current) {\n chatMessagesRef.current[current.id] = messages;\n }\n\n responseIdRef.current = null;\n\n const newChat: ChatType = {\n id: uuidv4(),\n name: 'New chat',\n createTime: new Date().toISOString(),\n };\n chatMessagesRef.current[newChat.id] = [];\n setChats((prev) => [newChat, ...prev]);\n setActiveChat(newChat);\n setMessages([]);\n reset();\n }, [messages, reset, controller]);\n\n const handleSelectChat = useCallback(\n (chat: ChatType) => {\n setCommandsResetKey((key) => key + 1);\n setFailedAttempt(null);\n setSendError(null);\n sendEpoch.current++;\n controller?.abort();\n setIsFetching(false);\n setStreamSource(null);\n setStreamOptions(null);\n const current = activeChatRef.current;\n if (current) {\n chatMessagesRef.current[current.id] = messages;\n }\n\n responseIdRef.current = null;\n setActiveChat(chat);\n setMessages(chatMessagesRef.current[chat.id] ?? []);\n reset();\n },\n [messages, reset, controller],\n );\n\n const handleDeleteChat = useCallback(\n async (chat: ChatType) => {\n delete chatMessagesRef.current[chat.id];\n setChats((prev) => prev.filter((c) => c.id !== chat.id));\n\n if (activeChatRef.current?.id === chat.id) {\n setCommandsResetKey((key) => key + 1);\n setFailedAttempt(null);\n setSendError(null);\n sendEpoch.current++;\n controller?.abort();\n setIsFetching(false);\n setStreamSource(null);\n setStreamOptions(null);\n responseIdRef.current = null;\n setActiveChat(null);\n setMessages([]);\n reset();\n }\n },\n [reset, controller],\n );\n\n /**\n * Update `userRating` on an assistant message inside the internal store.\n * Mirrors the change into the per-chat history map so it survives chat switches.\n */\n const setUserRating = useCallback((messageId: string, rating: UserRating | undefined) => {\n const updateRating = (msgs: TChatMessage[]): TChatMessage[] =>\n msgs.map((msg) =>\n msg.role === 'assistant' && msg.id === messageId\n ? {...msg, userRating: rating}\n : msg,\n );\n\n setMessages(updateRating);\n\n const chat = activeChatRef.current;\n if (chat && chatMessagesRef.current[chat.id]) {\n chatMessagesRef.current[chat.id] = updateRating(chatMessagesRef.current[chat.id]);\n }\n }, []);\n\n /**\n * Build the final messageListConfig:\n * - Wrap consumer-provided Like/Dislike actions so the library toggles `userRating`\n * automatically before delegating to the original `onClick`. Other actions and\n * non-default (ReactNode) entries pass through unchanged.\n * - Inject a custom 'tool' renderer that renders MCP request/response sections when\n * `mcpRequest`/`mcpResponse` are present in the tool content. A consumer-provided\n * `messageRendererRegistry` wins on overlap.\n */\n const messageListConfig = useMemo<MessageListConfig | undefined>(() => {\n const original = chatContainerProps.messageListConfig;\n\n const baseRegistry = createMessageRendererRegistry();\n registerMessageRenderer<ToolMessageContent>(baseRegistry, 'tool', {\n component: McpToolRenderer,\n });\n const messageRendererRegistry = mergeMessageRendererRegistries(\n baseRegistry,\n original?.messageRendererRegistry ?? {},\n );\n\n const originalAssistantActions = original?.assistantActions;\n if (!originalAssistantActions) {\n return {...original, messageRendererRegistry};\n }\n\n const wrappedAssistantActions = originalAssistantActions.map((action) => {\n const typed = action as DefaultMessageAction<TAssistantMessage>;\n const isLike = typed.type === BaseMessageActionType.Like;\n const isDislike = typed.type === BaseMessageActionType.Dislike;\n if (!isLike && !isDislike) return action;\n\n const targetRating: UserRating = isLike ? 'like' : 'dislike';\n const originalOnClick = typed.onClick;\n\n return {\n ...typed,\n onClick: (message: TAssistantMessage) => {\n if (message.id) {\n const nextRating =\n message.userRating === targetRating ? undefined : targetRating;\n setUserRating(message.id, nextRating);\n }\n originalOnClick(message);\n },\n };\n });\n\n return {\n ...original,\n assistantActions: wrappedAssistantActions,\n messageRendererRegistry,\n };\n }, [chatContainerProps.messageListConfig, setUserRating]);\n\n return (\n <ChatContainer\n {...chatContainerProps}\n messageListConfig={messageListConfig}\n messages={displayMessages}\n status={status}\n error={sendError ?? streamResult.error}\n onSendMessage={handleSendMessage}\n onCancel={handleCancel}\n onRetry={handleRetry}\n chats={showHistory ? chats : undefined}\n activeChat={showHistory ? activeChat : undefined}\n onSelectChat={showHistory ? handleSelectChat : undefined}\n onCreateChat={showHistory ? handleCreateChat : undefined}\n onDeleteChat={showHistory ? handleDeleteChat : undefined}\n showHistory={showHistory}\n showNewChat={showNewChat}\n promptInputProps={{\n ...chatContainerProps.promptInputProps,\n apiRef: mergedPromptApiRef,\n commandsResetKey,\n view: 'full',\n headerProps: chatContainerProps.promptInputProps?.headerProps?.topContent\n ? chatContainerProps.promptInputProps.headerProps\n : {\n qa: chatContainerProps.promptInputProps?.headerProps?.qa,\n showContextIndicator:\n chatContainerProps.promptInputProps?.headerProps\n ?.showContextIndicator,\n contextIndicatorProps:\n chatContainerProps.promptInputProps?.headerProps\n ?.contextIndicatorProps,\n contextItems:\n chatContainerProps.promptInputProps?.headerProps?.contextItems ??\n contextItems,\n },\n footerProps: {\n ...chatContainerProps.promptInputProps?.footerProps,\n attachmentContent:\n chatContainerProps.promptInputProps?.footerProps?.attachmentContent ??\n attachmentContent,\n },\n }}\n />\n );\n}\n"]}
@@ -0,0 +1,4 @@
1
+ import type { TSubmitData } from "../../../types/index.js";
2
+ import type { AIStudioChatProps } from "./types.js";
3
+ /** Resolve application mapping once and keep a serialized snapshot for retries. */
4
+ export declare function serializeChatRequest(request: Record<string, unknown>, data: TSubmitData, transform: AIStudioChatProps['transformRequest'], retryBody?: string): Promise<string | false>;
@@ -0,0 +1,8 @@
1
+ /** Resolve application mapping once and keep a serialized snapshot for retries. */
2
+ export async function serializeChatRequest(request, data, transform, retryBody) {
3
+ if (retryBody !== undefined)
4
+ return retryBody;
5
+ const mapped = transform ? await transform(request, data) : request;
6
+ return mapped === false ? false : JSON.stringify(mapped);
7
+ }
8
+ //# sourceMappingURL=request.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request.js","sourceRoot":"../../../../../src","sources":["components/pages/AIStudioChat/request.ts"],"names":[],"mappings":"AAIA,mFAAmF;AACnF,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACtC,OAAgC,EAChC,IAAiB,EACjB,SAAgD,EAChD,SAAkB;IAElB,IAAI,SAAS,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC9C,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,MAAM,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IACpE,OAAO,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;AAC7D,CAAC","sourcesContent":["import type {TSubmitData} from '../../../types';\n\nimport type {AIStudioChatProps} from './types';\n\n/** Resolve application mapping once and keep a serialized snapshot for retries. */\nexport async function serializeChatRequest(\n request: Record<string, unknown>,\n data: TSubmitData,\n transform: AIStudioChatProps['transformRequest'],\n retryBody?: string,\n): Promise<string | false> {\n if (retryBody !== undefined) return retryBody;\n const mapped = transform ? await transform(request, data) : request;\n return mapped === false ? false : JSON.stringify(mapped);\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import type { UseFileUploadStoreOptions } from "../../../hooks/useFileUploadStore.js";
2
- import type { TChatMessage } from "../../../types/index.js";
2
+ import type { TChatMessage, TSubmitData } from "../../../types/index.js";
3
3
  import type { InputContextMeta } from "../../molecules/InputContext/index.js";
4
4
  import type { ChatContainerProps } from "../ChatContainer/index.js";
5
5
  /**
@@ -36,11 +36,11 @@ export interface AIStudioChatProps extends Omit<ChatContainerProps, ManagedChatC
36
36
  /**
37
37
  * Called before each API request is made.
38
38
  * Return an object to merge into the request body for this specific send.
39
- * Return false/null/undefined to cancel the send entirely.
39
+ * Return false/null to cancel the send entirely.
40
40
  */
41
- onBeforeSend?: (params: {
42
- content: string;
43
- }) => Promise<Record<string, unknown> | false | null | void>;
41
+ onBeforeSend?: (params: TSubmitData) => Promise<Record<string, unknown> | false | null | void>;
42
+ /** Final request mapping, after file parameters. Return false to keep the draft. */
43
+ transformRequest?: (request: Record<string, unknown>, data: TSubmitData) => Record<string, unknown> | false | Promise<Record<string, unknown> | false>;
44
44
  /**
45
45
  * File upload options for prompt `InputContext` (`useFileUploadStore`).
46
46
  * The consumer fully owns the upload pipeline — no default is provided.
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"../../../../../src","sources":["components/pages/AIStudioChat/types.ts"],"names":[],"mappings":"","sourcesContent":["import type {UseFileUploadStoreOptions} from '../../../hooks/useFileUploadStore';\nimport type {TChatMessage} from '../../../types';\nimport type {InputContextMeta} from '../../molecules/InputContext';\nimport type {ChatContainerProps} from '../ChatContainer';\n\n/**\n * Props managed internally by AIStudioChat that are omitted from ChatContainerProps\n */\ntype ManagedChatContainerProps =\n | 'messages'\n | 'status'\n | 'error'\n | 'onSendMessage'\n | 'onCancel'\n | 'onRetry'\n | 'chats'\n | 'activeChat'\n | 'onSelectChat'\n | 'onCreateChat'\n | 'onDeleteChat'\n | 'onDeleteAllChats'\n | 'showHistory'\n | 'showNewChat';\n\n/**\n * Props for AIStudioChat component\n */\nexport interface AIStudioChatProps extends Omit<ChatContainerProps, ManagedChatContainerProps> {\n /** URL of the OpenAI-compatible streaming API endpoint */\n apiUrl: string;\n\n /** Initial messages to pre-populate the chat (e.g., for restoring a session) */\n initialMessages?: TChatMessage[];\n\n /** Enable multi-chat history panel (default: false) */\n showHistory?: boolean;\n\n /** Show new chat button in header (defaults to the value of showHistory) */\n showNewChat?: boolean;\n\n /** System prompt sent with every request */\n systemPrompt?: string;\n\n /** Additional fetch options applied to every API request (e.g., auth headers) */\n requestInit?: Omit<RequestInit, 'body' | 'method' | 'signal'>;\n\n /**\n * Extra fields merged into the request body on every send.\n * Use for assistantId, promptVariables, conversationId, etc.\n * Per-request overrides take precedence (returned from onBeforeSend).\n */\n extraRequestParams?: Record<string, unknown>;\n\n /**\n * Enable token usage tracking in stream responses (default: true).\n * Set to false to disable tracking and reduce payload size.\n */\n trackTokenUsage?: boolean;\n\n /**\n * Called before each API request is made.\n * Return an object to merge into the request body for this specific send.\n * Return false/null/undefined to cancel the send entirely.\n */\n onBeforeSend?: (params: {\n content: string;\n }) => Promise<Record<string, unknown> | false | null | void>;\n\n /**\n * File upload options for prompt `InputContext` (`useFileUploadStore`).\n * The consumer fully owns the upload pipeline — no default is provided.\n */\n fileUpload: UseFileUploadStoreOptions<InputContextMeta>;\n\n /** Title of the attachment file dialog (`InputContextProvider`). */\n fileDialogTitle?: string;\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"../../../../../src","sources":["components/pages/AIStudioChat/types.ts"],"names":[],"mappings":"","sourcesContent":["import type {UseFileUploadStoreOptions} from '../../../hooks/useFileUploadStore';\nimport type {TChatMessage, TSubmitData} from '../../../types';\nimport type {InputContextMeta} from '../../molecules/InputContext';\nimport type {ChatContainerProps} from '../ChatContainer';\n\n/**\n * Props managed internally by AIStudioChat that are omitted from ChatContainerProps\n */\ntype ManagedChatContainerProps =\n | 'messages'\n | 'status'\n | 'error'\n | 'onSendMessage'\n | 'onCancel'\n | 'onRetry'\n | 'chats'\n | 'activeChat'\n | 'onSelectChat'\n | 'onCreateChat'\n | 'onDeleteChat'\n | 'onDeleteAllChats'\n | 'showHistory'\n | 'showNewChat';\n\n/**\n * Props for AIStudioChat component\n */\nexport interface AIStudioChatProps extends Omit<ChatContainerProps, ManagedChatContainerProps> {\n /** URL of the OpenAI-compatible streaming API endpoint */\n apiUrl: string;\n\n /** Initial messages to pre-populate the chat (e.g., for restoring a session) */\n initialMessages?: TChatMessage[];\n\n /** Enable multi-chat history panel (default: false) */\n showHistory?: boolean;\n\n /** Show new chat button in header (defaults to the value of showHistory) */\n showNewChat?: boolean;\n\n /** System prompt sent with every request */\n systemPrompt?: string;\n\n /** Additional fetch options applied to every API request (e.g., auth headers) */\n requestInit?: Omit<RequestInit, 'body' | 'method' | 'signal'>;\n\n /**\n * Extra fields merged into the request body on every send.\n * Use for assistantId, promptVariables, conversationId, etc.\n * Per-request overrides take precedence (returned from onBeforeSend).\n */\n extraRequestParams?: Record<string, unknown>;\n\n /**\n * Enable token usage tracking in stream responses (default: true).\n * Set to false to disable tracking and reduce payload size.\n */\n trackTokenUsage?: boolean;\n\n /**\n * Called before each API request is made.\n * Return an object to merge into the request body for this specific send.\n * Return false/null to cancel the send entirely.\n */\n onBeforeSend?: (params: TSubmitData) => Promise<Record<string, unknown> | false | null | void>;\n\n /** Final request mapping, after file parameters. Return false to keep the draft. */\n transformRequest?: (\n request: Record<string, unknown>,\n data: TSubmitData,\n ) => Record<string, unknown> | false | Promise<Record<string, unknown> | false>;\n\n /**\n * File upload options for prompt `InputContext` (`useFileUploadStore`).\n * The consumer fully owns the upload pipeline — no default is provided.\n */\n fileUpload: UseFileUploadStoreOptions<InputContextMeta>;\n\n /** Title of the attachment file dialog (`InputContextProvider`). */\n fileDialogTitle?: string;\n}\n"]}