@@ -23,6 +23,20 @@ import type {
2323
2424const STREAMING_LINE_BUFFER_LIMIT = 2000 ;
2525
26+ // ==================== 流式 chunks 模块级缓冲 ====================
27+ // 将 chunks 累积移出 Zustand store,避免每次 delta 都展开数组触发状态更新开销
28+ // 仅在 finalizeStreamingMessage 时读取
29+ let streamingChunksBuffer : string [ ] = [ ] ;
30+
31+ /**
32+ * 获取并清空流式 chunks 缓冲区(供 finalize 使用)
33+ */
34+ export function drainStreamingChunksBuffer ( ) : string [ ] {
35+ const chunks = streamingChunksBuffer ;
36+ streamingChunksBuffer = [ ] ;
37+ return chunks ;
38+ }
39+
2640/**
2741 * 初始 Token 使用量
2842 */
@@ -360,6 +374,8 @@ export const createSessionSlice: StateCreator<BladeStore, [], [], SessionSlice>
360374 content : '' , // 空内容,后续增量填充
361375 timestamp : Date . now ( ) ,
362376 } ;
377+ // 清空模块级 chunks 缓冲区
378+ streamingChunksBuffer = [ ] ;
363379 set ( ( state ) => ( {
364380 session : {
365381 ...state . session ,
@@ -390,11 +406,14 @@ export const createSessionSlice: StateCreator<BladeStore, [], [], SessionSlice>
390406 appendAssistantContent : ( delta : string ) => {
391407 const streamingId = get ( ) . session . currentStreamingMessageId ;
392408 const nextStreamingId = streamingId ?? `assistant-${ Date . now ( ) } -${ Math . random ( ) } ` ;
409+
410+ // chunks 累积在模块级缓冲区,不写入 store(减少数组展开开销)
411+ streamingChunksBuffer . push ( delta ) ;
412+
393413 set ( ( state ) => {
394414 const normalizeLine = ( line : string ) =>
395415 line . endsWith ( '\r' ) ? line . slice ( 0 , - 1 ) : line ;
396416
397- const currentChunks = streamingId ? state . session . currentStreamingChunks : [ ] ;
398417 const currentLines = streamingId ? state . session . currentStreamingLines : [ ] ;
399418 const currentTail = streamingId ? state . session . currentStreamingTail : '' ;
400419 const currentLineCount = streamingId
@@ -406,7 +425,6 @@ export const createSessionSlice: StateCreator<BladeStore, [], [], SessionSlice>
406425 const parts = combined . split ( '\n' ) ;
407426 const completedParts = parts . slice ( 0 , - 1 ) . map ( normalizeLine ) ;
408427 const nextTail = normalizeLine ( parts [ parts . length - 1 ] ?? '' ) ;
409- const nextChunks = [ ...currentChunks , delta ] ;
410428 let nextLines = currentLines ;
411429 if ( completedParts . length > 0 ) {
412430 nextLines = [ ...currentLines , ...completedParts ] ;
@@ -420,7 +438,6 @@ export const createSessionSlice: StateCreator<BladeStore, [], [], SessionSlice>
420438 session : {
421439 ...state . session ,
422440 currentStreamingMessageId : nextStreamingId ,
423- currentStreamingChunks : nextChunks ,
424441 currentStreamingLines : nextLines ,
425442 currentStreamingTail : nextTail ,
426443 currentStreamingLineCount : currentLineCount + completedParts . length ,
@@ -440,9 +457,11 @@ export const createSessionSlice: StateCreator<BladeStore, [], [], SessionSlice>
440457 * @param extraThinking 可选的额外 thinking 内容(缓冲区剩余)
441458 */
442459 finalizeStreamingMessage : ( extraContent ?: string , extraThinking ?: string ) => {
460+ // 从模块级缓冲区读取 chunks 并清空
461+ const chunks = drainStreamingChunksBuffer ( ) ;
443462 set ( ( state ) => {
444463 const streamingId = state . session . currentStreamingMessageId ;
445- const baseContent = state . session . currentStreamingChunks . join ( '' ) ;
464+ const baseContent = chunks . join ( '' ) ;
446465 const streamingContent = baseContent + ( extraContent || '' ) ;
447466 const thinkingContent =
448467 ( state . session . currentThinkingContent || '' ) + ( extraThinking || '' ) ;
0 commit comments