feat(swift): voeg chat orchestration toe (E5)
Epic 5 compleet: Chat orchestration voor Swift Agenda Planning. Alle agenda intents worden nu correct gerouteerd naar AgendaBlock met user-friendly error handling en fallback opties. E5.S1 - Action Routing (2 SP) - routeIntentToArtifact() functie in action-parser - Maps agenda intents naar juiste AgendaBlock mode - Confidence threshold enforcement (< 0.7 → fallback) - Required entity validation (patient voor create, identifier voor reschedule) - Command-input gebruikt nieuwe routing ipv legacy openBlock - Migratie naar modern artifact systeem (openArtifact) E5.S2 - Chat Prompt Update (2 SP) - 4 agenda intents toegevoegd aan Swift chat system prompt - agenda_query: afspraken opvragen op datumrange - create_appointment: nieuwe afspraak maken (required: patient, datetime) - cancel_appointment: afspraak annuleren (disambiguation support) - reschedule_appointment: afspraak verzetten (required: identifier) - Entity extraction rules gedocumenteerd (dateRange, datetime, identifier) - 4 complete voorbeelden met JSON action format - Clarification questions voor incomplete data - Prompt size: ~325 → ~525 regels (+60%) E5.S3 - Error States (2 SP) - AgendaErrorState component voor full-page errors - AgendaErrorAlert component voor inline form errors - getUserFriendlyMessage() vertaalt technical → user-friendly Dutch - Auto-redirect bij auth errors (401 → /login) - Fallback link naar /epd/agenda in alle error states - Context-aware messaging (query/create/cancel/reschedule) - Retry functionaliteit voor recoverable errors - Dev-only technical details collapsible Error message mapping: - 401 → "Je sessie is verlopen. Log opnieuw in." + auto-redirect - 403 → "Je hebt geen toegang tot deze afspraak." - 404 → "De gevraagde afspraak kon niet worden gevonden." - 500 → "Er ging iets mis op de server. Probeer het opnieuw." - Network → "Geen internetverbinding. Controleer je netwerkverbinding." - Timeout → "De aanvraag duurde te lang. Probeer het opnieuw." Components updated: - command-input: gebruikt routeIntentToArtifact + openArtifact - agenda-create-form: gebruikt AgendaErrorAlert met fallback link - chat/route: uitgebreide system prompt met agenda sectie Nieuwe files: - lib/swift/action-parser.ts: routeIntentToArtifact() functie - components/swift/artifacts/blocks/agenda-error-state.tsx (225 regels) - docs/swift/implementation-e5-s1-action-routing.md - docs/swift/implementation-e5-s2-chat-prompt.md - docs/swift/implementation-e5-s3-error-states.md Documentatie: - Bouwplan bijgewerkt: Epic 5 → Done - 3 implementation docs met API specs en testing scenarios - Error handling best practices gedocumenteerd Progress: 48 SP / 51 SP (94%) - Epic 6 (QA) remaining 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -21,6 +21,7 @@ import type { BlockType } from '@/lib/swift/types';
|
||||
import { Mic, MicOff, Send, Loader2 } from 'lucide-react';
|
||||
import { useToast } from '@/hooks/use-toast';
|
||||
import { safeFetch, getErrorInfo } from '@/lib/swift/error-handler';
|
||||
import { routeIntentToArtifact } from '@/lib/swift/action-parser';
|
||||
|
||||
export const CommandInput = forwardRef<HTMLInputElement>(function CommandInput(_, ref) {
|
||||
const {
|
||||
@@ -31,6 +32,7 @@ export const CommandInput = forwardRef<HTMLInputElement>(function CommandInput(_
|
||||
activeBlock,
|
||||
isVoiceActive,
|
||||
openBlock,
|
||||
openArtifact,
|
||||
addRecentAction,
|
||||
} = useSwiftStore();
|
||||
const { toast } = useToast();
|
||||
@@ -139,22 +141,27 @@ export const CommandInput = forwardRef<HTMLInputElement>(function CommandInput(_
|
||||
const result = await response.json();
|
||||
const { intent, confidence, entities } = result;
|
||||
|
||||
// Check if we have a valid intent with sufficient confidence
|
||||
if (intent !== 'unknown' && confidence >= 0.5) {
|
||||
// Open the appropriate block with prefill data
|
||||
// Type assertion: intent is BlockType after 'unknown' check
|
||||
openBlock(intent as BlockType, entities);
|
||||
|
||||
// Route intent to artifact using Epic 5.S1 routing logic
|
||||
const artifactConfig = routeIntentToArtifact(intent, entities, confidence);
|
||||
|
||||
if (artifactConfig) {
|
||||
// Open artifact with routing configuration
|
||||
openArtifact({
|
||||
type: artifactConfig.type,
|
||||
title: artifactConfig.title,
|
||||
prefill: artifactConfig.prefill,
|
||||
});
|
||||
|
||||
// Add to recent actions
|
||||
addRecentAction({
|
||||
intent,
|
||||
label: inputText.slice(0, 50), // Truncate for display
|
||||
patientName: entities.patientName,
|
||||
});
|
||||
|
||||
|
||||
clearInput();
|
||||
} else {
|
||||
// Low confidence or unknown intent - show FallbackPicker
|
||||
// Low confidence or missing required entities - show FallbackPicker
|
||||
openBlock('fallback', { content: inputText });
|
||||
clearInput();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user