/** * Configurable API Client */ import type { Session, Message, HealthStatus, FileListResponse, FileReadResponse, FileTreeResponse, ServerConfig, CommandInfo, CommandSearchResult, CommandExecuteResult, CommandListResponse, } from './types.js'; // Re-export types export type { Session, Message, HealthStatus, FileInfo, FileListResponse, FileReadResponse, FileTreeNode, FileTreeResponse, ServerConfig, CommandInfo, CommandSearchResult, CommandExecuteResult, CommandListResponse, } from './types.js'; // API Configuration interface ApiConfig { baseUrl: string; wsBaseUrl: () => string; healthUrl: () => string; } let apiConfig: ApiConfig = { baseUrl: '/api', wsBaseUrl: () => { const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; return `${protocol}//${window.location.host}/api`; }, healthUrl: () => '/health', }; /** * Configure API client for different environments */ export function configureApiClient(config: { baseUrl: string; wsBaseUrl: string | (() => string); healthUrl?: string | (() => string); }) { apiConfig = { baseUrl: config.baseUrl, wsBaseUrl: typeof config.wsBaseUrl === 'function' ? config.wsBaseUrl : () => config.wsBaseUrl as string, healthUrl: config.healthUrl ? typeof config.healthUrl === 'function' ? config.healthUrl : () => config.healthUrl as string : () => '/health', }; } async function request(method: string, path: string, body?: unknown): Promise { const response = await fetch(`${apiConfig.baseUrl}${path}`, { method, headers: { 'Content-Type': 'application/json', }, body: body ? JSON.stringify(body) : undefined, }); if (!response.ok) { const error = await response.json().catch(() => ({ error: response.statusText })); throw new Error(error.error || `HTTP ${response.status}`); } return response.json(); } // Health export async function getHealth(): Promise { const healthUrl = apiConfig.healthUrl(); const response = await fetch(healthUrl); if (!response.ok) { throw new Error(`HTTP ${response.status}`); } return response.json(); } // Sessions export async function listSessions(): Promise<{ success: boolean; data: Session[] }> { return request('GET', '/sessions'); } export async function createSession(name?: string): Promise<{ success: boolean; data: Session }> { return request('POST', '/sessions', { name }); } export async function getSession(id: string): Promise<{ success: boolean; data: Session }> { return request('GET', `/sessions/${id}`); } export async function deleteSession(id: string): Promise<{ success: boolean }> { return request('DELETE', `/sessions/${id}`); } // Messages export async function getMessages( sessionId: string ): Promise<{ success: boolean; data: Message[] }> { return request('GET', `/sessions/${sessionId}/messages`); } export async function sendMessage( sessionId: string, content: string ): Promise<{ success: boolean; data: Message }> { return request('POST', `/sessions/${sessionId}/messages`, { content }); } // WebSocket export function createWebSocket(sessionId: string): WebSocket { const wsBase = apiConfig.wsBaseUrl(); return new WebSocket(`${wsBase}/ws/${sessionId}`); } // Files export async function getWorkingDirectory(): Promise<{ success: boolean; data: { workingDirectory: string; separator: string }; }> { return request('GET', '/files'); } export async function listFiles( path: string = '.', showHidden: boolean = false ): Promise { const params = new URLSearchParams({ path }); if (showHidden) params.set('hidden', 'true'); return request('GET', `/files/list?${params}`); } export async function readFile(path: string): Promise { return request('GET', `/files/read?path=${encodeURIComponent(path)}`); } export async function getFileTree(path: string = '.', depth: number = 3): Promise { const params = new URLSearchParams({ path, depth: String(depth) }); return request('GET', `/files/tree?${params}`); } // Config export async function getConfig(): Promise<{ success: boolean; data: ServerConfig }> { return request('GET', '/config'); } export async function updateConfig( config: Partial ): Promise<{ success: boolean; data: ServerConfig }> { return request('PATCH', '/config', config); } // Commands export async function listCommands(): Promise<{ success: boolean; data: CommandListResponse }> { return request('GET', '/commands'); } export async function getCommand(name: string): Promise<{ success: boolean; data: CommandInfo }> { return request('GET', `/commands/${encodeURIComponent(name)}`); } export async function executeCommand( name: string, args: string = '' ): Promise<{ success: boolean; data?: CommandExecuteResult; error?: string }> { return request('POST', `/commands/${encodeURIComponent(name)}/execute`, { arguments: args, }); } export async function searchCommands( query: string, limit: number = 10 ): Promise<{ success: boolean; data: CommandSearchResult[] }> { return request('POST', '/commands/search', { query, limit }); } export async function reloadCommands(): Promise<{ success: boolean; data: { message: string; stats: { total: number; bySource: Record } }; }> { return request('POST', '/commands/reload'); }