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:
weishu
2025-12-18 23:24:41 +08:00
parent 7042596c90
commit ac67718ec0
16 changed files with 758 additions and 32 deletions
+6 -3
View File
@@ -48,7 +48,8 @@ export const AgentStateSchema = z.object({
reason: z.string().optional(),
mode: z.string().optional(),
decision: z.enum(['approved', 'approved_for_session', 'denied', 'abort']).optional(),
allowTools: z.array(z.string()).optional()
allowTools: z.array(z.string()).optional(),
answers: z.record(z.string(), z.array(z.string())).optional()
}).passthrough()).nullish()
}).passthrough()
@@ -591,14 +592,16 @@ export class SyncEngine {
requestId: string,
mode?: 'default' | 'acceptEdits' | 'bypassPermissions' | 'plan',
allowTools?: string[],
decision?: 'approved' | 'approved_for_session' | 'denied' | 'abort'
decision?: 'approved' | 'approved_for_session' | 'denied' | 'abort',
answers?: Record<string, string[]>
): Promise<void> {
await this.sessionRpc(sessionId, 'permission', {
id: requestId,
approved: true,
mode,
allowTools,
decision
decision,
answers
})
}
+4 -2
View File
@@ -9,7 +9,8 @@ const decisionSchema = z.enum(['approved', 'approved_for_session', 'denied', 'ab
const approveBodySchema = z.object({
mode: z.enum(['default', 'acceptEdits', 'bypassPermissions', 'plan']).optional(),
allowTools: z.array(z.string()).optional(),
decision: decisionSchema.optional()
decision: decisionSchema.optional(),
answers: z.record(z.string(), z.array(z.string())).optional()
})
const denyBodySchema = z.object({
@@ -47,7 +48,8 @@ export function createPermissionsRoutes(getSyncEngine: () => SyncEngine | null):
const mode = parsed.data.mode
const allowTools = parsed.data.allowTools
const decision = parsed.data.decision
await engine.approvePermission(sessionId, requestId, mode, allowTools, decision)
const answers = parsed.data.answers
await engine.approvePermission(sessionId, requestId, mode, allowTools, decision, answers)
return c.json({ ok: true })
})