mirror of
https://github.com/wu736139669/hapi.git
synced 2026-11-01 23:41:40 +00:00
feat: implement AskUserQuestion tool with interactive UI and question flow
Add comprehensive support for the AskUserQuestion tool including: - New footer component for handling user responses with multi-step question flow - Type definitions and parsing utilities for question and answer formats - View component for displaying questions and options - Integration with permission system to capture user answers - Support for single and multi-select questions with optional text input - Haptic feedback and error handling for better UX
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
export type AskUserQuestionOption = {
|
||||
label: string
|
||||
description: string | null
|
||||
}
|
||||
|
||||
export type AskUserQuestionQuestion = {
|
||||
header: string | null
|
||||
question: string
|
||||
options: AskUserQuestionOption[]
|
||||
multiSelect: boolean
|
||||
}
|
||||
|
||||
export type AskUserQuestionQuestionInfo = {
|
||||
header: string | null
|
||||
question: string | null
|
||||
}
|
||||
|
||||
function isObject(value: unknown): value is Record<string, unknown> {
|
||||
return Boolean(value) && typeof value === 'object'
|
||||
}
|
||||
|
||||
export function isAskUserQuestionToolName(toolName: string): boolean {
|
||||
return toolName === 'AskUserQuestion' || toolName === 'ask_user_question'
|
||||
}
|
||||
|
||||
export function parseAskUserQuestionInput(input: unknown): { questions: AskUserQuestionQuestion[] } {
|
||||
if (!isObject(input)) return { questions: [] }
|
||||
|
||||
const rawQuestions = input.questions
|
||||
if (!Array.isArray(rawQuestions)) return { questions: [] }
|
||||
|
||||
const questions: AskUserQuestionQuestion[] = []
|
||||
for (const raw of rawQuestions) {
|
||||
if (!isObject(raw)) continue
|
||||
|
||||
const question = typeof raw.question === 'string' ? raw.question.trim() : ''
|
||||
const header = typeof raw.header === 'string' ? raw.header.trim() : ''
|
||||
const multiSelect = typeof raw.multiSelect === 'boolean' ? raw.multiSelect : false
|
||||
|
||||
const rawOptions = Array.isArray(raw.options) ? raw.options : []
|
||||
const options: AskUserQuestionOption[] = []
|
||||
for (const opt of rawOptions) {
|
||||
if (!isObject(opt)) continue
|
||||
const label = typeof opt.label === 'string' ? opt.label.trim() : ''
|
||||
if (!label) continue
|
||||
const description = typeof opt.description === 'string' ? opt.description.trim() : null
|
||||
options.push({ label, description })
|
||||
}
|
||||
|
||||
if (!question && options.length === 0) continue
|
||||
|
||||
questions.push({
|
||||
header: header.length > 0 ? header : null,
|
||||
question,
|
||||
options,
|
||||
multiSelect
|
||||
})
|
||||
}
|
||||
|
||||
return { questions }
|
||||
}
|
||||
|
||||
export function extractAskUserQuestionQuestionsInfo(input: unknown): AskUserQuestionQuestionInfo[] | null {
|
||||
if (!isObject(input)) return null
|
||||
const raw = input.questions
|
||||
if (!Array.isArray(raw)) return null
|
||||
|
||||
const questions: AskUserQuestionQuestionInfo[] = []
|
||||
for (const q of raw) {
|
||||
if (!isObject(q)) continue
|
||||
const header = typeof q.header === 'string' ? q.header.trim() : null
|
||||
const question = typeof q.question === 'string' ? q.question.trim() : null
|
||||
questions.push({
|
||||
header: header && header.length > 0 ? header : null,
|
||||
question: question && question.length > 0 ? question : null
|
||||
})
|
||||
}
|
||||
return questions
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user