fix(web): preserve mixed ask-user results

This commit is contained in:
Yichen Jiang
2026-08-27 15:11:55 +08:00
parent 49753b33fa
commit 94d06e23d2
2 changed files with 30 additions and 7 deletions
@@ -3,6 +3,7 @@ import type { Context } from '@deepseek-ai/cordis'
import type { PropsLocale } from '@deepseek-ai/dsh-client-ui-slots' import type { PropsLocale } from '@deepseek-ai/dsh-client-ui-slots'
import type { ToolCallViewProps } from '../../contract/slots.ts' import type { ToolCallViewProps } from '../../contract/slots.ts'
import type { AskQuestionCardModel } from '../models/ask-question-card-model.ts' import type { AskQuestionCardModel } from '../models/ask-question-card-model.ts'
import { singleResultText } from '../models/raw-tool-call.ts'
import { toolRowModel } from '../models/tool-call-model.ts' import { toolRowModel } from '../models/tool-call-model.ts'
import { ToolRow } from '../components/ToolRow.tsx' import { ToolRow } from '../components/ToolRow.tsx'
import { CONVERSATION_NS as NS } from '../../locale.ts' import { CONVERSATION_NS as NS } from '../../locale.ts'
@@ -166,13 +167,15 @@ export function AskQuestionRow({ toolName, block, inspect, t }: AskQuestionRowPr
} else if (model.state === 'running') { } else if (model.state === 'running') {
summary = t('ask.waiting') summary = t('ask.waiting')
} else if ('kind' in block && model.state === 'ok') { } else if ('kind' in block && model.state === 'ok') {
const text = block.content.filter(b => b.type === 'text').map(b => b.text).join('') const text = singleResultText(block)
const presentation = answeredPresentation(argsRaw, text, t) if (text !== undefined) {
// Full transcripts require stable ids and valid visible fields; retain the const presentation = answeredPresentation(argsRaw, text, t)
// legacy best-effort count when only strict pairing is unsafe. // Full transcripts require stable ids and valid visible fields; retain the
summary = presentation?.summary ?? answeredSummary(text, t) ?? model.summary // legacy best-effort count when only strict pairing is unsafe.
if (presentation?.questions !== null && presentation?.questions !== undefined) { summary = presentation?.summary ?? answeredSummary(text, t) ?? model.summary
transcript = { kind: 'answered', questions: presentation.questions, skippedLabel: t('ask.skipped') } if (presentation?.questions !== null && presentation?.questions !== undefined) {
transcript = { kind: 'answered', questions: presentation.questions, skippedLabel: t('ask.skipped') }
}
} }
} }
return ( return (
@@ -84,6 +84,26 @@ describe('AskQuestionRow', () => {
expect(screen.queryByText(/"answers"/)).toBeNull() expect(screen.queryByText(/"answers"/)).toBeNull()
}) })
it('keeps generic diagnostics when a valid answer result includes a non-text block', () => {
const resultText = answers([
{ id: 'goal', selected: ['Develop a feature'] },
{ id: 'scope', selected: ['deepseek-harness'] },
{ id: 'notes', selected: [] },
])
const view = render(<AskQuestionRow {...rowProps(resultNode(READABLE_ARGS, resultText, {
content: [
{ type: 'text', text: resultText },
{ type: 'reasoning', text: 'unexpected diagnostic' },
],
}))} />)
expect(screen.getByText(`ask_user_question · ${READABLE_ARGS}`)).toBeTruthy()
fireEvent.click(screen.getByRole('button', { expanded: false }))
expect(view.container.querySelector('[class*="ioCard"]')).not.toBeNull()
expect(view.container.textContent).toContain('"type": "reasoning"')
expect(view.container.textContent).toContain('"text": "unexpected diagnostic"')
})
it('skipped questions (no selection, no custom) stay out of the answered count', () => { it('skipped questions (no selection, no custom) stay out of the answered count', () => {
const view = render(<AskQuestionRow {...rowProps(resultNode(ARGS, answers([ const view = render(<AskQuestionRow {...rowProps(resultNode(ARGS, answers([
{ id: 'a', selected: ['x'] }, { id: 'a', selected: ['x'] },