cc-haha/adapters/dingtalk/stream-state.ts
程序员阿江(Relakkes) 09d2c4f4db Fix IM stream completion when card text already flushed
DingTalk AI cards can receive all intermediate text before the final
message_complete event. In that case the message buffer is empty, but
the platform card still needs an explicit terminal update to leave the
inputing state.

Constraint: DingTalk AI cards expose completion separately from buffered text delivery
Rejected: Rely on MessageBuffer.complete only | an empty buffer cannot finalize an active card
Confidence: high
Scope-risk: narrow
Directive: Keep IM terminal-state updates independent from whether a text buffer has pending content
Tested: bun test adapters/common/__tests__/message-buffer.test.ts adapters/dingtalk/__tests__/stream-state.test.ts adapters/dingtalk/__tests__/ai-card.test.ts
Tested: bunx tsc -p adapters/tsconfig.json --noEmit
Tested: bun run check:adapters
Tested: cd desktop && bun run build
Tested: bun run check:native
Not-tested: bun run check:coverage is blocked by existing desktop pages.test.tsx sidebar expectation unrelated to IM
2026-05-15 20:04:23 +08:00

31 lines
984 B
TypeScript

import type { MessageBuffer } from '../common/message-buffer.js'
import type { DingTalkAiCardInstance } from './ai-card.js'
export type DingTalkStreamingState = {
aiCardBuffers: Map<string, MessageBuffer>
streamingCards: Map<string, Promise<DingTalkAiCardInstance | null>>
streamingCardText: Map<string, string>
finalize?: () => Promise<void>
}
export function resetDingTalkStreamingState(
state: DingTalkStreamingState,
chatId: string,
): void {
state.aiCardBuffers.get(chatId)?.reset()
state.aiCardBuffers.delete(chatId)
state.streamingCards.delete(chatId)
state.streamingCardText.delete(chatId)
}
export async function finishAndResetDingTalkStreamingState(
state: DingTalkStreamingState,
chatId: string,
): Promise<void> {
await state.aiCardBuffers.get(chatId)?.complete()
if (state.finalize && (state.streamingCards.has(chatId) || state.streamingCardText.has(chatId))) {
await state.finalize()
}
resetDingTalkStreamingState(state, chatId)
}