@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.
- package/build/cjs/components/molecules/PromptInputBody/PromptInputBody.d.ts +1 -0
- package/build/cjs/components/molecules/PromptInputBody/PromptInputBody.js +2 -8
- package/build/cjs/components/molecules/PromptInputBody/PromptInputBody.js.map +1 -1
- package/build/cjs/components/organisms/PromptInput/PromptInput.css +37 -0
- package/build/cjs/components/organisms/PromptInput/PromptInput.d.ts +13 -2
- package/build/cjs/components/organisms/PromptInput/PromptInput.js +64 -3
- package/build/cjs/components/organisms/PromptInput/PromptInput.js.map +1 -1
- package/build/cjs/components/organisms/PromptInput/PromptInputCommands.d.ts +9 -0
- package/build/cjs/components/organisms/PromptInput/PromptInputCommands.js +39 -0
- package/build/cjs/components/organisms/PromptInput/PromptInputCommands.js.map +1 -0
- package/build/cjs/components/organisms/PromptInput/PromptInputFull.d.ts +2 -0
- package/build/cjs/components/organisms/PromptInput/PromptInputFull.js +4 -4
- package/build/cjs/components/organisms/PromptInput/PromptInputFull.js.map +1 -1
- package/build/cjs/components/organisms/PromptInput/PromptInputSimple.d.ts +2 -0
- package/build/cjs/components/organisms/PromptInput/PromptInputSimple.js +3 -3
- package/build/cjs/components/organisms/PromptInput/PromptInputSimple.js.map +1 -1
- package/build/cjs/components/organisms/PromptInput/commandUtils.d.ts +13 -0
- package/build/cjs/components/organisms/PromptInput/commandUtils.js +27 -0
- package/build/cjs/components/organisms/PromptInput/commandUtils.js.map +1 -0
- package/build/cjs/components/organisms/PromptInput/i18n/en.json +8 -0
- package/build/cjs/components/organisms/PromptInput/i18n/index.d.ts +13 -0
- package/build/cjs/components/organisms/PromptInput/i18n/index.js +10 -0
- package/build/cjs/components/organisms/PromptInput/i18n/index.js.map +1 -0
- package/build/cjs/components/organisms/PromptInput/i18n/ru.json +8 -0
- package/build/cjs/components/organisms/PromptInput/index.d.ts +2 -1
- package/build/cjs/components/organisms/PromptInput/index.js.map +1 -1
- package/build/cjs/components/organisms/PromptInput/types.d.ts +1 -0
- package/build/cjs/components/organisms/PromptInput/types.js.map +1 -1
- package/build/cjs/components/organisms/PromptInput/usePromptCommands.d.ts +41 -0
- package/build/cjs/components/organisms/PromptInput/usePromptCommands.js +222 -0
- package/build/cjs/components/organisms/PromptInput/usePromptCommands.js.map +1 -0
- package/build/cjs/components/organisms/PromptInput/usePromptInput.d.ts +10 -1
- package/build/cjs/components/organisms/PromptInput/usePromptInput.js +100 -11
- package/build/cjs/components/organisms/PromptInput/usePromptInput.js.map +1 -1
- package/build/cjs/components/pages/AIStudioChat/AIStudioChat.js +139 -52
- package/build/cjs/components/pages/AIStudioChat/AIStudioChat.js.map +1 -1
- package/build/cjs/components/pages/AIStudioChat/request.d.ts +4 -0
- package/build/cjs/components/pages/AIStudioChat/request.js +11 -0
- package/build/cjs/components/pages/AIStudioChat/request.js.map +1 -0
- package/build/cjs/components/pages/AIStudioChat/types.d.ts +5 -5
- package/build/cjs/components/pages/AIStudioChat/types.js.map +1 -1
- package/build/cjs/components/pages/ChatContainer/ChatContainer.js +10 -4
- package/build/cjs/components/pages/ChatContainer/ChatContainer.js.map +1 -1
- package/build/cjs/components/pages/ChatContainer/types.d.ts +1 -1
- package/build/cjs/components/pages/ChatContainer/types.js.map +1 -1
- package/build/cjs/components/pages/ChatContainer/useChatContainer.d.ts +1 -0
- package/build/cjs/components/pages/ChatContainer/useChatContainer.js +5 -1
- package/build/cjs/components/pages/ChatContainer/useChatContainer.js.map +1 -1
- package/build/cjs/package.json +1 -1
- package/build/cjs/types/index.d.ts +1 -0
- package/build/cjs/types/index.js +1 -0
- package/build/cjs/types/index.js.map +1 -1
- package/build/cjs/types/messages.d.ts +3 -0
- package/build/cjs/types/messages.js.map +1 -1
- package/build/cjs/types/promptCommands.d.ts +44 -0
- package/build/cjs/types/promptCommands.js +3 -0
- package/build/cjs/types/promptCommands.js.map +1 -0
- package/build/docs/components/molecules/PromptInputBody.md +16 -15
- package/build/docs/components/organisms/PromptInput.md +151 -0
- package/build/docs/components/pages/AIStudioChat.md +38 -0
- package/build/esm/components/molecules/PromptInputBody/PromptInputBody.d.ts +1 -0
- package/build/esm/components/molecules/PromptInputBody/PromptInputBody.js +2 -8
- package/build/esm/components/molecules/PromptInputBody/PromptInputBody.js.map +1 -1
- package/build/esm/components/organisms/PromptInput/PromptInput.css +37 -0
- package/build/esm/components/organisms/PromptInput/PromptInput.d.ts +13 -2
- package/build/esm/components/organisms/PromptInput/PromptInput.js +65 -4
- package/build/esm/components/organisms/PromptInput/PromptInput.js.map +1 -1
- package/build/esm/components/organisms/PromptInput/PromptInputCommands.d.ts +9 -0
- package/build/esm/components/organisms/PromptInput/PromptInputCommands.js +36 -0
- package/build/esm/components/organisms/PromptInput/PromptInputCommands.js.map +1 -0
- package/build/esm/components/organisms/PromptInput/PromptInputFull.d.ts +2 -0
- package/build/esm/components/organisms/PromptInput/PromptInputFull.js +4 -4
- package/build/esm/components/organisms/PromptInput/PromptInputFull.js.map +1 -1
- package/build/esm/components/organisms/PromptInput/PromptInputSimple.d.ts +2 -0
- package/build/esm/components/organisms/PromptInput/PromptInputSimple.js +3 -3
- package/build/esm/components/organisms/PromptInput/PromptInputSimple.js.map +1 -1
- package/build/esm/components/organisms/PromptInput/commandUtils.d.ts +13 -0
- package/build/esm/components/organisms/PromptInput/commandUtils.js +23 -0
- package/build/esm/components/organisms/PromptInput/commandUtils.js.map +1 -0
- package/build/esm/components/organisms/PromptInput/i18n/en.json +8 -0
- package/build/esm/components/organisms/PromptInput/i18n/index.d.ts +13 -0
- package/build/esm/components/organisms/PromptInput/i18n/index.js +6 -0
- package/build/esm/components/organisms/PromptInput/i18n/index.js.map +1 -0
- package/build/esm/components/organisms/PromptInput/i18n/ru.json +8 -0
- package/build/esm/components/organisms/PromptInput/index.d.ts +2 -1
- package/build/esm/components/organisms/PromptInput/index.js.map +1 -1
- package/build/esm/components/organisms/PromptInput/types.d.ts +1 -0
- package/build/esm/components/organisms/PromptInput/types.js.map +1 -1
- package/build/esm/components/organisms/PromptInput/usePromptCommands.d.ts +41 -0
- package/build/esm/components/organisms/PromptInput/usePromptCommands.js +219 -0
- package/build/esm/components/organisms/PromptInput/usePromptCommands.js.map +1 -0
- package/build/esm/components/organisms/PromptInput/usePromptInput.d.ts +10 -1
- package/build/esm/components/organisms/PromptInput/usePromptInput.js +101 -12
- package/build/esm/components/organisms/PromptInput/usePromptInput.js.map +1 -1
- package/build/esm/components/pages/AIStudioChat/AIStudioChat.js +139 -52
- package/build/esm/components/pages/AIStudioChat/AIStudioChat.js.map +1 -1
- package/build/esm/components/pages/AIStudioChat/request.d.ts +4 -0
- package/build/esm/components/pages/AIStudioChat/request.js +8 -0
- package/build/esm/components/pages/AIStudioChat/request.js.map +1 -0
- package/build/esm/components/pages/AIStudioChat/types.d.ts +5 -5
- package/build/esm/components/pages/AIStudioChat/types.js.map +1 -1
- package/build/esm/components/pages/ChatContainer/ChatContainer.js +12 -6
- package/build/esm/components/pages/ChatContainer/ChatContainer.js.map +1 -1
- package/build/esm/components/pages/ChatContainer/types.d.ts +1 -1
- package/build/esm/components/pages/ChatContainer/types.js.map +1 -1
- package/build/esm/components/pages/ChatContainer/useChatContainer.d.ts +1 -0
- package/build/esm/components/pages/ChatContainer/useChatContainer.js +5 -1
- package/build/esm/components/pages/ChatContainer/useChatContainer.js.map +1 -1
- package/build/esm/package.json +1 -1
- package/build/esm/types/index.d.ts +1 -0
- package/build/esm/types/index.js +1 -0
- package/build/esm/types/index.js.map +1 -1
- package/build/esm/types/messages.d.ts +3 -0
- package/build/esm/types/messages.js.map +1 -1
- package/build/esm/types/promptCommands.d.ts +44 -0
- package/build/esm/types/promptCommands.js +2 -0
- package/build/esm/types/promptCommands.js.map +1 -0
- 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: (
|
|
115
|
-
assistantMessageId: (
|
|
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
|
|
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
|
-
|
|
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:
|
|
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
|
-
|
|
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
|
|
196
|
-
|
|
197
|
-
|
|
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
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
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
|
-
|
|
221
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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: (
|
|
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: ((
|
|
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: (
|
|
359
|
-
showContextIndicator: (
|
|
360
|
-
contextIndicatorProps: (
|
|
361
|
-
contextItems: (
|
|
362
|
-
}, footerProps: Object.assign(Object.assign({}, (
|
|
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
|
|
39
|
+
* Return false/null to cancel the send entirely.
|
|
40
40
|
*/
|
|
41
|
-
onBeforeSend?: (params:
|
|
42
|
-
|
|
43
|
-
|
|
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
|
|
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"]}
|