feat: Embedded chat window supports userVariables configuration. (#20983)

This commit is contained in:
croatialu 2025-06-18 14:27:02 +08:00 • committed by GitHub
commit 15800c6108
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 58 additions and 6 deletions

View file

@ -50,6 +50,10 @@ const OPTION_MAP = {
// user_id: 'YOU CAN DEFINE USER ID HERE',
// conversation_id: 'YOU CAN DEFINE CONVERSATION ID HERE, IT MUST BE A VALID UUID',
},
userVariables: {
// avatar_url: 'YOU CAN DEFINE USER AVATAR URL HERE',
// name: 'YOU CAN DEFINE USER NAME HERE',
},
}
</script>
<script

View file

@ -25,6 +25,7 @@ import SuggestedQuestions from '@/app/components/base/chat/chat/answer/suggested
import { Markdown } from '@/app/components/base/markdown'
import cn from '@/utils/classnames'
import type { FileEntity } from '../../file-uploader/types'
import Avatar from '../../avatar'
const ChatWrapper = () => {
const {
@ -49,6 +50,7 @@ const ChatWrapper = () => {
setClearChatList,
setIsResponding,
allInputsHidden,
initUserVariables,
} = useEmbeddedChatbotContext()
const appConfig = useMemo(() => {
const config = appParams || {}
@ -261,6 +263,14 @@ const ChatWrapper = () => {
switchSibling={siblingMessageId => setTargetMessageId(siblingMessageId)}
inputDisabled={inputDisabled}
isMobile={isMobile}
questionIcon={
initUserVariables?.avatar_url
? <Avatar
avatar={initUserVariables.avatar_url}
name={initUserVariables.name || 'user'}
size={40}
/> : undefined
}
/>
)
}

View file

@ -52,6 +52,10 @@ export type EmbeddedChatbotContextValue = {
currentConversationInputs: Record<string, any> | null,
setCurrentConversationInputs: (v: Record<string, any>) => void,
allInputsHidden: boolean
initUserVariables?: {
name?: string
avatar_url?: string
}
}
export const EmbeddedChatbotContext = createContext<EmbeddedChatbotContextValue>({
@ -81,5 +85,6 @@ export const EmbeddedChatbotContext = createContext<EmbeddedChatbotContextValue>
currentConversationInputs: {},
setCurrentConversationInputs: noop,
allInputsHidden: false,
initUserVariables: {},
})
export const useEmbeddedChatbotContext = () => useContext(EmbeddedChatbotContext)

View file

@ -15,7 +15,7 @@ import type {
Feedback,
} from '../types'
import { CONVERSATION_ID_INFO } from '../constants'
import { buildChatItemTree, getProcessedInputsFromUrlParams, getProcessedSystemVariablesFromUrlParams } from '../utils'
import { buildChatItemTree, getProcessedInputsFromUrlParams, getProcessedSystemVariablesFromUrlParams, getProcessedUserVariablesFromUrlParams } from '../utils'
import { getProcessedFilesFromResponse } from '../../file-uploader/utils'
import {
fetchAppInfo,
@ -169,6 +169,7 @@ export const useEmbeddedChatbot = () => {
const newConversationInputsRef = useRef<Record<string, any>>({})
const [newConversationInputs, setNewConversationInputs] = useState<Record<string, any>>({})
const [initInputs, setInitInputs] = useState<Record<string, any>>({})
const [initUserVariables, setInitUserVariables] = useState<Record<string, any>>({})
const handleNewConversationInputsChange = useCallback((newInputs: Record<string, any>) => {
newConversationInputsRef.current = newInputs
setNewConversationInputs(newInputs)
@ -237,7 +238,9 @@ export const useEmbeddedChatbot = () => {
// init inputs from url params
(async () => {
const inputs = await getProcessedInputsFromUrlParams()
const userVariables = await getProcessedUserVariablesFromUrlParams()
setInitInputs(inputs)
setInitUserVariables(userVariables)
})()
}, [])
useEffect(() => {
@ -418,5 +421,6 @@ export const useEmbeddedChatbot = () => {
currentConversationInputs,
setCurrentConversationInputs,
allInputsHidden,
initUserVariables,
}
}

View file

@ -195,6 +195,7 @@ const EmbeddedChatbotWrapper = () => {
currentConversationInputs,
setCurrentConversationInputs,
allInputsHidden,
initUserVariables,
} = useEmbeddedChatbot()
return <EmbeddedChatbotContext.Provider value={{
@ -233,6 +234,7 @@ const EmbeddedChatbotWrapper = () => {
currentConversationInputs,
setCurrentConversationInputs,
allInputsHidden,
initUserVariables,
}}>
<Chatbot />
</EmbeddedChatbotContext.Provider>

View file

@ -32,7 +32,8 @@ async function getProcessedInputsFromUrlParams(): Promise<Record<string, any>> {
const entriesArray = Array.from(urlParams.entries())
await Promise.all(
entriesArray.map(async ([key, value]) => {
if (!key.startsWith('sys.'))
const prefixArray = ['sys.', 'user.']
if (!prefixArray.some(prefix => key.startsWith(prefix)))
inputs[key] = await decodeBase64AndDecompress(decodeURIComponent(value))
}),
)
@ -52,6 +53,19 @@ async function getProcessedSystemVariablesFromUrlParams(): Promise<Record<string
return systemVariables
}
async function getProcessedUserVariablesFromUrlParams(): Promise<Record<string, any>> {
const urlParams = new URLSearchParams(window.location.search)
const userVariables: Record<string, any> = {}
const entriesArray = Array.from(urlParams.entries())
await Promise.all(
entriesArray.map(async ([key, value]) => {
if (key.startsWith('user.'))
userVariables[key.slice(5)] = await decodeBase64AndDecompress(decodeURIComponent(value))
}),
)
return userVariables
}
function isValidGeneratedAnswer(item?: ChatItem | ChatItemInTree): boolean {
return !!item && item.isAnswer && !item.id.startsWith('answer-placeholder-') && !item.isOpeningStatement
}
@ -198,6 +212,7 @@ export {
getRawInputsFromUrlParams,
getProcessedInputsFromUrlParams,
getProcessedSystemVariablesFromUrlParams,
getProcessedUserVariablesFromUrlParams,
isValidGeneratedAnswer,
getLastAnswer,
buildChatItemTree,