Add API layer, Zustand store, markdown renderer, types
This commit is contained in:
+121
@@ -0,0 +1,121 @@
|
||||
const API_BASE = process.env.NEXT_PUBLIC_API_URL || 'https://api.aaronnelson.studio';
|
||||
|
||||
async function request<T>(path: string, options?: RequestInit): Promise<T> {
|
||||
const res = await fetch(`${API_BASE}${path}`, {
|
||||
credentials: 'include',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
...options,
|
||||
});
|
||||
if (!res.ok) throw new Error(`API error: ${res.status}`);
|
||||
return res.json();
|
||||
}
|
||||
|
||||
export const api = {
|
||||
// Settings
|
||||
getSettings: () => request<Settings>('/api/settings'),
|
||||
updateSettings: (s: Partial<Settings>) =>
|
||||
request<Settings>('/api/settings', { method: 'POST', body: JSON.stringify(s) }),
|
||||
|
||||
// Conversations
|
||||
getConversations: () => request<Conversation[]>('/api/conversations'),
|
||||
newConversation: (title = 'New conversation') =>
|
||||
request<Conversation>('/api/conversations', { method: 'POST', body: JSON.stringify({ title }) }),
|
||||
getMessages: (id: string) => request<Message[]>(`/api/conversations/${id}/messages`),
|
||||
renameConversation: (id: string, title: string) =>
|
||||
request<Conversation>(`/api/conversations/${id}`, { method: 'PATCH', body: JSON.stringify({ title }) }),
|
||||
deleteConversation: (id: string) =>
|
||||
request<{ deleted: string }>(`/api/conversations/${id}`, { method: 'DELETE' }),
|
||||
clearAllConversations: () =>
|
||||
request<{ cleared: boolean }>('/api/conversations', { method: 'DELETE' }),
|
||||
|
||||
// Chat
|
||||
sendMessage: (message: string, conversation_id: string) =>
|
||||
request<ChatResponse>('/api/chat', { method: 'POST', body: JSON.stringify({ message, conversation_id }) }),
|
||||
|
||||
// Memory
|
||||
getMemory: () => request<{ content: string }>('/api/memory'),
|
||||
updateMemory: (content: string) =>
|
||||
request<{ saved: boolean }>('/api/memory', { method: 'POST', body: JSON.stringify({ content }) }),
|
||||
|
||||
// Status
|
||||
getStatus: () => request<Status>('/api/status'),
|
||||
|
||||
// Reindex
|
||||
reindex: () => request<{ started: boolean }>('/api/reindex', { method: 'POST' }),
|
||||
|
||||
// Transcribe
|
||||
transcribe: async (audio: Blob): Promise<{ text: string }> => {
|
||||
const form = new FormData();
|
||||
form.append('audio', audio, 'recording.webm');
|
||||
const res = await fetch(`${API_BASE}/api/transcribe`, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
body: form,
|
||||
});
|
||||
if (!res.ok) throw new Error(`Transcribe error: ${res.status}`);
|
||||
return res.json();
|
||||
},
|
||||
|
||||
// Capture
|
||||
capture: async (data: CapturePayload): Promise<{ saved: boolean }> => {
|
||||
const form = new FormData();
|
||||
if (data.audio) form.append('audio', data.audio, 'capture.webm');
|
||||
if (data.image) form.append('image', data.image);
|
||||
if (data.text) form.append('text', data.text);
|
||||
if (data.project) form.append('project', data.project);
|
||||
const res = await fetch(`${API_BASE}/api/capture`, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
body: form,
|
||||
});
|
||||
if (!res.ok) throw new Error(`Capture error: ${res.status}`);
|
||||
return res.json();
|
||||
},
|
||||
};
|
||||
|
||||
// Types
|
||||
export interface Settings {
|
||||
theme: 'light' | 'dark';
|
||||
font_size: 'small' | 'medium' | 'large';
|
||||
web_search: boolean;
|
||||
show_sources: boolean;
|
||||
}
|
||||
|
||||
export interface Conversation {
|
||||
id: string;
|
||||
title: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
message_count: number;
|
||||
}
|
||||
|
||||
export interface Message {
|
||||
role: 'user' | 'assistant';
|
||||
content: string;
|
||||
sources: string[];
|
||||
timestamp: string;
|
||||
}
|
||||
|
||||
export interface ChatResponse {
|
||||
response: string;
|
||||
sources: string[];
|
||||
conversation_id: string;
|
||||
}
|
||||
|
||||
export interface Status {
|
||||
aaron_ai: string;
|
||||
watcher: string;
|
||||
chunk_count: number;
|
||||
file_count: number;
|
||||
last_indexed: string;
|
||||
conversation_count: number;
|
||||
model: string;
|
||||
nextcloud_path: string;
|
||||
}
|
||||
|
||||
export interface CapturePayload {
|
||||
audio?: Blob;
|
||||
image?: File;
|
||||
text?: string;
|
||||
project?: string;
|
||||
}
|
||||
Reference in New Issue
Block a user