(props: {
api: ApiClient
sessionId: string
tool: ChatToolCall
disabled: boolean
onDone: () => void
})
| 84 | } |
| 85 | |
| 86 | export function AskUserQuestionFooter(props: { |
| 87 | api: ApiClient |
| 88 | sessionId: string |
| 89 | tool: ChatToolCall |
| 90 | disabled: boolean |
| 91 | onDone: () => void |
| 92 | }) { |
| 93 | const { t } = useTranslation() |
| 94 | const { haptic } = usePlatform() |
| 95 | const permission = props.tool.permission |
| 96 | const useStableQuestionIds = isCursorAskQuestionToolName(props.tool.name) |
| 97 | const parsed = useMemo(() => ( |
| 98 | useStableQuestionIds |
| 99 | ? parseCursorAskQuestionInput(props.tool.input) |
| 100 | : parseAskUserQuestionInput(props.tool.input) |
| 101 | ), [props.tool.name, props.tool.input, useStableQuestionIds]) |
| 102 | const questions = parsed.questions |
| 103 | |
| 104 | const [step, setStep] = useState(0) |
| 105 | const [selectedByQuestion, setSelectedByQuestion] = useState<number[][]>([]) |
| 106 | const [otherSelectedByQuestion, setOtherSelectedByQuestion] = useState<boolean[]>([]) |
| 107 | const [otherTextByQuestion, setOtherTextByQuestion] = useState<string[]>([]) |
| 108 | const [fallbackText, setFallbackText] = useState('') |
| 109 | |
| 110 | const [loading, setLoading] = useState(false) |
| 111 | const [error, setError] = useState<string | null>(null) |
| 112 | |
| 113 | useEffect(() => { |
| 114 | setStep(0) |
| 115 | setSelectedByQuestion(questions.map(() => [])) |
| 116 | setOtherSelectedByQuestion(questions.map(() => false)) |
| 117 | setOtherTextByQuestion(questions.map(() => '')) |
| 118 | setFallbackText('') |
| 119 | setLoading(false) |
| 120 | setError(null) |
| 121 | }, [props.tool.id]) |
| 122 | |
| 123 | if (!permission || permission.status !== 'pending') return null |
| 124 | if (!isAskUserQuestionToolName(props.tool.name)) return null |
| 125 | |
| 126 | const run = async (action: () => Promise<void>, hapticType: 'success' | 'error') => { |
| 127 | if (props.disabled) return |
| 128 | setError(null) |
| 129 | try { |
| 130 | await action() |
| 131 | haptic.notification(hapticType) |
| 132 | props.onDone() |
| 133 | } catch (e) { |
| 134 | haptic.notification('error') |
| 135 | setError(e instanceof Error ? e.message : t('dialog.error.default')) |
| 136 | } |
| 137 | } |
| 138 | |
| 139 | const total = Math.max(1, questions.length) |
| 140 | const clampedStep = Math.min(Math.max(step, 0), total - 1) |
| 141 | |
| 142 | const mode: AskUserQuestionChoiceMode = questions[clampedStep]?.multiSelect ? 'multi' : 'single' |
| 143 |
nothing calls this directly
no test coverage detected