@@ -25,6 +25,7 @@ export interface UseMessageOperationsReturn {
2525 customParentId ?: string
2626 ) => Promise < void >
2727 handleRetryMessage : ( messageId : string ) => Promise < void >
28+ handleContinueMessage : ( messageId : string ) => Promise < void >
2829 handleEditMessage : ( messageId : string , newContent : string ) => Promise < void >
2930 handleEditAndResendMessage : ( messageId : string , newContent : string ) => Promise < void >
3031 handleToggleFavorite : ( messageId : string ) => void
@@ -171,6 +172,56 @@ export function useMessageOperations({
171172 [ chat , isLoading , aiService , chatId , messageTree , setIsLoading ]
172173 )
173174
175+ const handleContinueMessage = useCallback (
176+ async ( messageId : string ) => {
177+ if ( ! chat || isLoading ) return
178+
179+ // 找到要继续的用户消息
180+ const targetMessage = chat . messages . find ( ( msg : any ) => msg . id === messageId )
181+ if ( ! targetMessage || targetMessage . role !== 'user' ) return
182+
183+ // 使用当前选中的模型
184+ const llmConfig = aiService . getLLMConfig ( selectedModel )
185+ if ( ! llmConfig ) {
186+ message . error ( '请先在设置中配置LLM' )
187+ return
188+ }
189+
190+ setIsLoading ( true )
191+
192+ try {
193+ // 获取当前路径上的消息历史,包含到该用户消息为止的所有消息
194+ const currentPath = chat . currentPath || messageTree . getCurrentPath ( )
195+ const currentPathMessages = currentPath
196+ . map ( ( id : string ) => chat . messages . find ( ( msg : any ) => msg . id === id ) )
197+ . filter ( Boolean ) as ChatMessage [ ]
198+
199+ // 构建到目标消息为止的消息历史
200+ let messagesToSend : ChatMessage [ ] = [ ]
201+ const targetIndex = currentPathMessages . findIndex ( ( msg ) => msg . id === messageId )
202+ if ( targetIndex >= 0 ) {
203+ messagesToSend = currentPathMessages . slice ( 0 , targetIndex + 1 )
204+ } else {
205+ // 如果在当前路径中找不到,直接从所有消息中构建路径
206+ messagesToSend = [ targetMessage ]
207+ }
208+
209+ // 从该用户消息继续生成AI回复
210+ await aiService . sendAIMessage ( messagesToSend , llmConfig , messageId , 'chat' , {
211+ continue : {
212+ fromMessageId : messageId
213+ }
214+ } )
215+ } catch ( error ) {
216+ console . error ( 'Continue message failed:' , error )
217+ message . error ( '继续对话失败,请检查网络连接和配置:' + error )
218+ } finally {
219+ setIsLoading ( false )
220+ }
221+ } ,
222+ [ chat , isLoading , aiService , chatId , messageTree , setIsLoading , selectedModel ]
223+ )
224+
174225 const handleEditMessage = useCallback (
175226 async ( messageId : string , newContent : string ) => {
176227 if ( ! chat ) return
@@ -193,6 +244,9 @@ export function useMessageOperations({
193244 const targetMessage = chat . messages . find ( ( msg : any ) => msg . id === messageId )
194245 if ( ! targetMessage ) return
195246
247+ // 判断当前消息是否有后继消息(子消息)
248+ const hasChildren = chat . messages . some ( ( msg : any ) => msg . parentId === messageId )
249+
196250 // 如果是用户消息,使用当前选中的模型;如果是AI消息,使用原消息的模型
197251 const modelIdToUse = targetMessage . role === 'user' ? selectedModel : targetMessage . modelId
198252 const llmConfig = aiService . getLLMConfig ( modelIdToUse )
@@ -205,81 +259,120 @@ export function useMessageOperations({
205259
206260 try {
207261 if ( targetMessage . role === 'user' ) {
208- // 对于用户消息,创建一个新的编辑版本作为兄弟分支
209- const editedUserMessage = {
210- id : uuidv4 ( ) ,
211- role : 'user' as const ,
212- content : newContent . trim ( ) ,
213- timestamp : Date . now ( ) ,
214- parentId : targetMessage . parentId || null
215- }
216-
217- // 添加编辑后的用户消息
218- addMessageToParent ( chatId , editedUserMessage , targetMessage . parentId )
219-
220- // 获取到编辑消息父节点为止的消息历史
221- const currentPath = chat . currentPath || messageTree . getCurrentPath ( )
222- const currentPathMessages = currentPath
223- . map ( ( id : string ) => chat . messages . find ( ( msg : any ) => msg . id === id ) )
224- . filter ( Boolean ) as ChatMessage [ ]
225-
226- let messagesToSend : ChatMessage [ ] = [ ]
227- if ( targetMessage . parentId ) {
228- const parentIndex = currentPathMessages . findIndex (
229- ( msg ) => msg . id === targetMessage . parentId
262+ if ( ! hasChildren ) {
263+ // 没有后继消息时,直接编辑原消息内容,然后追加AI回复
264+ const { updatePage } = usePagesStore . getState ( )
265+ const updatedMessages = chat . messages . map ( ( msg : any ) =>
266+ msg . id === messageId ? { ...msg , content : newContent . trim ( ) , timestamp : Date . now ( ) } : msg
267+ )
268+ updatePage ( chatId , { messages : updatedMessages } )
269+
270+ // 获取当前路径上的消息历史
271+ const currentPath = chat . currentPath || messageTree . getCurrentPath ( )
272+ const currentPathMessages = currentPath
273+ . map ( ( id : string ) => updatedMessages . find ( ( msg : any ) => msg . id === id ) )
274+ . filter ( Boolean ) as ChatMessage [ ]
275+
276+ // 直接追加AI回复,就像正常发送消息一样
277+ await aiService . sendAIMessage (
278+ currentPathMessages ,
279+ llmConfig ,
280+ messageId ,
281+ 'edit_resend' ,
282+ {
283+ editResend : {
284+ originalMessageId : messageId ,
285+ newContent : newContent ,
286+ isDirectAppend : true
287+ }
288+ }
230289 )
231- if ( parentIndex >= 0 ) {
232- messagesToSend = [ ...currentPathMessages . slice ( 0 , parentIndex + 1 ) , editedUserMessage ]
290+ } else {
291+ // 有后继消息时,创建兄弟分支
292+ const editedUserMessage = {
293+ id : uuidv4 ( ) ,
294+ role : 'user' as const ,
295+ content : newContent . trim ( ) ,
296+ timestamp : Date . now ( ) ,
297+ parentId : targetMessage . parentId || null
298+ }
299+
300+ // 添加编辑后的用户消息
301+ addMessageToParent ( chatId , editedUserMessage , targetMessage . parentId )
302+
303+ // 获取到编辑消息父节点为止的消息历史
304+ const currentPath = chat . currentPath || messageTree . getCurrentPath ( )
305+ const currentPathMessages = currentPath
306+ . map ( ( id : string ) => chat . messages . find ( ( msg : any ) => msg . id === id ) )
307+ . filter ( Boolean ) as ChatMessage [ ]
308+
309+ let messagesToSend : ChatMessage [ ] = [ ]
310+ if ( targetMessage . parentId ) {
311+ const parentIndex = currentPathMessages . findIndex (
312+ ( msg ) => msg . id === targetMessage . parentId
313+ )
314+ if ( parentIndex >= 0 ) {
315+ messagesToSend = [ ...currentPathMessages . slice ( 0 , parentIndex + 1 ) , editedUserMessage ]
316+ } else {
317+ messagesToSend = [ editedUserMessage ]
318+ }
233319 } else {
234320 messagesToSend = [ editedUserMessage ]
235321 }
236- } else {
237- messagesToSend = [ editedUserMessage ]
238- }
239322
240- // 生成新的AI回复
241- await aiService . sendAIMessage (
242- messagesToSend ,
243- llmConfig ,
244- editedUserMessage . id ,
245- 'edit_resend' ,
246- {
247- editResend : {
248- originalMessageId : messageId ,
249- newContent : newContent
323+ // 生成新的AI回复
324+ await aiService . sendAIMessage (
325+ messagesToSend ,
326+ llmConfig ,
327+ editedUserMessage . id ,
328+ 'edit_resend' ,
329+ {
330+ editResend : {
331+ originalMessageId : messageId ,
332+ newContent : newContent
333+ }
250334 }
251- }
252- )
335+ )
336+ }
253337 } else {
254- // 对于AI消息,从其父消息重新生成
255- const currentPath = chat . currentPath || messageTree . getCurrentPath ( )
256- const currentPathMessages = currentPath
257- . map ( ( id : string ) => chat . messages . find ( ( msg : any ) => msg . id === id ) )
258- . filter ( Boolean ) as ChatMessage [ ]
259-
260- let messagesToSend : ChatMessage [ ] = [ ]
261- if ( targetMessage . parentId ) {
262- const parentIndex = currentPathMessages . findIndex (
263- ( msg ) => msg . id === targetMessage . parentId
338+ if ( ! hasChildren ) {
339+ // AI消息没有后继消息时,只需要直接编辑内容,不需要重新生成
340+ const { updatePage } = usePagesStore . getState ( )
341+ const updatedMessages = chat . messages . map ( ( msg : any ) =>
342+ msg . id === messageId ? { ...msg , content : newContent . trim ( ) , timestamp : Date . now ( ) } : msg
264343 )
265- if ( parentIndex >= 0 ) {
266- messagesToSend = currentPathMessages . slice ( 0 , parentIndex + 1 )
344+ updatePage ( chatId , { messages : updatedMessages } )
345+ } else {
346+ // 有后继消息时,从父消息重新生成作为兄弟分支
347+ const currentPath = chat . currentPath || messageTree . getCurrentPath ( )
348+ const currentPathMessages = currentPath
349+ . map ( ( id : string ) => chat . messages . find ( ( msg : any ) => msg . id === id ) )
350+ . filter ( Boolean ) as ChatMessage [ ]
351+
352+ let messagesToSend : ChatMessage [ ] = [ ]
353+ if ( targetMessage . parentId ) {
354+ const parentIndex = currentPathMessages . findIndex (
355+ ( msg ) => msg . id === targetMessage . parentId
356+ )
357+ if ( parentIndex >= 0 ) {
358+ messagesToSend = currentPathMessages . slice ( 0 , parentIndex + 1 )
359+ }
267360 }
268- }
269361
270- // 生成新的AI回复作为兄弟分支
271- await aiService . sendAIMessage (
272- messagesToSend ,
273- llmConfig ,
274- targetMessage . parentId ,
275- 'edit_resend' ,
276- {
277- editResend : {
278- originalMessageId : messageId ,
279- newContent : newContent
362+ // 生成新的AI回复作为兄弟分支
363+ await aiService . sendAIMessage (
364+ messagesToSend ,
365+ llmConfig ,
366+ targetMessage . parentId ,
367+ 'edit_resend' ,
368+ {
369+ editResend : {
370+ originalMessageId : messageId ,
371+ newContent : newContent
372+ }
280373 }
281- }
282- )
374+ )
375+ }
283376 }
284377 } catch ( error ) {
285378 console . error ( 'Edit and resend failed:' , error )
@@ -421,6 +514,7 @@ export function useMessageOperations({
421514 return {
422515 handleSendMessage,
423516 handleRetryMessage,
517+ handleContinueMessage,
424518 handleEditMessage,
425519 handleEditAndResendMessage,
426520 handleToggleFavorite,
0 commit comments