Przeglądaj źródła

fix(web): preserve mixed ask-user results

Yichen Jiang 1 miesiąc temu
rodzic
commit
94d06e23d2

+ 10 - 7
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 (

+ 20 - 0
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(<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', () => {
     const view = render(<AskQuestionRow {...rowProps(resultNode(ARGS, answers([
       { id: 'a', selected: ['x'] },