cc-haha/adapters/dingtalk/stream-state.ts
程序员阿江(Relakkes) 54c975bc09 fix: preserve DingTalk permission reply order
DingTalk keeps AI card placement tied to the original card delivery time, so a card created before a permission request can later be updated with the final answer above the permission card. Finish and drop the active stream when permission interrupts a turn so authorized output creates a new card below the prompt.

Constraint: DingTalk does not reorder an existing delivered AI card when its streaming content is updated
Rejected: Reuse the pre-permission AI card after approval | final answers can remain visually above the permission request
Confidence: high
Scope-risk: narrow
Directive: Keep permission_request as a lifecycle boundary for DingTalk AI card streams
Tested: cd adapters && bun test dingtalk/__tests__/stream-state.test.ts dingtalk/__tests__/ai-card.test.ts
Tested: cd adapters && bunx tsc --noEmit
Tested: bun run check:adapters
Tested: git diff --check
Not-tested: Live DingTalk account end-to-end permission approval
2026-05-05 21:49:39 +08:00

27 lines
819 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>
}
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()
resetDingTalkStreamingState(state, chatId)
}