@gravity-ui/aikit 2.24.1-beta.883c85d04b93d8521b2733baa3e86da20249b4e7.0 → 2.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/build/cjs/components/molecules/PromptInputBody/PromptInputBody.d.ts +1 -0
  2. package/build/cjs/components/molecules/PromptInputBody/PromptInputBody.js +2 -8
  3. package/build/cjs/components/molecules/PromptInputBody/PromptInputBody.js.map +1 -1
  4. package/build/cjs/components/organisms/PromptInput/PromptInput.css +37 -0
  5. package/build/cjs/components/organisms/PromptInput/PromptInput.d.ts +13 -2
  6. package/build/cjs/components/organisms/PromptInput/PromptInput.js +64 -3
  7. package/build/cjs/components/organisms/PromptInput/PromptInput.js.map +1 -1
  8. package/build/cjs/components/organisms/PromptInput/PromptInputCommands.d.ts +9 -0
  9. package/build/cjs/components/organisms/PromptInput/PromptInputCommands.js +39 -0
  10. package/build/cjs/components/organisms/PromptInput/PromptInputCommands.js.map +1 -0
  11. package/build/cjs/components/organisms/PromptInput/PromptInputFull.d.ts +2 -0
  12. package/build/cjs/components/organisms/PromptInput/PromptInputFull.js +4 -4
  13. package/build/cjs/components/organisms/PromptInput/PromptInputFull.js.map +1 -1
  14. package/build/cjs/components/organisms/PromptInput/PromptInputSimple.d.ts +2 -0
  15. package/build/cjs/components/organisms/PromptInput/PromptInputSimple.js +3 -3
  16. package/build/cjs/components/organisms/PromptInput/PromptInputSimple.js.map +1 -1
  17. package/build/cjs/components/organisms/PromptInput/commandUtils.d.ts +13 -0
  18. package/build/cjs/components/organisms/PromptInput/commandUtils.js +27 -0
  19. package/build/cjs/components/organisms/PromptInput/commandUtils.js.map +1 -0
  20. package/build/cjs/components/organisms/PromptInput/i18n/en.json +8 -0
  21. package/build/cjs/components/organisms/PromptInput/i18n/index.d.ts +13 -0
  22. package/build/cjs/components/organisms/PromptInput/i18n/index.js +10 -0
  23. package/build/cjs/components/organisms/PromptInput/i18n/index.js.map +1 -0
  24. package/build/cjs/components/organisms/PromptInput/i18n/ru.json +8 -0
  25. package/build/cjs/components/organisms/PromptInput/index.d.ts +2 -1
  26. package/build/cjs/components/organisms/PromptInput/index.js.map +1 -1
  27. package/build/cjs/components/organisms/PromptInput/types.d.ts +1 -0
  28. package/build/cjs/components/organisms/PromptInput/types.js.map +1 -1
  29. package/build/cjs/components/organisms/PromptInput/usePromptCommands.d.ts +41 -0
  30. package/build/cjs/components/organisms/PromptInput/usePromptCommands.js +222 -0
  31. package/build/cjs/components/organisms/PromptInput/usePromptCommands.js.map +1 -0
  32. package/build/cjs/components/organisms/PromptInput/usePromptInput.d.ts +10 -1
  33. package/build/cjs/components/organisms/PromptInput/usePromptInput.js +100 -11
  34. package/build/cjs/components/organisms/PromptInput/usePromptInput.js.map +1 -1
  35. package/build/cjs/components/pages/AIStudioChat/AIStudioChat.js +139 -52
  36. package/build/cjs/components/pages/AIStudioChat/AIStudioChat.js.map +1 -1
  37. package/build/cjs/components/pages/AIStudioChat/request.d.ts +4 -0
  38. package/build/cjs/components/pages/AIStudioChat/request.js +11 -0
  39. package/build/cjs/components/pages/AIStudioChat/request.js.map +1 -0
  40. package/build/cjs/components/pages/AIStudioChat/types.d.ts +5 -5
  41. package/build/cjs/components/pages/AIStudioChat/types.js.map +1 -1
  42. package/build/cjs/components/pages/ChatContainer/ChatContainer.js +10 -4
  43. package/build/cjs/components/pages/ChatContainer/ChatContainer.js.map +1 -1
  44. package/build/cjs/components/pages/ChatContainer/types.d.ts +1 -1
  45. package/build/cjs/components/pages/ChatContainer/types.js.map +1 -1
  46. package/build/cjs/components/pages/ChatContainer/useChatContainer.d.ts +1 -0
  47. package/build/cjs/components/pages/ChatContainer/useChatContainer.js +5 -1
  48. package/build/cjs/components/pages/ChatContainer/useChatContainer.js.map +1 -1
  49. package/build/cjs/package.json +1 -1
  50. package/build/cjs/types/index.d.ts +1 -0
  51. package/build/cjs/types/index.js +1 -0
  52. package/build/cjs/types/index.js.map +1 -1
  53. package/build/cjs/types/messages.d.ts +3 -0
  54. package/build/cjs/types/messages.js.map +1 -1
  55. package/build/cjs/types/promptCommands.d.ts +44 -0
  56. package/build/cjs/types/promptCommands.js +3 -0
  57. package/build/cjs/types/promptCommands.js.map +1 -0
  58. package/build/docs/components/molecules/PromptInputBody.md +16 -15
  59. package/build/docs/components/organisms/PromptInput.md +151 -0
  60. package/build/docs/components/pages/AIStudioChat.md +38 -0
  61. package/build/esm/components/molecules/PromptInputBody/PromptInputBody.d.ts +1 -0
  62. package/build/esm/components/molecules/PromptInputBody/PromptInputBody.js +2 -8
  63. package/build/esm/components/molecules/PromptInputBody/PromptInputBody.js.map +1 -1
  64. package/build/esm/components/organisms/PromptInput/PromptInput.css +37 -0
  65. package/build/esm/components/organisms/PromptInput/PromptInput.d.ts +13 -2
  66. package/build/esm/components/organisms/PromptInput/PromptInput.js +65 -4
  67. package/build/esm/components/organisms/PromptInput/PromptInput.js.map +1 -1
  68. package/build/esm/components/organisms/PromptInput/PromptInputCommands.d.ts +9 -0
  69. package/build/esm/components/organisms/PromptInput/PromptInputCommands.js +36 -0
  70. package/build/esm/components/organisms/PromptInput/PromptInputCommands.js.map +1 -0
  71. package/build/esm/components/organisms/PromptInput/PromptInputFull.d.ts +2 -0
  72. package/build/esm/components/organisms/PromptInput/PromptInputFull.js +4 -4
  73. package/build/esm/components/organisms/PromptInput/PromptInputFull.js.map +1 -1
  74. package/build/esm/components/organisms/PromptInput/PromptInputSimple.d.ts +2 -0
  75. package/build/esm/components/organisms/PromptInput/PromptInputSimple.js +3 -3
  76. package/build/esm/components/organisms/PromptInput/PromptInputSimple.js.map +1 -1
  77. package/build/esm/components/organisms/PromptInput/commandUtils.d.ts +13 -0
  78. package/build/esm/components/organisms/PromptInput/commandUtils.js +23 -0
  79. package/build/esm/components/organisms/PromptInput/commandUtils.js.map +1 -0
  80. package/build/esm/components/organisms/PromptInput/i18n/en.json +8 -0
  81. package/build/esm/components/organisms/PromptInput/i18n/index.d.ts +13 -0
  82. package/build/esm/components/organisms/PromptInput/i18n/index.js +6 -0
  83. package/build/esm/components/organisms/PromptInput/i18n/index.js.map +1 -0
  84. package/build/esm/components/organisms/PromptInput/i18n/ru.json +8 -0
  85. package/build/esm/components/organisms/PromptInput/index.d.ts +2 -1
  86. package/build/esm/components/organisms/PromptInput/index.js.map +1 -1
  87. package/build/esm/components/organisms/PromptInput/types.d.ts +1 -0
  88. package/build/esm/components/organisms/PromptInput/types.js.map +1 -1
  89. package/build/esm/components/organisms/PromptInput/usePromptCommands.d.ts +41 -0
  90. package/build/esm/components/organisms/PromptInput/usePromptCommands.js +219 -0
  91. package/build/esm/components/organisms/PromptInput/usePromptCommands.js.map +1 -0
  92. package/build/esm/components/organisms/PromptInput/usePromptInput.d.ts +10 -1
  93. package/build/esm/components/organisms/PromptInput/usePromptInput.js +101 -12
  94. package/build/esm/components/organisms/PromptInput/usePromptInput.js.map +1 -1
  95. package/build/esm/components/pages/AIStudioChat/AIStudioChat.js +139 -52
  96. package/build/esm/components/pages/AIStudioChat/AIStudioChat.js.map +1 -1
  97. package/build/esm/components/pages/AIStudioChat/request.d.ts +4 -0
  98. package/build/esm/components/pages/AIStudioChat/request.js +8 -0
  99. package/build/esm/components/pages/AIStudioChat/request.js.map +1 -0
  100. package/build/esm/components/pages/AIStudioChat/types.d.ts +5 -5
  101. package/build/esm/components/pages/AIStudioChat/types.js.map +1 -1
  102. package/build/esm/components/pages/ChatContainer/ChatContainer.js +12 -6
  103. package/build/esm/components/pages/ChatContainer/ChatContainer.js.map +1 -1
  104. package/build/esm/components/pages/ChatContainer/types.d.ts +1 -1
  105. package/build/esm/components/pages/ChatContainer/types.js.map +1 -1
  106. package/build/esm/components/pages/ChatContainer/useChatContainer.d.ts +1 -0
  107. package/build/esm/components/pages/ChatContainer/useChatContainer.js +5 -1
  108. package/build/esm/components/pages/ChatContainer/useChatContainer.js.map +1 -1
  109. package/build/esm/package.json +1 -1
  110. package/build/esm/types/index.d.ts +1 -0
  111. package/build/esm/types/index.js +1 -0
  112. package/build/esm/types/index.js.map +1 -1
  113. package/build/esm/types/messages.d.ts +3 -0
  114. package/build/esm/types/messages.js.map +1 -1
  115. package/build/esm/types/promptCommands.d.ts +44 -0
  116. package/build/esm/types/promptCommands.js +2 -0
  117. package/build/esm/types/promptCommands.js.map +1 -0
  118. package/package.json +1 -1
