import React, { useState } from 'react'; import { Button } from './ui/button'; import { Checkbox } from './ui/checkbox'; import { AlertTriangle, Wrench } from 'lucide-react'; import type { ApprovalEvent } from './ToolConfirmationHandler'; import type { JSONSchema7 } from 'json-schema'; import { ApprovalType } from '@dexto/core'; interface InlineApprovalCardProps { approval: ApprovalEvent; onApprove: (formData?: Record, rememberChoice?: boolean) => void; onDeny: () => void; } export function InlineApprovalCard({ approval, onApprove, onDeny }: InlineApprovalCardProps) { const [formData, setFormData] = useState>({}); const [formErrors, setFormErrors] = useState>({}); const [rememberChoice, setRememberChoice] = useState(false); // Update form field value const updateFormField = (fieldName: string, value: unknown) => { setFormData((prev) => ({ ...prev, [fieldName]: value })); if (formErrors[fieldName]) { setFormErrors((prev) => { const newErrors = { ...prev }; delete newErrors[fieldName]; return newErrors; }); } }; // Render form field based on JSON Schema field type const renderFormField = (fieldName: string, fieldSchema: JSONSchema7, isRequired: boolean) => { const fieldType = fieldSchema.type || 'string'; const fieldValue = formData[fieldName]; const hasError = !!formErrors[fieldName]; // Use title if available, fallback to fieldName const label = fieldSchema.title || fieldName; if (fieldType === 'boolean') { return (
updateFormField(fieldName, checked === true) } />
{fieldSchema.description && (

{fieldSchema.description}

)}
); } if (fieldType === 'number' || fieldType === 'integer') { return (
{fieldSchema.description && (

{fieldSchema.description}

)} { const raw = e.target.value; const nextValue = raw === '' ? undefined : Number(raw); updateFormField(fieldName, nextValue); }} className={`w-full px-3 py-2 border rounded-md text-sm bg-background ${ hasError ? 'border-red-500' : 'border-border' }`} placeholder={isRequired ? 'Required' : 'Optional'} /> {hasError &&

{formErrors[fieldName]}

}
); } if (fieldSchema.enum && Array.isArray(fieldSchema.enum)) { return (
{fieldSchema.description && (

{fieldSchema.description}

)} {hasError &&

{formErrors[fieldName]}

}
); } // Default to string input return (
{fieldSchema.description && (

{fieldSchema.description}

)} updateFormField(fieldName, e.target.value)} className={`w-full px-3 py-2 border rounded-md text-sm bg-background ${ hasError ? 'border-red-500' : 'border-border' }`} placeholder={isRequired ? 'Required' : 'Optional'} /> {hasError &&

{formErrors[fieldName]}

}
); }; const handleApprove = () => { if (approval.type === ApprovalType.ELICITATION) { // Validate form - metadata is typed as ElicitationMetadata after type check const { schema } = approval.metadata; const required = (schema.required as string[]) || []; const errors: Record = {}; for (const fieldName of required) { const value = formData[fieldName]; const isEmptyString = typeof value === 'string' && value.trim() === ''; if (value === undefined || value === null || isEmptyString) { errors[fieldName] = 'This field is required'; } } if (Object.keys(errors).length > 0) { setFormErrors(errors); return; } onApprove(formData); } else { onApprove(undefined, rememberChoice); } }; return (
{/* Header */}
{approval.type === ApprovalType.ELICITATION ? 'Information Request' : 'Approval Required'}
{/* Content */} {approval.type === ApprovalType.COMMAND_CONFIRMATION ? (
Tool: {approval.metadata.toolName}
Command:
                            {approval.metadata.command}
                        
{approval.metadata.originalCommand && approval.metadata.originalCommand !== approval.metadata.command && (
Original: {approval.metadata.originalCommand}
)}

This command requires approval because it may modify your system.

) : approval.type === ApprovalType.ELICITATION ? (

{approval.metadata.prompt}

From: {approval.metadata.serverName || 'Dexto Agent'}

{(() => { const { schema } = approval.metadata; if (!schema?.properties || typeof schema.properties !== 'object') { return (

Invalid form schema

); } const required = (schema.required as string[]) || []; const properties = schema.properties; return (
{Object.entries(properties).map(([fieldName, fieldSchema]) => { const isRequired = required.includes(fieldName); return renderFormField( fieldName, fieldSchema as JSONSchema7, isRequired ); })}
); })()}
) : approval.type === ApprovalType.TOOL_CONFIRMATION ? (
Tool: {approval.metadata.toolName}
{approval.metadata.description && (

{approval.metadata.description}

)}
Arguments:
                            {JSON.stringify(approval.metadata.args, null, 2)}
                        
{/* Only show "Remember choice" for tool confirmations, not command confirmations */}
setRememberChoice(checked === true)} />
) : null} {/* Actions */}
); }