refactor: rename swift → cortex in code and documentation
Complete rename of "swift" terminology to "cortex" across the codebase: Code Changes: - Rename directories: lib/swift → lib/cortex, components/swift → components/cortex - Rename API routes: /api/swift/* → /api/cortex/* - Rename page routes: /epd/swift → /epd/cortex - Rename store: swift-store.ts → cortex-store.ts Type Renames: - SwiftIntent → CortexIntent - SwiftStore → CortexStore - useSwiftStore → useCortexStore - SwiftContext → CortexContext - useSwiftVoice → useCortexVoice Documentation Updates (docs/intent/): - Safety Net → Nudge (Layer 3 rename) - SafetySuggestion → NudgeSuggestion - evaluateSafetyNet → evaluateNudge - SWIFT_* feature flags → CORTEX_* - All path references updated to match new structure Files affected: 47 files, ~700 lines changed 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,14 +1,14 @@
|
||||
/**
|
||||
* Action Parser for Swift Assistent
|
||||
* Action Parser for Cortex Assistent
|
||||
*
|
||||
* Parses JSON action objects from AI responses and validates them.
|
||||
*
|
||||
* Epic: E3 (Chat API & Swift Assistent)
|
||||
* Epic: E3 (Chat API & Cortex Assistent)
|
||||
* Story: E3.S4 (Intent detection in response)
|
||||
*/
|
||||
|
||||
import { z } from 'zod';
|
||||
import type { ChatAction, SwiftIntent, BlockType } from '@/stores/swift-store';
|
||||
import type { ChatAction, CortexIntent, BlockType } from '@/stores/cortex-store';
|
||||
|
||||
// Validation schema for action objects
|
||||
const ActionSchema = z.object({
|
||||
@@ -156,10 +156,19 @@ export function parseActionFromResponse(responseText: string): ParsedActionResul
|
||||
};
|
||||
}
|
||||
|
||||
// Normalize entities - convert complex identifier to string
|
||||
const normalizedEntities = {
|
||||
...validation.data.entities,
|
||||
// Convert object identifier to string if needed
|
||||
identifier: typeof validation.data.entities.identifier === 'object'
|
||||
? validation.data.entities.identifier.encounterId || JSON.stringify(validation.data.entities.identifier)
|
||||
: validation.data.entities.identifier,
|
||||
};
|
||||
|
||||
// Valid action found
|
||||
const action: ChatAction = {
|
||||
intent: validation.data.intent,
|
||||
entities: validation.data.entities,
|
||||
entities: normalizedEntities,
|
||||
confidence: validation.data.confidence,
|
||||
artifact: validation.data.artifact,
|
||||
};
|
||||
@@ -191,7 +200,7 @@ export function getConfidenceLabel(confidence: number): string {
|
||||
/**
|
||||
* Validate that artifact type matches intent
|
||||
*/
|
||||
export function validateArtifactType(intent: SwiftIntent, artifactType?: BlockType): boolean {
|
||||
export function validateArtifactType(intent: CortexIntent, artifactType?: BlockType): boolean {
|
||||
if (!artifactType) return true; // No artifact is valid
|
||||
if (artifactType === 'patient-dashboard') return true;
|
||||
|
||||
@@ -199,14 +208,14 @@ export function validateArtifactType(intent: SwiftIntent, artifactType?: BlockTy
|
||||
if (intent === 'unknown') return artifactType === 'fallback';
|
||||
|
||||
// For agenda intents, all map to agenda block types
|
||||
const agendaIntents: SwiftIntent[] = [
|
||||
const agendaIntents: CortexIntent[] = [
|
||||
'agenda_query',
|
||||
'create_appointment',
|
||||
'cancel_appointment',
|
||||
'reschedule_appointment',
|
||||
];
|
||||
if (agendaIntents.includes(intent)) {
|
||||
return agendaIntents.includes(artifactType as SwiftIntent);
|
||||
return agendaIntents.includes(artifactType as CortexIntent);
|
||||
}
|
||||
|
||||
return intent === artifactType;
|
||||
@@ -224,7 +233,7 @@ export function validateArtifactType(intent: SwiftIntent, artifactType?: BlockTy
|
||||
* @returns Artifact configuration or null if confidence too low or required data missing
|
||||
*/
|
||||
export function routeIntentToArtifact(
|
||||
intent: SwiftIntent,
|
||||
intent: CortexIntent,
|
||||
entities: Record<string, any>,
|
||||
confidence: number
|
||||
): { type: BlockType; prefill: Record<string, any>; title: string } | null {
|
||||
@@ -1,13 +1,13 @@
|
||||
/**
|
||||
* Swift Chat API Client
|
||||
* Cortex Chat API Client
|
||||
*
|
||||
* Client-side helper voor het aanroepen van de Swift chat API met streaming support.
|
||||
* Client-side helper voor het aanroepen van de Cortex chat API met streaming support.
|
||||
*
|
||||
* Epic: E3 (Chat API & Swift Assistent)
|
||||
* Epic: E3 (Chat API & Cortex Assistent)
|
||||
* Story: E3.S1 (Chat API endpoint skeleton)
|
||||
*/
|
||||
|
||||
import type { ChatMessage } from '@/stores/swift-store';
|
||||
import type { ChatMessage } from '@/stores/cortex-store';
|
||||
|
||||
export interface ChatContext {
|
||||
activePatient?: {
|
||||
@@ -36,7 +36,7 @@ export async function sendChatMessage(
|
||||
onError?: (error: string) => void
|
||||
): Promise<void> {
|
||||
try {
|
||||
const response = await fetch('/api/swift/chat', {
|
||||
const response = await fetch('/api/cortex/chat', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
@@ -2,7 +2,7 @@
|
||||
* Date/Time Parser Utilities
|
||||
*
|
||||
* Parses natural language date and time expressions (Dutch)
|
||||
* for Swift agenda functionality.
|
||||
* for Cortex agenda functionality.
|
||||
*/
|
||||
|
||||
import {
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
import type { VerpleegkundigCategory } from '@/lib/types/report';
|
||||
import type { ExtractedEntities, SwiftIntent } from './types';
|
||||
import type { ExtractedEntities, CortexIntent } from './types';
|
||||
import {
|
||||
parseRelativeDate,
|
||||
parseTime,
|
||||
@@ -90,7 +90,7 @@ const COMMON_NAMES = new Set([
|
||||
/**
|
||||
* Extract entities from user input based on the detected intent.
|
||||
*/
|
||||
export function extractEntities(input: string, intent: SwiftIntent): ExtractedEntities {
|
||||
export function extractEntities(input: string, intent: CortexIntent): ExtractedEntities {
|
||||
const trimmedInput = input.trim().toLowerCase();
|
||||
const entities: ExtractedEntities = {};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Error Handler Utility voor Swift
|
||||
*
|
||||
* Error Handler Utility voor Cortex
|
||||
*
|
||||
* E5.S2: Gecentraliseerde error handling met network detection,
|
||||
* gebruiksvriendelijke berichten en retry logic.
|
||||
*/
|
||||
@@ -1,9 +1,9 @@
|
||||
/**
|
||||
* Swift Library Barrel Export
|
||||
* Cortex Library Barrel Export
|
||||
*/
|
||||
|
||||
export * from './types';
|
||||
export * from './use-swift-voice';
|
||||
export * from './use-cortex-voice';
|
||||
export * from './intent-classifier';
|
||||
export * from './intent-classifier-ai';
|
||||
export * from './entity-extractor';
|
||||
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
import { z } from 'zod';
|
||||
import type { SwiftIntent, ExtractedEntities } from './types';
|
||||
import type { CortexIntent, ExtractedEntities } from './types';
|
||||
import type { VerpleegkundigCategory } from '@/lib/types/report';
|
||||
|
||||
// Zod schema for AI response validation
|
||||
@@ -37,7 +37,7 @@ const AIIntentResponseSchema = z.object({
|
||||
type AIIntentResponse = z.infer<typeof AIIntentResponseSchema>;
|
||||
|
||||
export interface AIClassificationResult {
|
||||
intent: SwiftIntent;
|
||||
intent: CortexIntent;
|
||||
confidence: number;
|
||||
entities: ExtractedEntities;
|
||||
source: 'ai';
|
||||
@@ -45,7 +45,7 @@ export interface AIClassificationResult {
|
||||
reasoning?: string;
|
||||
}
|
||||
|
||||
const INTENT_CLASSIFIER_SYSTEM_PROMPT = `Je bent een intent classifier voor een Nederlands EPD (Elektronisch Patiënten Dossier) systeem genaamd Swift.
|
||||
const INTENT_CLASSIFIER_SYSTEM_PROMPT = `Je bent een intent classifier voor een Nederlands EPD (Elektronisch Patiënten Dossier) systeem genaamd Cortex.
|
||||
|
||||
Je taak is om de intentie van een zorgmedewerker te classificeren in één van deze categorieën:
|
||||
|
||||
@@ -199,7 +199,7 @@ export async function classifyIntentWithAI(input: string): Promise<AIClassificat
|
||||
// and the local extractor will structure them properly
|
||||
|
||||
return {
|
||||
intent: validated.intent as SwiftIntent,
|
||||
intent: validated.intent as CortexIntent,
|
||||
confidence: validated.confidence,
|
||||
entities,
|
||||
source: 'ai',
|
||||
@@ -1,14 +1,14 @@
|
||||
/**
|
||||
* Local Intent Classifier
|
||||
*
|
||||
* Fast regex-based intent classification for Swift.
|
||||
* Fast regex-based intent classification for Cortex.
|
||||
* Target: <50ms response time.
|
||||
*/
|
||||
|
||||
import type { SwiftIntent } from './types';
|
||||
import type { CortexIntent } from './types';
|
||||
|
||||
export interface ClassificationResult {
|
||||
intent: SwiftIntent;
|
||||
intent: CortexIntent;
|
||||
confidence: number;
|
||||
matchedPattern?: string;
|
||||
processingTimeMs: number;
|
||||
@@ -21,7 +21,7 @@ interface PatternConfig {
|
||||
|
||||
// Intent patterns with weights
|
||||
// Weight 1.0 = exact match, 0.8 = strong match, 0.6 = partial match
|
||||
const INTENT_PATTERNS: Record<Exclude<SwiftIntent, 'unknown'>, PatternConfig[]> = {
|
||||
const INTENT_PATTERNS: Record<Exclude<CortexIntent, 'unknown'>, PatternConfig[]> = {
|
||||
dagnotitie: [
|
||||
// Exact commands
|
||||
{ pattern: /^dagnotitie\b/i, weight: 1.0 },
|
||||
@@ -159,7 +159,7 @@ const HELP_PATTERNS: PatternConfig[] = [
|
||||
{ pattern: /^help\b/i, weight: 1.0 },
|
||||
{ pattern: /^hulp\b/i, weight: 1.0 },
|
||||
{ pattern: /^\?\s*$/i, weight: 1.0 },
|
||||
{ pattern: /^wat\s+kan\s+(ik|je|swift)\b/i, weight: 1.0 },
|
||||
{ pattern: /^wat\s+kan\s+(ik|je|cortex)\b/i, weight: 1.0 },
|
||||
{ pattern: /^hoe\s+werkt\b/i, weight: 0.9 },
|
||||
{ pattern: /^voorbeelden?\b/i, weight: 0.9 },
|
||||
];
|
||||
@@ -194,14 +194,14 @@ export function classifyIntent(input: string): ClassificationResult {
|
||||
}
|
||||
|
||||
// Find best matching intent
|
||||
let bestMatch: { intent: SwiftIntent; confidence: number; pattern: string } | null = null;
|
||||
let bestMatch: { intent: CortexIntent; confidence: number; pattern: string } | null = null;
|
||||
|
||||
for (const [intent, patterns] of Object.entries(INTENT_PATTERNS)) {
|
||||
for (const { pattern, weight } of patterns) {
|
||||
if (pattern.test(trimmedInput)) {
|
||||
if (!bestMatch || weight > bestMatch.confidence) {
|
||||
bestMatch = {
|
||||
intent: intent as SwiftIntent,
|
||||
intent: intent as CortexIntent,
|
||||
confidence: weight,
|
||||
pattern: pattern.toString(),
|
||||
};
|
||||
@@ -1,13 +1,13 @@
|
||||
/**
|
||||
* Swift Type Definitions
|
||||
* Cortex Type Definitions
|
||||
*
|
||||
* Core types for the Swift Contextual UI system.
|
||||
* Core types for the Cortex Contextual UI system.
|
||||
*/
|
||||
|
||||
import type { VerpleegkundigCategory } from '@/lib/types/report';
|
||||
|
||||
// Intent types
|
||||
export type SwiftIntent =
|
||||
export type CortexIntent =
|
||||
| 'dagnotitie'
|
||||
| 'zoeken'
|
||||
| 'overdracht'
|
||||
@@ -17,14 +17,14 @@ export type SwiftIntent =
|
||||
| 'reschedule_appointment'
|
||||
| 'unknown';
|
||||
|
||||
export type BlockType = Exclude<SwiftIntent, 'unknown'> | 'patient-dashboard';
|
||||
export type BlockType = Exclude<CortexIntent, 'unknown'> | 'patient-dashboard';
|
||||
|
||||
// Shift types
|
||||
export type ShiftType = 'nacht' | 'ochtend' | 'middag' | 'avond';
|
||||
|
||||
// Intent classification result
|
||||
export interface IntentClassificationResult {
|
||||
intent: SwiftIntent;
|
||||
intent: CortexIntent;
|
||||
confidence: number;
|
||||
entities: ExtractedEntities;
|
||||
source: 'local' | 'ai';
|
||||
@@ -140,7 +140,7 @@ export const BLOCK_CONFIGS: Record<BlockType, BlockConfig> = {
|
||||
// Recent action type
|
||||
export interface RecentAction {
|
||||
id: string;
|
||||
intent: SwiftIntent;
|
||||
intent: CortexIntent;
|
||||
label: string;
|
||||
timestamp: Date;
|
||||
patientName?: string;
|
||||
@@ -1,20 +1,20 @@
|
||||
'use client';
|
||||
|
||||
/**
|
||||
* Swift Voice Hook
|
||||
* Cortex Voice Hook
|
||||
*
|
||||
* Wraps useDeepgramStreaming for Swift-specific voice input behavior.
|
||||
* Wraps useDeepgramStreaming for Cortex-specific voice input behavior.
|
||||
* Streams transcript directly to the command input.
|
||||
*/
|
||||
|
||||
import { useCallback, useEffect, useRef } from 'react';
|
||||
import { useSwiftStore } from '@/stores/swift-store';
|
||||
import { useCortexStore } from '@/stores/cortex-store';
|
||||
import {
|
||||
useDeepgramStreaming,
|
||||
type TranscriptResult,
|
||||
} from '@/hooks/use-deepgram-streaming';
|
||||
|
||||
export interface UseSwiftVoiceReturn {
|
||||
export interface UseCortexVoiceReturn {
|
||||
isRecording: boolean;
|
||||
isConnecting: boolean;
|
||||
isConnected: boolean;
|
||||
@@ -25,8 +25,8 @@ export interface UseSwiftVoiceReturn {
|
||||
isBrowserSupported: boolean;
|
||||
}
|
||||
|
||||
export function useSwiftVoice(): UseSwiftVoiceReturn {
|
||||
const { setInputValue, setVoiceActive, inputValue } = useSwiftStore();
|
||||
export function useCortexVoice(): UseCortexVoiceReturn {
|
||||
const { setInputValue, setVoiceActive, inputValue } = useCortexStore();
|
||||
|
||||
// Track the base text (what was in input before recording started)
|
||||
const baseTextRef = useRef('');
|
||||
@@ -59,7 +59,7 @@ export function useSwiftVoice(): UseSwiftVoiceReturn {
|
||||
|
||||
const handleError = useCallback(
|
||||
(error: Error) => {
|
||||
console.error('[SwiftVoice] Error:', error.message);
|
||||
console.error('[CortexVoice] Error:', error.message);
|
||||
},
|
||||
[]
|
||||
);
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Manual verification script for entity extraction with date/time parser
|
||||
* Run with: pnpm tsx lib/swift/verify-entity-extraction.ts
|
||||
* Run with: pnpm tsx lib/cortex/verify-entity-extraction.ts
|
||||
*/
|
||||
|
||||
import { extractEntities } from './entity-extractor';
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Manual verification script for date-time parser
|
||||
* Run with: pnpm tsx lib/swift/verify-parser.ts
|
||||
* Run with: pnpm tsx lib/cortex/verify-parser.ts
|
||||
*/
|
||||
|
||||
import {
|
||||
Reference in New Issue
Block a user