@@ -1 +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: (_a = streamOptions === null || streamOptions === void 0 ? void 0 : streamOptions.initialMessages) !== null && _a !== void 0 ? _a : [],
118
- assistantMessageId: (_b = streamOptions === null || streamOptions === void 0 ? void 0 : streamOptions.assistantMessageId) !== null && _b !== void 0 ? _b : 'assistant-idle',
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 displayMessages = hasSource && streamResult.messages.length > 0 ? streamResult.messages : messages;
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
- return isFetching ? 'submitted' : 'ready';
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: (0, uuid_1.v4)(),
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
- setMessages(messagesWithUser);
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 response = await fetch(apiUrl, Object.assign(Object.assign({}, requestInit), { method: 'POST', headers: Object.assign({ 'Content-Type': 'application/json', Accept: 'text/event-stream' }, requestInit === null || requestInit === void 0 ? void 0 : requestInit.headers), body: JSON.stringify(Object.assign(Object.assign(Object.assign({ messages: apiMessages }, extraRequestParams), perSendParams), (responseIdRef.current
199
- ? { previousResponseId: responseIdRef.current }
200
- : {}))), signal: abortController.signal }));
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
- const errorMessage = {
210
- id: (0, uuid_1.v4)(),
211
- role: 'assistant',
212
- content: error.message,
213
- };
214
- setMessages((prev) => {
215
- const filtered = prev.filter((msg) => msg.role !== 'assistant' || getMessageTextContent(msg) !== '');
216
- return [...filtered, errorMessage];
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
- setIsFetching(false);
224
- setController(null);
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({ content: data.content });
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
- await performSend({
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
- }, [messages, onBeforeSend, performSend, prepareFilesForSend, reset]);
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: (_a = lastUserMsg.images) !== null && _a !== void 0 ? _a : [],
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: ((_d = (_c = chatContainerProps.promptInputProps) === null || _c === void 0 ? void 0 : _c.headerProps) === null || _d === void 0 ? void 0 : _d.topContent)
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: (_f = (_e = chatContainerProps.promptInputProps) === null || _e === void 0 ? void 0 : _e.headerProps) === null || _f === void 0 ? void 0 : _f.qa,
362
- showContextIndicator: (_h = (_g = chatContainerProps.promptInputProps) === null || _g === void 0 ? void 0 : _g.headerProps) === null || _h === void 0 ? void 0 : _h.showContextIndicator,
363
- contextIndicatorProps: (_k = (_j = chatContainerProps.promptInputProps) === null || _j === void 0 ? void 0 : _j.headerProps) === null || _k === void 0 ? void 0 : _k.contextIndicatorProps,
364
- contextItems: (_o = (_m = (_l = chatContainerProps.promptInputProps) === null || _l === void 0 ? void 0 : _l.headerProps) === null || _m === void 0 ? void 0 : _m.contextItems) !== null && _o !== void 0 ? _o : contextItems,
365
- }, footerProps: Object.assign(Object.assign({}, (_p = chatContainerProps.promptInputProps) === null || _p === void 0 ? void 0 : _p.footerProps), { attachmentContent: (_s = (_r = (_q = chatContainerProps.promptInputProps) === null || _q === void 0 ? void 0 : _q.footerProps) === null || _r === void 0 ? void 0 : _r.attachmentContent) !== null && _s !== void 0 ? _s : attachmentContent }) }) })));
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>;