Files
triqura-ecd/lib/cortex/chat-api.ts
colinislit 2170b23348 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>
2025-12-30 09:18:06 +01:00

110 lines
2.7 KiB
TypeScript

/**
* Cortex Chat API Client
*
* Client-side helper voor het aanroepen van de Cortex chat API met streaming support.
*
* Epic: E3 (Chat API & Cortex Assistent)
* Story: E3.S1 (Chat API endpoint skeleton)
*/
import type { ChatMessage } from '@/stores/cortex-store';
export interface ChatContext {
activePatient?: {
id: string;
first_name: string;
last_name: string;
} | null;
shift: 'nacht' | 'ochtend' | 'middag' | 'avond';
}
export interface StreamEvent {
type: 'content' | 'done' | 'error';
text?: string;
error?: string;
}
/**
* Send a chat message and receive streaming response via SSE
*/
export async function sendChatMessage(
message: string,
messages: ChatMessage[],
context?: ChatContext,
onChunk?: (text: string) => void,
onDone?: () => void,
onError?: (error: string) => void
): Promise<void> {
try {
const response = await fetch('/api/cortex/chat', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
message,
messages,
context,
}),
});
if (!response.ok) {
const errorData = await response.json().catch(() => ({ error: response.statusText }));
throw new Error(errorData.error || 'API request failed');
}
if (!response.body) {
throw new Error('Response body is null');
}
// Read SSE stream
const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = '';
while (true) {
const { done, value } = await reader.read();
if (done) {
break;
}
// Decode chunk and add to buffer
buffer += decoder.decode(value, { stream: true });
// Process complete SSE events (separated by \n\n)
const events = buffer.split('\n\n');
// Keep the last incomplete event in the buffer
buffer = events.pop() || '';
// Process complete events
for (const eventStr of events) {
if (!eventStr.trim()) continue;
// Parse SSE event (format: "data: {...}")
const dataMatch = eventStr.match(/^data: (.+)$/);
if (!dataMatch) continue;
try {
const event: StreamEvent = JSON.parse(dataMatch[1]);
if (event.type === 'content' && event.text) {
onChunk?.(event.text);
} else if (event.type === 'done') {
onDone?.();
} else if (event.type === 'error') {
onError?.(event.error || 'Unknown error');
}
} catch (parseError) {
console.error('Failed to parse SSE event:', parseError);
}
}
}
} catch (error) {
console.error('Chat API error:', error);
onError?.(error instanceof Error ? error.message : 'Unknown error');
}
}