| |
| |
| |
| |
| |
|
|
| const API_BASE = import.meta.env.VITE_API_URL || '/api/v1'; |
|
|
| |
|
|
| export interface User { |
| id: string; |
| external_id: string; |
| created_at: string; |
| } |
|
|
| export interface Session { |
| id: string; |
| user_id: string; |
| started_at: string; |
| ended_at: string | null; |
| metadata: Record<string, unknown>; |
| } |
|
|
| export interface MemoryItem { |
| id: string; |
| user_id: string; |
| session_id: string | null; |
| memory_type: 'episodic' | 'semantic' | 'procedural'; |
| content: string; |
| summary: string | null; |
| metadata: Record<string, unknown>; |
| importance: number; |
| recency_score: number; |
| access_count: number; |
| created_at: string; |
| last_accessed: string | null; |
| } |
|
|
| export interface ScoredMemory { |
| memory: MemoryItem; |
| score: number; |
| cosine_similarity: number; |
| } |
|
|
| export interface IngestResponse { |
| memory_id: string; |
| message: string; |
| } |
|
|
| export interface ChatResponse { |
| assistant_message: string; |
| retrieved_memories: { |
| id: string; |
| type: string; |
| content: string; |
| score: number; |
| }[]; |
| } |
|
|
| export interface ContradictionItem { |
| id: string; |
| memory_a: string; |
| memory_b: string; |
| detected_at: string; |
| resolved: boolean; |
| memory_a_content: string | null; |
| memory_b_content: string | null; |
| } |
|
|
| export interface StatsOverview { |
| total_memories: number; |
| type_counts: { |
| episodic: number; |
| semantic: number; |
| procedural: number; |
| }; |
| avg_importance: number; |
| avg_recency_score: number; |
| total_users: number; |
| total_sessions: number; |
| recent_contradictions: ContradictionItem[]; |
| } |
|
|
| export interface GraphNode { |
| id: string; |
| memory_type: 'episodic' | 'semantic' | 'procedural'; |
| content: string; |
| importance: number; |
| created_at: string; |
| } |
|
|
| export interface GraphEdge { |
| source: string; |
| target: string; |
| similarity: number; |
| } |
|
|
| export interface GraphData { |
| nodes: GraphNode[]; |
| edges: GraphEdge[]; |
| } |
|
|
| export interface SessionWithMemories extends Session { |
| memories: MemoryItem[]; |
| } |
|
|
| |
|
|
| async function apiFetch<T>( |
| path: string, |
| options: RequestInit = {} |
| ): Promise<T> { |
| const url = `${API_BASE}${path}`; |
| const headers: Record<string, string> = { |
| 'Content-Type': 'application/json', |
| ...(options.headers as Record<string, string> || {}), |
| }; |
|
|
| const response = await fetch(url, { ...options, headers }); |
|
|
| if (!response.ok) { |
| const body = await response.json().catch(() => ({ detail: response.statusText })); |
| throw new Error(body.detail || `API error: ${response.status}`); |
| } |
|
|
| return response.json(); |
| } |
|
|
| |
|
|
| export async function createUser(externalId: string): Promise<User> { |
| return apiFetch<User>('/users', { |
| method: 'POST', |
| body: JSON.stringify({ external_id: externalId }), |
| }); |
| } |
|
|
| export async function getUser(userId: string): Promise<User> { |
| return apiFetch<User>(`/users/${userId}`); |
| } |
|
|
| export async function getUserContext( |
| userId: string, |
| query: string, |
| topK: number = 10 |
| ): Promise<ScoredMemory[]> { |
| const params = new URLSearchParams({ query, top_k: String(topK) }); |
| return apiFetch<ScoredMemory[]>(`/users/${userId}/context?${params}`); |
| } |
|
|
| export async function createSession( |
| userId: string, |
| metadata: Record<string, unknown> = {} |
| ): Promise<Session> { |
| return apiFetch<Session>('/sessions', { |
| method: 'POST', |
| body: JSON.stringify({ user_id: userId, metadata }), |
| }); |
| } |
|
|
| export async function getSession(sessionId: string): Promise<SessionWithMemories> { |
| return apiFetch<SessionWithMemories>(`/sessions/${sessionId}`); |
| } |
|
|
| export async function endSession(sessionId: string): Promise<Session> { |
| return apiFetch<Session>(`/sessions/${sessionId}`, { method: 'DELETE' }); |
| } |
|
|
| export async function sendChatMessage( |
| sessionId: string, |
| userMessage: string |
| ): Promise<ChatResponse> { |
| return apiFetch<ChatResponse>(`/sessions/${sessionId}/chat`, { |
| method: 'POST', |
| body: JSON.stringify({ user_message: userMessage }), |
| }); |
| } |
|
|
| export async function ingestMemory( |
| userId: string, |
| sessionId: string, |
| userMessage: string, |
| assistantMessage: string |
| ): Promise<IngestResponse> { |
| return apiFetch<IngestResponse>('/memories/ingest', { |
| method: 'POST', |
| body: JSON.stringify({ |
| user_id: userId, |
| session_id: sessionId, |
| user_message: userMessage, |
| assistant_message: assistantMessage, |
| }), |
| }); |
| } |
|
|
| export async function searchMemories( |
| userId: string, |
| query: string, |
| memoryType?: string, |
| topK: number = 10 |
| ): Promise<ScoredMemory[]> { |
| const params = new URLSearchParams({ |
| user_id: userId, |
| query, |
| top_k: String(topK), |
| }); |
| if (memoryType) params.append('memory_type', memoryType); |
| return apiFetch<ScoredMemory[]>(`/memories/search?${params}`); |
| } |
|
|
| export async function getMemory(memoryId: string): Promise<MemoryItem> { |
| return apiFetch<MemoryItem>(`/memories/${memoryId}`); |
| } |
|
|
| export async function deleteMemory(memoryId: string): Promise<MemoryItem> { |
| return apiFetch<MemoryItem>(`/memories/${memoryId}`, { method: 'DELETE' }); |
| } |
|
|
| export async function getContradictions(memoryId: string): Promise<ContradictionItem[]> { |
| return apiFetch<ContradictionItem[]>(`/memories/${memoryId}/contradictions`); |
| } |
|
|
| export async function getStatsOverview(): Promise<StatsOverview> { |
| return apiFetch<StatsOverview>('/stats/overview'); |
| } |
|
|
| export async function getGraphData(userId?: string): Promise<GraphData> { |
| const params = userId ? `?user_id=${userId}` : ''; |
| return apiFetch<GraphData>(`/stats/graph${params}`); |
| } |
|
|