feat(cortex): update chat/nudge flow, deepgram streaming and agenda form

Refines chat panel, nudge messages and artifact rendering, reworks
deepgram token/streaming handling, and adds test tooling deps
(playwright, cypress) to package.json.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
colinislit
2026-07-09 22:37:46 +02:00
parent 6c6dae5eb7
commit cdeea793bd
20 changed files with 1634 additions and 283 deletions

View File

@@ -26,6 +26,8 @@ const ActionSchema = z.object({
'intake_navigeer',
'risico_query',
'diagnose_query',
// No Show casus
'register_no_show',
'unknown',
]),
entities: z.object({
@@ -88,6 +90,8 @@ const ActionSchema = z.object({
'diagnose_query',
'fallback',
'patient-dashboard',
// No Show casus
'register_no_show',
]),
prefill: z.record(z.string(), z.any()),
})
@@ -253,6 +257,9 @@ export function getDefaultConfirmationMessage(intent: CortexIntent, entities: Re
case 'overdracht':
return 'Ik bereid de overdracht voor.';
case 'register_no_show':
return 'Ik registreer de no show en controleer de agenda op declarabiliteit.';
default:
return 'Ik help je verder.';
}
@@ -404,6 +411,11 @@ export function routeIntentToArtifact(
// Returns null to trigger navigation instead of artifact
return null;
case 'register_no_show':
// Artifact opened via handleNoShowRescriptStep in chat-panel.tsx after API calls —
// not via generic routing (needs documentId + rescripted content from API response)
return null;
case 'unknown':
// Unknown intent - show fallback picker
return {

View File

@@ -206,6 +206,18 @@ const INTENT_PATTERNS: Record<Exclude<CortexIntent, 'unknown'>, PatternConfig[]>
{ pattern: /^geef\s+(een\s+)?(overzicht|samenvatting)\s+(van\s+)?(de\s+)?diagnose[ns]?/i, weight: 0.85 },
{ pattern: /^(is\s+er\s+)?(een\s+)?persoonlijkheidsstoornis/i, weight: 0.9 },
],
// No Show casus
register_no_show: [
{ pattern: /no.?show/i, weight: 1.0 },
{ pattern: /niet\s+verschenen/i, weight: 0.95 },
{ pattern: /niet\s+gekomen/i, weight: 0.95 },
{ pattern: /niet\s+op\s+komen\s+dagen/i, weight: 0.95 },
{ pattern: /afwezig\s+(bij|voor)\s+(de\s+)?afspraak/i, weight: 0.9 },
{ pattern: /pati[eë]nt\s+afwezig/i, weight: 0.85 },
{ pattern: /komt?\s+niet\s+(op|naar)/i, weight: 0.85 },
{ pattern: /is\s+er\s+niet\s+(geweest)?/i, weight: 0.7 },
],
};
// Help patterns (separate, always check)

View File

@@ -25,6 +25,8 @@ export const INTENT_LABELS: Record<CortexIntent, string> = {
intake_navigeer: 'Naar intake sectie',
risico_query: 'Risicotaxatie',
diagnose_query: 'Diagnoses',
// No Show casus
register_no_show: 'No Show registratie',
unknown: 'Onbekend',
};

View File

@@ -192,6 +192,22 @@ const DEFAULT_EXPIRY_MS = 5 * 60 * 1000;
* In production, these would come from a database or configuration.
*/
export const PROTOCOL_RULES: ProtocolRule[] = [
{
id: 'noshow-declarabel-check',
name: 'No Show declarabiliteitscheck',
trigger: {
intent: 'register_no_show',
conditions: [],
},
suggestion: {
intent: 'cancel_appointment',
message: 'Ik zie een declarabel consult in de agenda. Volgens inkoopvoorwaarden mag deze afspraak NIET gedeclareerd worden. Wil je dat ik deze annuleer als \'No Show\'?',
prefillEntities: (_source) => ({}),
},
priority: 'high',
enabled: true,
expiresAfterMs: DEFAULT_EXPIRY_MS,
},
{
id: 'wondzorg-controle',
name: 'Wondcontrole na verzorging',

View File

@@ -212,6 +212,27 @@ const INTENT_PATTERNS: Record<Exclude<CortexIntent, 'unknown'>, PatternConfig[]>
{ pattern: /^diagnose[ns]?\s+(van|voor)\s+\w+/i, weight: 0.95 },
{ pattern: /^icd\s*-?\s*10/i, weight: 0.8 },
],
// =========================================================================
// No Show casus
// =========================================================================
register_no_show: [
// Exacte no-show varianten
{ pattern: /no.?show/i, weight: 1.0 },
// "Niet verschenen" varianten
{ pattern: /niet\s+verschenen/i, weight: 0.95 },
{ pattern: /niet\s+gekomen/i, weight: 0.95 },
{ pattern: /niet\s+op\s+komen\s+dagen/i, weight: 0.95 },
// "Afwezig" + context
{ pattern: /afwezig\s+(bij|voor)\s+(de\s+)?afspraak/i, weight: 0.9 },
{ pattern: /pati[eë]nt\s+afwezig/i, weight: 0.85 },
// Werkwoordvormen
{ pattern: /komt?\s+niet\s+(op|naar)/i, weight: 0.85 },
{ pattern: /is\s+er\s+niet\s+(geweest)?/i, weight: 0.7 },
],
};
/**

View File

@@ -20,6 +20,8 @@ export type CortexIntent =
| 'intake_navigeer'
| 'risico_query'
| 'diagnose_query'
// No Show casus
| 'register_no_show'
| 'unknown';
export type BlockType =
@@ -173,6 +175,13 @@ export const BLOCK_CONFIGS: Record<BlockType, BlockConfig> = {
size: 'md',
icon: 'Stethoscope',
},
// No Show casus
register_no_show: {
type: 'register_no_show',
title: 'No Show Registratie',
size: 'md',
icon: 'UserX',
},
};
// Recent action type