diff --git a/packages/client/ui-tool/src/client/tool/toolviews/ask-question-row.tsx b/packages/client/ui-tool/src/client/tool/toolviews/ask-question-row.tsx index 272a1b4f22..44fca5b9e4 100644 --- a/packages/client/ui-tool/src/client/tool/toolviews/ask-question-row.tsx +++ b/packages/client/ui-tool/src/client/tool/toolviews/ask-question-row.tsx @@ -3,6 +3,7 @@ import type { Context } from '@deepseek-ai/cordis' import type { PropsLocale } from '@deepseek-ai/dsh-client-ui-slots' import type { ToolCallViewProps } from '../../contract/slots.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 { ToolRow } from '../components/ToolRow.tsx' 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') { summary = t('ask.waiting') } else if ('kind' in block && model.state === 'ok') { - const text = block.content.filter(b => b.type === 'text').map(b => b.text).join('') - const presentation = answeredPresentation(argsRaw, text, t) - // Full transcripts require stable ids and valid visible fields; retain the - // legacy best-effort count when only strict pairing is unsafe. - summary = presentation?.summary ?? answeredSummary(text, t) ?? model.summary - if (presentation?.questions !== null && presentation?.questions !== undefined) { - transcript = { kind: 'answered', questions: presentation.questions, skippedLabel: t('ask.skipped') } + const text = singleResultText(block) + if (text !== undefined) { + const presentation = answeredPresentation(argsRaw, text, t) + // Full transcripts require stable ids and valid visible fields; retain the + // legacy best-effort count when only strict pairing is unsafe. + summary = presentation?.summary ?? answeredSummary(text, t) ?? model.summary + if (presentation?.questions !== null && presentation?.questions !== undefined) { + transcript = { kind: 'answered', questions: presentation.questions, skippedLabel: t('ask.skipped') } + } } } return ( diff --git a/packages/client/ui-tool/tests/ask-question-row.client.spec.tsx b/packages/client/ui-tool/tests/ask-question-row.client.spec.tsx index c371d0bce2..22f1e0d5e4 100644 --- a/packages/client/ui-tool/tests/ask-question-row.client.spec.tsx +++ b/packages/client/ui-tool/tests/ask-question-row.client.spec.tsx @@ -84,6 +84,26 @@ describe('AskQuestionRow', () => { 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() + + 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', () => { const view = render(