fix(client): address conversation assembly review findings

This commit is contained in:
imccyu
2026-08-09 17:02:20 +08:00
parent 522acc7432
commit 8723a0e15f
7 changed files with 128 additions and 20 deletions

View File

@@ -122,14 +122,26 @@ function tailData(context: ConversationNodeContext<TurnTailState>): TurnTailChat
.filter((candidate): candidate is Readonly<FinalAssistantChatData> => candidate.finalNode !== undefined)
.sort((left, right) => left.finalNode.seq - right.finalNode.seq)
const closing = finalized.findLast(hasText) ?? null
const latest = finalized.at(-1)
let latestTranscriptSeq = finalized.at(-1)?.finalNode.seq
for (const match of context.matches) {
const event = match.event
const candidate = event.type === 'tool/call'
|| (event.type === 'tool/result' && isAppendSurfaceEvent(event))
|| (event.type === 'turn/end' && event.data.reason.kind === 'error')
|| (event.type as string) === 'llm/retry'
? event.seq
: undefined
if (candidate !== undefined && (latestTranscriptSeq === undefined || candidate > latestTranscriptSeq)) {
latestTranscriptSeq = candidate
}
}
const metrics = deriveTurnMetrics(finalized.map(candidate => candidate.finalNode)).get(end.event.data.turn)
return {
turn: end.event.data.turn,
seq: end.event.seq,
time: end.event.time,
closing,
branchUnavailable: closing === null || latest?.finalNode.seq !== closing.finalNode.seq,
branchUnavailable: closing === null || latestTranscriptSeq !== closing.finalNode.seq,
...metrics?.ttftMs === undefined ? {} : { ttftMs: metrics.ttftMs },
...metrics?.tokensPerSecond === undefined ? {} : { tokensPerSecond: metrics.tokensPerSecond },
}
@@ -141,6 +153,9 @@ export const turnTailDefinition: ConversationNodeDefinition<TurnTailState> = {
match: (event) => {
if (event.type === 'turn/start') return { id: String(event.data.turn), role: 'start' }
if (event.type === 'turn/end') return { id: String(event.data.turn), role: 'update' }
if (event.type === 'tool/call' || event.type === 'tool/result') {
return { id: String(event.data.turn), role: 'update' }
}
const coordinates = turnCoordinates(event)
if (coordinates !== undefined) return { id: String(coordinates.turn), role: 'update' }
return null

View File

@@ -3,19 +3,18 @@
* between the independently implemented skeleton and chat domains; `apply.ts`
* owns their slot assembly.
*/
export type {} from './conversation-nodes/assistant.ts'
export type {} from './conversation-nodes/command.ts'
export type {} from './conversation-nodes/compaction.ts'
export type {} from './conversation-nodes/fallback.ts'
export type {} from './conversation-nodes/message.ts'
export type {} from './conversation-nodes/retry.ts'
export type {} from './conversation-nodes/tool.ts'
export type {} from './conversation-nodes/turn-error.ts'
export type {} from './conversation-nodes/turn-tail.ts'
export { apply, inject } from './apply.ts'
export { ConversationService } from './service.ts'
export { registerAssistantConversationNode } from './conversation-nodes/assistant.ts'
export { registerChatConversationView } from './conversation-nodes/chat-snapshot-builder.ts'
export { registerCommandConversationNode } from './conversation-nodes/command.ts'
export { registerCompactionConversationNode } from './conversation-nodes/compaction.ts'
export { registerUnknownConversationFallback } from './conversation-nodes/fallback.ts'
export { registerInboxConversationNodes } from './conversation-nodes/inbox.ts'
export { registerMessageConversationNode } from './conversation-nodes/message.ts'
export { registerRetryConversationNode } from './conversation-nodes/retry.ts'
export { registerToolConversationNode } from './conversation-nodes/tool.ts'
export { registerTurnErrorConversationNode } from './conversation-nodes/turn-error.ts'
export { registerTurnTailConversationNode } from './conversation-nodes/turn-tail.ts'
export type { IConversation } from './service.ts'
export type {