@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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePromptInput.js","sourceRoot":"../../../../../src","sources":["components/organisms/PromptInput/usePromptInput.ts"],"names":[],"mappings":"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","sourcesContent":["import {useCallback, useState} from 'react';\n\nimport {ChatStatus, TSubmitData} from '../../../types';\n\n/**\n * Hook props for managing PromptInput state\n */\nexport type UsePromptInputProps = {\n /** Callback when message is sent */\n onSend: (data: TSubmitData) => Promise<void>;\n /** Callback when sending is cancelled */\n onCancel?: () => Promise<void>;\n /** Initial value */\n initialValue?: string;\n /** Maximum length of input */\n maxLength?: number;\n /** Disabled state */\n disabled?: boolean;\n /** Chat status to determine input behavior */\n status?: ChatStatus;\n /** Called whenever the hook changes its internal value. */\n onValueChange?: (value: string) => void;\n};\n\n/**\n * Hook return type for PromptInput state management\n */\nexport type UsePromptInputReturn = {\n /** Current input value */\n value: string;\n /** Can submit the form */\n canSubmit: boolean;\n /** Submit button state */\n submitButtonState: 'enabled' | 'disabled' | 'loading' | 'cancelable';\n /** Is input disabled (when loading) */\n isInputDisabled: boolean;\n /** Handle input change */\n handleChange: (value: string) => void;\n /** Handle key down */\n handleKeyDown: (event: React.KeyboardEvent<HTMLTextAreaElement>) => void;\n /** Handle submit */\n handleSubmit: () => Promise<void>;\n /** Attachments */\n attachments: File[];\n /** Set attachments */\n setAttachments: (files: File[]) => void;\n};\n\n/**\n * Custom hook for managing PromptInput state and behavior\n *\n * @param props - Hook props\n * @returns Hook return value with state and handlers\n */\nexport function usePromptInput(props: UsePromptInputProps): UsePromptInputReturn {\n const {\n onSend,\n onCancel,\n initialValue = '',\n maxLength,\n disabled = false,\n status = 'ready',\n onValueChange,\n } = props;\n\n const [value, setValue] = useState(initialValue);\n const [attachments, setAttachments] = useState<File[]>([]);\n\n const updateValue = useCallback(\n (nextValue: string) => {\n setValue(nextValue);\n onValueChange?.(nextValue);\n },\n [onValueChange],\n );\n const isSubmitted = status === 'submitted';\n\n const trimmedValue = value.trim();\n const canSubmit = !disabled && !isSubmitted && trimmedValue.length > 0;\n\n // Map ChatStatus to submit button state\n // ChatStatus.ready → submitButtonState.enabled\n // ChatStatus.error → submitButtonState.enabled\n // ChatStatus.streaming → submitButtonState.cancelable\n // ChatStatus.streaming_loading → submitButtonState.cancelable (same as streaming)\n // ChatStatus.submitted → submitButtonState.loading\n let submitButtonState: 'enabled' | 'disabled' | 'loading' | 'cancelable' = 'disabled';\n\n // disabled by props or empty value and status is ready\n if (disabled) {\n submitButtonState = 'disabled';\n } else if (!trimmedValue && (status === 'ready' || status === 'error')) {\n submitButtonState = 'disabled';\n } else {\n switch (status) {\n case 'ready':\n case 'error':\n submitButtonState = 'enabled';\n break;\n case 'streaming':\n case 'streaming_loading':\n submitButtonState = onCancel ? 'cancelable' : 'enabled';\n break;\n case 'submitted':\n submitButtonState = 'loading';\n break;\n default:\n submitButtonState = 'enabled';\n }\n }\n\n // Input is disabled when loading\n const isInputDisabled = submitButtonState === 'loading';\n\n const handleChange = useCallback(\n (newValue: string) => {\n if (maxLength && newValue.length > maxLength) {\n return;\n }\n updateValue(newValue);\n },\n [maxLength, updateValue],\n );\n\n const handleSubmit = useCallback(async () => {\n if (submitButtonState === 'cancelable' && onCancel) {\n await onCancel();\n return;\n }\n\n if (!canSubmit) {\n return;\n }\n\n const submitData: TSubmitData = {\n content: trimmedValue,\n ...(attachments.length > 0 && {attachments}),\n };\n\n onSend(submitData);\n updateValue('');\n setAttachments([]);\n }, [submitButtonState, canSubmit, trimmedValue, attachments, onSend, onCancel, updateValue]);\n\n const handleKeyDown = useCallback(\n (event: React.KeyboardEvent<HTMLTextAreaElement>) => {\n const isEnter = event.code === 'Enter' || event.code === 'NumpadEnter';\n\n // Insert new line on Ctrl/Cmd + Enter\n if (isEnter && (event.ctrlKey || event.metaKey)) {\n updateValue(`${value}\\n`);\n event.preventDefault();\n return;\n }\n\n // Prevent submission if can't submit\n if (isEnter && !event.shiftKey && !canSubmit) {\n event.preventDefault();\n return;\n }\n\n // Submit on Enter (without Shift)\n if (isEnter && !event.shiftKey && canSubmit) {\n event.preventDefault();\n handleSubmit();\n }\n },\n [canSubmit, handleSubmit, updateValue, value],\n );\n\n return {\n value,\n canSubmit,\n submitButtonState,\n isInputDisabled,\n handleChange,\n handleKeyDown,\n handleSubmit,\n attachments,\n setAttachments,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"usePromptInput.js","sourceRoot":"../../../../../src","sources":["components/organisms/PromptInput/usePromptInput.ts"],"names":[],"mappings":"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","sourcesContent":["import {useCallback, useEffect, useRef, useState} from 'react';\n\nimport {ChatStatus, TSubmitData} from '../../../types';\n\n/**\n * Hook props for managing PromptInput state\n */\nexport type UsePromptInputProps = {\n /** Callback when message is sent */\n onSend: (data: TSubmitData) => Promise<void | false>;\n resetKey?: string | number;\n captureSubmission?: () => {restore: () => void; hasChanged: () => boolean; clear: () => void};\n /** Callback when sending is cancelled */\n onCancel?: () => Promise<void>;\n /** Initial value */\n initialValue?: string;\n /** Maximum length of input */\n maxLength?: number;\n /** Disabled state */\n disabled?: boolean;\n /** Chat status to determine input behavior */\n status?: ChatStatus;\n /** Called whenever the hook changes its internal value. */\n onValueChange?: (value: string) => void;\n};\n\n/**\n * Hook return type for PromptInput state management\n */\nexport type UsePromptInputReturn = {\n sendError?: boolean;\n /** Current input value */\n value: string;\n /** Can submit the form */\n canSubmit: boolean;\n /** Submit button state */\n submitButtonState: 'enabled' | 'disabled' | 'loading' | 'cancelable';\n /** Is input disabled (when loading) */\n isInputDisabled: boolean;\n /** Handle input change */\n handleChange: (value: string) => void;\n /** Handle key down */\n handleKeyDown: (event: React.KeyboardEvent<HTMLTextAreaElement>) => void;\n /** Handle submit */\n handleSubmit: () => Promise<void>;\n submit: (data?: TSubmitData) => Promise<void>;\n clearFailedDraft: () => boolean;\n /** Attachments */\n attachments: File[];\n /** Set attachments */\n setAttachments: (files: File[]) => void;\n};\n\n/**\n * Custom hook for managing PromptInput state and behavior\n *\n * @param props - Hook props\n * @returns Hook return value with state and handlers\n */\nexport function usePromptInput(props: UsePromptInputProps): UsePromptInputReturn {\n const {\n onSend,\n onCancel,\n initialValue = '',\n maxLength,\n disabled = false,\n status = 'ready',\n onValueChange,\n resetKey,\n captureSubmission,\n } = props;\n\n const [value, setValue] = useState(initialValue);\n const [sending, setSending] = useState(false);\n const [sendError, setSendError] = useState(false);\n const mounted = useRef(true);\n useEffect(() => {\n mounted.current = true;\n return () => {\n mounted.current = false;\n };\n }, []);\n const revision = useRef(0);\n const inFlight = useRef(false);\n const [attachments, updateAttachments] = useState<File[]>([]);\n const setAttachments = useCallback((files: File[]) => {\n revision.current++;\n updateAttachments(files);\n }, []);\n const failedDraft = useRef<(() => boolean) | null>(null);\n useEffect(() => {\n revision.current++;\n failedDraft.current = null;\n }, [resetKey]);\n\n const updateValue = useCallback(\n (nextValue: string) => {\n revision.current++;\n setSendError(false);\n setValue(nextValue);\n onValueChange?.(nextValue);\n },\n [onValueChange],\n );\n const isSubmitted = status === 'submitted' || sending;\n\n const trimmedValue = value.trim();\n const canSubmit = !disabled && !isSubmitted && trimmedValue.length > 0;\n\n // Map ChatStatus to submit button state\n // ChatStatus.ready → submitButtonState.enabled\n // ChatStatus.error → submitButtonState.enabled\n // ChatStatus.streaming → submitButtonState.cancelable\n // ChatStatus.streaming_loading → submitButtonState.cancelable (same as streaming)\n // ChatStatus.submitted → submitButtonState.loading\n let submitButtonState: 'enabled' | 'disabled' | 'loading' | 'cancelable' = 'disabled';\n\n // disabled by props or empty value and status is ready\n if (disabled) {\n submitButtonState = 'disabled';\n } else if (!trimmedValue && (status === 'ready' || status === 'error')) {\n submitButtonState = 'disabled';\n } else {\n switch (status) {\n case 'ready':\n case 'error':\n submitButtonState = 'enabled';\n break;\n case 'streaming':\n case 'streaming_loading':\n submitButtonState = onCancel ? 'cancelable' : 'enabled';\n break;\n case 'submitted':\n submitButtonState = 'loading';\n break;\n default:\n submitButtonState = 'enabled';\n }\n }\n\n // Input is disabled when loading\n if (sending && submitButtonState !== 'cancelable') submitButtonState = 'loading';\n const isInputDisabled = submitButtonState === 'loading';\n\n const handleChange = useCallback(\n (newValue: string) => {\n if (maxLength && newValue.length > maxLength) {\n return;\n }\n updateValue(newValue);\n },\n [maxLength, updateValue],\n );\n\n const submit = useCallback(\n async (override?: TSubmitData) => {\n const content = override?.content.trim() ?? trimmedValue;\n if (disabled || isSubmitted || inFlight.current || !content) return;\n const draftValue = value;\n const submitData: TSubmitData = {\n ...override,\n content,\n ...(attachments.length > 0 && {attachments}),\n };\n inFlight.current = true;\n setSending(true);\n setSendError(false);\n failedDraft.current = null;\n const selectionSnapshot = captureSubmission?.();\n updateValue('');\n updateAttachments([]);\n const clearedRevision = revision.current;\n const restore = () => {\n if (\n !mounted.current ||\n revision.current !== clearedRevision ||\n selectionSnapshot?.hasChanged()\n )\n return;\n updateValue(draftValue);\n updateAttachments(attachments);\n selectionSnapshot?.restore();\n const restoredRevision = revision.current;\n failedDraft.current = () => {\n if (\n !mounted.current ||\n revision.current !== restoredRevision ||\n selectionSnapshot?.hasChanged()\n )\n return false;\n updateValue('');\n updateAttachments([]);\n selectionSnapshot?.clear();\n return true;\n };\n return true;\n };\n try {\n const result = await onSend(submitData);\n if (result === false) restore();\n } catch {\n if (restore()) setSendError(true);\n } finally {\n inFlight.current = false;\n if (mounted.current) setSending(false);\n }\n },\n [\n disabled,\n isSubmitted,\n trimmedValue,\n value,\n attachments,\n onSend,\n updateValue,\n captureSubmission,\n ],\n );\n\n const clearFailedDraft = useCallback(() => {\n const clear = failedDraft.current;\n failedDraft.current = null;\n return clear?.() ?? false;\n }, []);\n\n const handleSubmit = useCallback(async () => {\n if (submitButtonState === 'cancelable' && onCancel) {\n await onCancel();\n return;\n }\n await submit();\n }, [submitButtonState, onCancel, submit]);\n\n const handleKeyDown = useCallback(\n (event: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (event.nativeEvent.isComposing || event.defaultPrevented) return;\n const isEnter = event.code === 'Enter' || event.code === 'NumpadEnter';\n\n // Insert new line on Ctrl/Cmd + Enter\n if (isEnter && (event.ctrlKey || event.metaKey)) {\n updateValue(`${value}\\n`);\n event.preventDefault();\n return;\n }\n\n // Prevent submission if can't submit\n if (isEnter && !event.shiftKey && !canSubmit) {\n event.preventDefault();\n return;\n }\n\n // Submit on Enter (without Shift)\n if (isEnter && !event.shiftKey && canSubmit) {\n event.preventDefault();\n handleSubmit();\n }\n },\n [canSubmit, handleSubmit, updateValue, value],\n );\n\n return {\n value,\n sendError,\n canSubmit,\n submitButtonState,\n isInputDisabled,\n handleChange,\n handleKeyDown,\n handleSubmit,\n submit,\n clearFailedDraft,\n attachments,\n setAttachments,\n };\n}\n"]}
|
|
@@ -4,6 +4,7 @@ exports.AIStudioChat = AIStudioChat;
|
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
6
6
|
const react_1 = require("react");
|
|
7
|
+
const uikit_1 = require("@gravity-ui/uikit");
|
|
7
8
|
const uuid_1 = require("uuid");
|
|
8
9
|
const openai_1 = require("../../../adapters/openai/index.js");
|
|
9
10
|
const types_1 = require("../../../types/index.js");
|
|
@@ -11,6 +12,7 @@ const messageTypeRegistry_1 = require("../../../utils/messageTypeRegistry.js");
|
|
|
11
12
|
const InputContext_1 = require("../../molecules/InputContext/index.js");
|
|
12
13
|
const ChatContainer_1 = require("../ChatContainer/index.js");
|
|
13
14
|
const McpToolRenderer_1 = require("./McpToolRenderer.js");
|
|
15
|
+
const request_1 = require("./request.js");
|
|
14
16
|
const transforms_1 = require("./transforms/index.js");
|
|
15
17
|
function isFileAttachment(value) {
|
|
16
18
|
if (!value || typeof value !== 'object')
|
|
@@ -77,9 +79,21 @@ function AIStudioChat(props) {
|
|
|
77
79
|
return ((0, jsx_runtime_1.jsx)(InputContext_1.InputContextProvider, { fileUpload: fileUpload, fileDialogTitle: fileDialogTitle, children: (0, jsx_runtime_1.jsx)(AIStudioChatInner, Object.assign({}, rest)) }));
|
|
78
80
|
}
|
|
79
81
|
function AIStudioChatInner(props) {
|
|
80
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
|
|
81
|
-
const { apiUrl, initialMessages = [], showHistory = false, showNewChat = showHistory, systemPrompt, requestInit, extraRequestParams, trackTokenUsage = true, onBeforeSend } = props, chatContainerProps = tslib_1.__rest(props, ["apiUrl", "initialMessages", "showHistory", "showNewChat", "systemPrompt", "requestInit", "extraRequestParams", "trackTokenUsage", "onBeforeSend"]);
|
|
82
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
|
|
83
|
+
const { apiUrl, initialMessages = [], showHistory = false, showNewChat = showHistory, systemPrompt, requestInit, extraRequestParams, trackTokenUsage = true, onBeforeSend, transformRequest } = props, chatContainerProps = tslib_1.__rest(props, ["apiUrl", "initialMessages", "showHistory", "showNewChat", "systemPrompt", "requestInit", "extraRequestParams", "trackTokenUsage", "onBeforeSend", "transformRequest"]);
|
|
82
84
|
const { prepareFilesForSend, reset, contextItems, attachmentContent } = (0, InputContext_1.useInputContext)();
|
|
85
|
+
const promptApiRef = (0, react_1.useRef)(null);
|
|
86
|
+
const mergedPromptApiRef = (0, uikit_1.useForkRef)(promptApiRef, (_a = chatContainerProps.promptInputProps) === null || _a === void 0 ? void 0 : _a.apiRef);
|
|
87
|
+
const fileDraftKey = JSON.stringify(contextItems.map((item) => item.id));
|
|
88
|
+
const latestFileDraftKey = (0, react_1.useRef)(fileDraftKey);
|
|
89
|
+
latestFileDraftKey.current = fileDraftKey;
|
|
90
|
+
const failedFileDraftKey = (0, react_1.useRef)();
|
|
91
|
+
// Keep the exact mapped request for retry, independently of later draft selections.
|
|
92
|
+
const sentRequests = (0, react_1.useRef)(new Map());
|
|
93
|
+
const sendEpoch = (0, react_1.useRef)(0);
|
|
94
|
+
const [commandsResetKey, setCommandsResetKey] = (0, react_1.useState)(0);
|
|
95
|
+
const [sendError, setSendError] = (0, react_1.useState)(null);
|
|
96
|
+
const [failedAttempt, setFailedAttempt] = (0, react_1.useState)(null);
|
|
83
97
|
// Current chat messages
|
|
84
98
|
const [messages, setMessages] = (0, react_1.useState)(initialMessages);
|
|
85
99
|
// Multi-chat state (used when showHistory=true)
|
|
@@ -114,8 +128,8 @@ function AIStudioChatInner(props) {
|
|
|
114
128
|
}
|
|
115
129
|
}, []);
|
|
116
130
|
const streamResult = (0, openai_1.useOpenAIStreamAdapter)(streamSource, {
|
|
117
|
-
initialMessages: (
|
|
118
|
-
assistantMessageId: (
|
|
131
|
+
initialMessages: (_b = streamOptions === null || streamOptions === void 0 ? void 0 : streamOptions.initialMessages) !== null && _b !== void 0 ? _b : [],
|
|
132
|
+
assistantMessageId: (_c = streamOptions === null || streamOptions === void 0 ? void 0 : streamOptions.assistantMessageId) !== null && _c !== void 0 ? _c : 'assistant-idle',
|
|
119
133
|
onStreamEnd: handleStreamEnd,
|
|
120
134
|
trackTokenUsage,
|
|
121
135
|
});
|
|
@@ -126,43 +140,35 @@ function AIStudioChatInner(props) {
|
|
|
126
140
|
}
|
|
127
141
|
}, [streamResult.responseId]);
|
|
128
142
|
const hasSource = Boolean(streamSource);
|
|
129
|
-
const
|
|
143
|
+
const pendingMessages = failedAttempt ? [...messages, failedAttempt.message] : messages;
|
|
144
|
+
const displayMessages = hasSource && streamResult.messages.length > 0 ? streamResult.messages : pendingMessages;
|
|
130
145
|
const status = (0, react_1.useMemo)(() => {
|
|
131
146
|
if (!hasSource) {
|
|
132
|
-
|
|
147
|
+
if (isFetching)
|
|
148
|
+
return 'submitted';
|
|
149
|
+
return sendError ? 'error' : 'ready';
|
|
133
150
|
}
|
|
134
151
|
if (streamResult.status === 'streaming')
|
|
135
152
|
return 'streaming';
|
|
136
153
|
if (streamResult.status === 'error')
|
|
137
154
|
return 'error';
|
|
138
155
|
return 'ready';
|
|
139
|
-
}, [hasSource, isFetching, streamResult.status]);
|
|
156
|
+
}, [hasSource, isFetching, streamResult.status, sendError]);
|
|
140
157
|
/**
|
|
141
158
|
* Core send function. Takes an already-resolved set of previous messages and
|
|
142
159
|
* pre-converted base64 images so it can be called both from handleSendMessage
|
|
143
160
|
* (which converts File objects) and from handleRetry (which reuses stored images).
|
|
144
161
|
*/
|
|
145
|
-
const performSend = (0, react_1.useCallback)(async ({ previousMessages, content, base64Images = [], perSendParams = {}, }) => {
|
|
146
|
-
// Auto-create a chat when history is enabled and no chat is active yet
|
|
147
|
-
if (showHistory && !activeChatRef.current) {
|
|
148
|
-
const newChat = {
|
|
149
|
-
id: (0, uuid_1.v4)(),
|
|
150
|
-
name: deriveChatName(content),
|
|
151
|
-
createTime: new Date().toISOString(),
|
|
152
|
-
};
|
|
153
|
-
chatMessagesRef.current[newChat.id] = [];
|
|
154
|
-
activeChatRef.current = newChat;
|
|
155
|
-
setActiveChat(newChat);
|
|
156
|
-
setChats((prev) => [newChat, ...prev]);
|
|
157
|
-
}
|
|
162
|
+
const performSend = (0, react_1.useCallback)(async ({ previousMessages, content, base64Images = [], perSendParams = {}, submitData, retryRequest, }) => {
|
|
158
163
|
const rawFileIds = Array.isArray(perSendParams.fileIds)
|
|
159
164
|
? perSendParams.fileIds
|
|
160
165
|
: undefined;
|
|
161
166
|
const rawFileAttachments = Array.isArray(perSendParams.fileAttachments)
|
|
162
167
|
? perSendParams.fileAttachments.filter(isFileAttachment)
|
|
163
168
|
: undefined;
|
|
169
|
+
const userMessageId = (0, uuid_1.v4)();
|
|
164
170
|
const userMessage = {
|
|
165
|
-
id:
|
|
171
|
+
id: userMessageId,
|
|
166
172
|
role: 'user',
|
|
167
173
|
content,
|
|
168
174
|
images: base64Images.length > 0 ? base64Images : undefined,
|
|
@@ -170,8 +176,10 @@ function AIStudioChatInner(props) {
|
|
|
170
176
|
};
|
|
171
177
|
const messagesWithUser = [...previousMessages, userMessage];
|
|
172
178
|
const assistantMessageId = (0, uuid_1.v4)();
|
|
173
|
-
|
|
179
|
+
const epoch = sendEpoch.current;
|
|
174
180
|
setIsFetching(true);
|
|
181
|
+
setSendError(null);
|
|
182
|
+
setFailedAttempt(null);
|
|
175
183
|
const abortController = new AbortController();
|
|
176
184
|
setController(abortController);
|
|
177
185
|
try {
|
|
@@ -195,61 +203,114 @@ function AIStudioChatInner(props) {
|
|
|
195
203
|
})),
|
|
196
204
|
{ role: 'user', content: lastUserContent },
|
|
197
205
|
];
|
|
198
|
-
const
|
|
199
|
-
|
|
200
|
-
|
|
206
|
+
const baseRequest = Object.assign(Object.assign(Object.assign({ messages: apiMessages }, extraRequestParams), perSendParams), (responseIdRef.current ? { previousResponseId: responseIdRef.current } : {}));
|
|
207
|
+
const body = await (0, request_1.serializeChatRequest)(baseRequest, submitData !== null && submitData !== void 0 ? submitData : { content }, transformRequest, retryRequest);
|
|
208
|
+
if (body === false || epoch !== sendEpoch.current)
|
|
209
|
+
return false;
|
|
210
|
+
sentRequests.current.set(userMessageId, body);
|
|
211
|
+
// Auto-create a chat when history is enabled and no chat is active yet
|
|
212
|
+
if (showHistory && !activeChatRef.current) {
|
|
213
|
+
const newChat = {
|
|
214
|
+
id: (0, uuid_1.v4)(),
|
|
215
|
+
name: deriveChatName(content),
|
|
216
|
+
createTime: new Date().toISOString(),
|
|
217
|
+
};
|
|
218
|
+
chatMessagesRef.current[newChat.id] = [];
|
|
219
|
+
activeChatRef.current = newChat;
|
|
220
|
+
setActiveChat(newChat);
|
|
221
|
+
setChats((prev) => [newChat, ...prev]);
|
|
222
|
+
}
|
|
223
|
+
setMessages(messagesWithUser);
|
|
224
|
+
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 }));
|
|
225
|
+
if (epoch !== sendEpoch.current)
|
|
226
|
+
return false;
|
|
201
227
|
if (!response.ok) {
|
|
202
228
|
throw new Error(`API error: ${response.status} ${response.statusText}`);
|
|
203
229
|
}
|
|
204
230
|
setStreamSource((0, transforms_1.normalizeMcpCallIds)((0, transforms_1.omitMcpListToolsEvents)((0, openai_1.fetchResponseToStreamEvents)(response))));
|
|
205
231
|
setStreamOptions({ initialMessages: messagesWithUser, assistantMessageId });
|
|
232
|
+
return true;
|
|
206
233
|
}
|
|
207
234
|
catch (error) {
|
|
235
|
+
if (epoch !== sendEpoch.current)
|
|
236
|
+
return false;
|
|
237
|
+
// Roll back the optimistic attempt; errors and failed messages are UI state only.
|
|
238
|
+
setMessages(previousMessages);
|
|
208
239
|
if (error.name !== 'AbortError') {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
240
|
+
setSendError(error instanceof Error ? error : new Error(String(error)));
|
|
241
|
+
setFailedAttempt({
|
|
242
|
+
message: userMessage,
|
|
243
|
+
request: {
|
|
244
|
+
previousMessages,
|
|
245
|
+
content,
|
|
246
|
+
base64Images,
|
|
247
|
+
perSendParams,
|
|
248
|
+
submitData,
|
|
249
|
+
retryRequest: sentRequests.current.get(userMessageId),
|
|
250
|
+
},
|
|
217
251
|
});
|
|
218
252
|
}
|
|
219
253
|
setStreamSource(null);
|
|
220
254
|
setStreamOptions(null);
|
|
255
|
+
return false;
|
|
221
256
|
}
|
|
222
257
|
finally {
|
|
223
|
-
|
|
224
|
-
|
|
258
|
+
if (epoch === sendEpoch.current) {
|
|
259
|
+
setIsFetching(false);
|
|
260
|
+
setController(null);
|
|
261
|
+
}
|
|
225
262
|
}
|
|
226
|
-
}, [showHistory, systemPrompt, requestInit, apiUrl, extraRequestParams]);
|
|
263
|
+
}, [showHistory, systemPrompt, requestInit, apiUrl, extraRequestParams, transformRequest]);
|
|
227
264
|
const handleSendMessage = (0, react_1.useCallback)(async (data) => {
|
|
265
|
+
const epoch = sendEpoch.current;
|
|
228
266
|
// Call onBeforeSend hook — allows caller to inject per-request params or cancel send
|
|
229
267
|
let perSendParams = {};
|
|
230
268
|
if (onBeforeSend) {
|
|
231
|
-
const result = await onBeforeSend(
|
|
269
|
+
const result = await onBeforeSend(data);
|
|
232
270
|
if (result === false || result === null)
|
|
233
|
-
return;
|
|
271
|
+
return false;
|
|
234
272
|
if (result)
|
|
235
273
|
perSendParams = result;
|
|
236
274
|
}
|
|
237
275
|
const { base64Images, perSendFileParams } = await prepareFilesForSend(data.attachments);
|
|
238
|
-
|
|
276
|
+
if (epoch !== sendEpoch.current)
|
|
277
|
+
return false;
|
|
278
|
+
const accepted = await performSend({
|
|
279
|
+
submitData: data,
|
|
239
280
|
previousMessages: messages,
|
|
240
281
|
content: data.content,
|
|
241
282
|
base64Images,
|
|
242
283
|
perSendParams: Object.assign(Object.assign({}, perSendParams), perSendFileParams),
|
|
243
284
|
});
|
|
285
|
+
if (epoch !== sendEpoch.current)
|
|
286
|
+
return false;
|
|
287
|
+
if (!accepted) {
|
|
288
|
+
failedFileDraftKey.current = fileDraftKey;
|
|
289
|
+
return false;
|
|
290
|
+
}
|
|
244
291
|
reset();
|
|
245
|
-
|
|
292
|
+
return undefined;
|
|
293
|
+
}, [messages, onBeforeSend, performSend, prepareFilesForSend, reset, fileDraftKey]);
|
|
246
294
|
const handleCancel = (0, react_1.useCallback)(async () => {
|
|
295
|
+
sendEpoch.current++;
|
|
296
|
+
setIsFetching(false);
|
|
247
297
|
controller === null || controller === void 0 ? void 0 : controller.abort();
|
|
248
298
|
setStreamSource(null);
|
|
249
299
|
setStreamOptions(null);
|
|
250
300
|
}, [controller]);
|
|
251
301
|
const handleRetry = (0, react_1.useCallback)(async () => {
|
|
252
|
-
var _a;
|
|
302
|
+
var _a, _b;
|
|
303
|
+
if (failedAttempt) {
|
|
304
|
+
const epoch = sendEpoch.current;
|
|
305
|
+
const accepted = await performSend(failedAttempt.request);
|
|
306
|
+
if (accepted &&
|
|
307
|
+
epoch === sendEpoch.current &&
|
|
308
|
+
latestFileDraftKey.current === failedFileDraftKey.current &&
|
|
309
|
+
((_a = promptApiRef.current) === null || _a === void 0 ? void 0 : _a.clearFailedDraft())) {
|
|
310
|
+
reset();
|
|
311
|
+
}
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
253
314
|
const lastUserMsg = [...messages]
|
|
254
315
|
.reverse()
|
|
255
316
|
.find((m) => m.role === 'user');
|
|
@@ -259,12 +320,22 @@ function AIStudioChatInner(props) {
|
|
|
259
320
|
const trimmedMessages = messages.slice(0, lastUserIndex);
|
|
260
321
|
await performSend({
|
|
261
322
|
previousMessages: trimmedMessages,
|
|
323
|
+
retryRequest: lastUserMsg.id ? sentRequests.current.get(lastUserMsg.id) : undefined,
|
|
262
324
|
content: lastUserMsg.content,
|
|
325
|
+
perSendParams: { fileAttachments: lastUserMsg.fileAttachments },
|
|
263
326
|
// Reuse images stored on the original message — no FileReader needed
|
|
264
|
-
base64Images: (
|
|
327
|
+
base64Images: (_b = lastUserMsg.images) !== null && _b !== void 0 ? _b : [],
|
|
265
328
|
});
|
|
266
|
-
}, [messages, performSend]);
|
|
329
|
+
}, [messages, performSend, failedAttempt, reset]);
|
|
267
330
|
const handleCreateChat = (0, react_1.useCallback)(() => {
|
|
331
|
+
setCommandsResetKey((key) => key + 1);
|
|
332
|
+
setFailedAttempt(null);
|
|
333
|
+
setSendError(null);
|
|
334
|
+
sendEpoch.current++;
|
|
335
|
+
controller === null || controller === void 0 ? void 0 : controller.abort();
|
|
336
|
+
setIsFetching(false);
|
|
337
|
+
setStreamSource(null);
|
|
338
|
+
setStreamOptions(null);
|
|
268
339
|
const current = activeChatRef.current;
|
|
269
340
|
if (current) {
|
|
270
341
|
chatMessagesRef.current[current.id] = messages;
|
|
@@ -280,9 +351,17 @@ function AIStudioChatInner(props) {
|
|
|
280
351
|
setActiveChat(newChat);
|
|
281
352
|
setMessages([]);
|
|
282
353
|
reset();
|
|
283
|
-
}, [messages, reset]);
|
|
354
|
+
}, [messages, reset, controller]);
|
|
284
355
|
const handleSelectChat = (0, react_1.useCallback)((chat) => {
|
|
285
356
|
var _a;
|
|
357
|
+
setCommandsResetKey((key) => key + 1);
|
|
358
|
+
setFailedAttempt(null);
|
|
359
|
+
setSendError(null);
|
|
360
|
+
sendEpoch.current++;
|
|
361
|
+
controller === null || controller === void 0 ? void 0 : controller.abort();
|
|
362
|
+
setIsFetching(false);
|
|
363
|
+
setStreamSource(null);
|
|
364
|
+
setStreamOptions(null);
|
|
286
365
|
const current = activeChatRef.current;
|
|
287
366
|
if (current) {
|
|
288
367
|
chatMessagesRef.current[current.id] = messages;
|
|
@@ -291,18 +370,26 @@ function AIStudioChatInner(props) {
|
|
|
291
370
|
setActiveChat(chat);
|
|
292
371
|
setMessages((_a = chatMessagesRef.current[chat.id]) !== null && _a !== void 0 ? _a : []);
|
|
293
372
|
reset();
|
|
294
|
-
}, [messages, reset]);
|
|
373
|
+
}, [messages, reset, controller]);
|
|
295
374
|
const handleDeleteChat = (0, react_1.useCallback)(async (chat) => {
|
|
296
375
|
var _a;
|
|
297
376
|
delete chatMessagesRef.current[chat.id];
|
|
298
377
|
setChats((prev) => prev.filter((c) => c.id !== chat.id));
|
|
299
378
|
if (((_a = activeChatRef.current) === null || _a === void 0 ? void 0 : _a.id) === chat.id) {
|
|
379
|
+
setCommandsResetKey((key) => key + 1);
|
|
380
|
+
setFailedAttempt(null);
|
|
381
|
+
setSendError(null);
|
|
382
|
+
sendEpoch.current++;
|
|
383
|
+
controller === null || controller === void 0 ? void 0 : controller.abort();
|
|
384
|
+
setIsFetching(false);
|
|
385
|
+
setStreamSource(null);
|
|
386
|
+
setStreamOptions(null);
|
|
300
387
|
responseIdRef.current = null;
|
|
301
388
|
setActiveChat(null);
|
|
302
389
|
setMessages([]);
|
|
303
390
|
reset();
|
|
304
391
|
}
|
|
305
|
-
}, [reset]);
|
|
392
|
+
}, [reset, controller]);
|
|
306
393
|
/**
|
|
307
394
|
* Update `userRating` on an assistant message inside the internal store.
|
|
308
395
|
* Mirrors the change into the per-chat history map so it survives chat switches.
|
|
@@ -355,13 +442,13 @@ function AIStudioChatInner(props) {
|
|
|
355
442
|
});
|
|
356
443
|
return Object.assign(Object.assign({}, original), { assistantActions: wrappedAssistantActions, messageRendererRegistry });
|
|
357
444
|
}, [chatContainerProps.messageListConfig, setUserRating]);
|
|
358
|
-
return ((0, jsx_runtime_1.jsx)(ChatContainer_1.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: ((
|
|
445
|
+
return ((0, jsx_runtime_1.jsx)(ChatContainer_1.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)
|
|
359
446
|
? chatContainerProps.promptInputProps.headerProps
|
|
360
447
|
: {
|
|
361
|
-
qa: (
|
|
362
|
-
showContextIndicator: (
|
|
363
|
-
contextIndicatorProps: (
|
|
364
|
-
contextItems: (
|
|
365
|
-
}, footerProps: Object.assign(Object.assign({}, (
|
|
448
|
+
qa: (_g = (_f = chatContainerProps.promptInputProps) === null || _f === void 0 ? void 0 : _f.headerProps) === null || _g === void 0 ? void 0 : _g.qa,
|
|
449
|
+
showContextIndicator: (_j = (_h = chatContainerProps.promptInputProps) === null || _h === void 0 ? void 0 : _h.headerProps) === null || _j === void 0 ? void 0 : _j.showContextIndicator,
|
|
450
|
+
contextIndicatorProps: (_l = (_k = chatContainerProps.promptInputProps) === null || _k === void 0 ? void 0 : _k.headerProps) === null || _l === void 0 ? void 0 : _l.contextIndicatorProps,
|
|
451
|
+
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,
|
|
452
|
+
}, 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 }) }) })));
|
|
366
453
|
}
|
|
367
454
|
//# 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>;
|