@@ -113,7 +113,9 @@ const props = defineProps({
113113 type: Function
114114 },
115115 status: { type: String },
116- chatMode: { type: String },
116+ messageContentResolver: {
117+ type: Function
118+ },
117119 allowFiles: {
118120 type: Boolean ,
119121 default: false
@@ -169,51 +171,35 @@ const contentRendererMatches = computed<BubbleContentRendererMatch[]>(() => [
169171 },
170172 {
171173 priority: BubbleRendererMatchPriority .NORMAL ,
172- find : (message : any , content : any ) =>
173- ! message .loading && message .content && (! content ?.type || [' markdown' , ' text' ].includes (content .type )),
174+ find : (_message : any , content : any ) => ! content ?.type || [' markdown' , ' text' ].includes (content .type ),
174175 renderer: MarkdownRenderer
175176 },
176177 {
177178 priority: BubbleRendererMatchPriority .NORMAL ,
178- find : (message : any ) => message ?. content ?.[ 0 ]?. type === ' img' || message ?. content ?.[ 0 ]?. type === ' image ' ,
179+ find : (_message : any , content : any ) => [ ' img' , ' image ' ]. includes ( content ?.type ) ,
179180 renderer: ImgRenderer
180181 }
181182])
182183
183- const isAgentMessage = (message : any ) => {
184- const hasAgentContent = message .renderContent ?.some ((item : any ) => {
185- return item .type === ' agent-content' || item .type === ' agent-loading'
186- })
187- return message .metadata ?.chatMode === ' agent' || hasAgentContent
188- }
189-
190- const resolveAgentRenderContent = (message : any ) => {
191- if (! isAgentMessage (message ) || message .role !== ' assistant' ) {
192- return message .renderContent
184+ const getTextContent = (content : any ) => {
185+ if (typeof content === ' string' ) {
186+ return content
193187 }
194-
195- const isLastMessage = messages .value .at (- 1 ) === message
196- const isGenerating = Boolean (message .loading ) || (isLastMessage && GeneratingStatus .includes (props .status as any ))
197- const renderContent = isGenerating
198- ? message .renderContent
199- : message .renderContent .filter ((item : any ) => item .type !== ' agent-loading' )
200- const agentContents = renderContent .filter ((item : any ) => item .type === ' agent-content' )
201- const finalStatus = agentContents .findLast ((item : any ) => [' success' , ' failed' , ' fix' ].includes (item .status ))?.status
202-
203- return renderContent .map ((item : any ) => {
204- if (item .type !== ' agent-content' || isGenerating ) {
205- return item
206- }
207-
208- if (! item .status || item .status === ' loading' ) {
209- return {
210- ... item ,
211- status: finalStatus || message .metadata ?.agentStatus || ' failed'
212- }
213- }
214-
215- return item
216- })
188+ if (Array .isArray (content )) {
189+ return content
190+ .map ((item ) => {
191+ if (typeof item === ' string' ) {
192+ return item
193+ }
194+ if (item ?.type === ' text' ) {
195+ return item .text ?? item .content ?? ' '
196+ }
197+ return ' '
198+ })
199+ .filter (Boolean )
200+ .join (' \n ' )
201+ }
202+ return ' '
217203}
218204
219205// 处理文件选择事件
@@ -272,21 +258,43 @@ const aiAvatar = getSvgIcon('AI')
272258const welcomeIcon = getSvgIcon (' AI' , { fontSize: ' 44px' })
273259
274260const resolveMessageContent = (message : any ) => {
275- if (Array .isArray (message .renderContent ) && message .renderContent .length > 0 ) {
276- return resolveAgentRenderContent (message )
261+ if (props .messageContentResolver ) {
262+ return props .messageContentResolver (message , {
263+ messages: messages .value ,
264+ status: props .status
265+ })
277266 }
278267
279- if (isAgentMessage (message ) && message .role === ' assistant' && message .content ) {
280- const agentStatus = [' success' , ' failed' , ' fix' ].includes (message .metadata ?.agentStatus )
281- ? message .metadata .agentStatus
282- : ' failed'
283- return [
284- {
285- type: ' agent-content' ,
286- status: agentStatus ,
287- content: message .content
268+ if (Array .isArray (message .renderContent ) && message .renderContent .length > 0 ) {
269+ return message .renderContent .map ((item : any ) => {
270+ if (item ?.type === ' img' || item ?.type === ' image' ) {
271+ return {
272+ type: ' img' ,
273+ content: item .content || item .url || item .image_url ?.url || ' '
274+ }
288275 }
289- ]
276+ if (item ?.type === ' text' ) {
277+ return {
278+ type: ' text' ,
279+ content: item .content ?? item .text ?? ' '
280+ }
281+ }
282+ return item
283+ })
284+ }
285+
286+ if (Array .isArray (message .content ) && message .content .length > 0 ) {
287+ const textContent = getTextContent (
288+ message .content .map ((item : any ) => item ?.text ?? item ?.content ?? item ?.image_url ?.url ?? ' ' )
289+ )
290+ if (textContent ) {
291+ return textContent
292+ }
293+ }
294+
295+ const textContent = getTextContent (message .content )
296+ if (textContent ) {
297+ return textContent
290298 }
291299
292300 return message .content
@@ -326,28 +334,29 @@ const handleSendMessage = async (content: string) => {
326334 }
327335 const files = selectedAttachments .value .filter ((item ) => item .status === ' success' )
328336 if (files .length > 0 ) {
329- const fileMessages: ChatMessage [] = files .map ((file ) => ({
330- role: ' user' ,
331- content: ' ' ,
332- renderContent: [
333- {
334- type: ' img' ,
335- content: file .url
336- }
337- ]
338- }))
339- messages .value .push (... fileMessages )
340- userMessage .content = files
341- .map ((item ) => ({
337+ userMessage .content = [
338+ {
339+ type: ' text' ,
340+ text: messageContent
341+ },
342+ ... files .map ((item ) => ({
342343 type: ' image_url' ,
343344 image_url: {
344345 url: item .url
345346 }
346347 }))
347- .concat ({
348+ ] as any
349+ userMessage .renderContent = [
350+ {
348351 type: ' text' ,
349- text: messageContent
350- })
352+ content: messageContent
353+ },
354+ ... files .map ((item ) => ({
355+ type: ' img' ,
356+ content: item .url
357+ }))
358+ ]
359+ } else {
351360 userMessage .renderContent = [
352361 {
353362 type: ' text' ,
0 commit comments