import { StudyListResponse, HistoryResponse, PruningResponse, StudyStatus } from '../types'; const API_BASE = '/api'; export interface OptimizationControlResponse { success: boolean; message: string; pid?: number; } export interface ReadmeResponse { content: string; path: string; } export interface ReportResponse { content: string; generated_at?: string; } export interface ConfigResponse { config: Record; objectives: Array<{ name: string; direction: string; weight?: number; target?: number; units?: string; }>; design_variables: Array<{ name: string; min: number; max: number; baseline?: number; units?: string; }>; constraints?: Array<{ name: string; type: string; max_value?: number; min_value?: number; units?: string; }>; } export interface ProcessStatus { is_running: boolean; is_paused?: boolean; pid?: number; start_time?: string; iteration?: number; fea_count?: number; nn_count?: number; total_trials?: number; completed_trials?: number; time_per_trial_seconds?: number; eta_seconds?: number; eta_formatted?: string; rate_per_hour?: number; } export interface ModelFile { name: string; path: string; extension: string; size_bytes: number; size_display: string; modified: string; } export interface ModelFilesResponse { study_id: string; model_dir: string; files: ModelFile[]; count: number; } class ApiClient { async getStudies(): Promise { const response = await fetch(`${API_BASE}/optimization/studies`); if (!response.ok) throw new Error('Failed to fetch studies'); return response.json(); } async getStudyStatus(studyId: string): Promise { const response = await fetch(`${API_BASE}/optimization/studies/${studyId}/status`); if (!response.ok) throw new Error('Failed to fetch study status'); return response.json(); } async getStudyHistory(studyId: string): Promise { const response = await fetch(`${API_BASE}/optimization/studies/${studyId}/history`); if (!response.ok) throw new Error('Failed to fetch study history'); return response.json(); } async getStudyPruning(studyId: string): Promise { const response = await fetch(`${API_BASE}/optimization/studies/${studyId}/pruning`); if (!response.ok) throw new Error('Failed to fetch pruning data'); return response.json(); } async createStudy(config: any): Promise<{ study_id: string }> { const response = await fetch(`${API_BASE}/optimization/studies`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(config), }); if (!response.ok) throw new Error('Failed to create study'); return response.json(); } async getStudyReport(studyId: string): Promise { const response = await fetch(`${API_BASE}/optimization/studies/${studyId}/report`); if (!response.ok) throw new Error('Failed to fetch report'); return response.json(); } async getStudyReadme(studyId: string): Promise { const response = await fetch(`${API_BASE}/optimization/studies/${studyId}/readme`); if (!response.ok) throw new Error('Failed to fetch README'); return response.json(); } async getStudyConfig(studyId: string): Promise { const response = await fetch(`${API_BASE}/optimization/studies/${studyId}/config`); if (!response.ok) throw new Error('Failed to fetch config'); return response.json(); } async getConsoleOutput(studyId: string, lines: number = 200): Promise<{ lines: string[]; total_lines: number; displayed_lines: number; log_file: string | null; timestamp: string; message?: string; }> { const response = await fetch(`${API_BASE}/optimization/studies/${studyId}/console?lines=${lines}`); if (!response.ok) throw new Error('Failed to fetch console output'); return response.json(); } async getProcessStatus(studyId: string): Promise { const response = await fetch(`${API_BASE}/optimization/studies/${studyId}/process`); if (!response.ok) throw new Error('Failed to fetch process status'); return response.json(); } // Control operations async startOptimization(studyId: string, options?: { freshStart?: boolean; maxIterations?: number; trials?: number; // For SAT scripts feaBatchSize?: number; tuneTrials?: number; ensembleSize?: number; patience?: number; }): Promise { const response = await fetch(`${API_BASE}/optimization/studies/${studyId}/start`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(options || {}), }); if (!response.ok) { const error = await response.json(); throw new Error(error.detail || 'Failed to start optimization'); } return response.json(); } async stopOptimization(studyId: string): Promise { const response = await fetch(`${API_BASE}/optimization/studies/${studyId}/stop`, { method: 'POST', }); if (!response.ok) { const error = await response.json(); throw new Error(error.detail || 'Failed to stop optimization'); } return response.json(); } async pauseOptimization(studyId: string): Promise { const response = await fetch(`${API_BASE}/optimization/studies/${studyId}/pause`, { method: 'POST', }); if (!response.ok) { const error = await response.json(); throw new Error(error.detail || 'Failed to pause optimization'); } return response.json(); } async resumeOptimization(studyId: string): Promise { const response = await fetch(`${API_BASE}/optimization/studies/${studyId}/resume`, { method: 'POST', }); if (!response.ok) { const error = await response.json(); throw new Error(error.detail || 'Failed to resume optimization'); } return response.json(); } async validateOptimization(studyId: string, options?: { topN?: number; }): Promise { const response = await fetch(`${API_BASE}/optimization/studies/${studyId}/validate`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(options || {}), }); if (!response.ok) { const error = await response.json(); throw new Error(error.detail || 'Failed to start validation'); } return response.json(); } async generateReport(studyId: string): Promise { const response = await fetch(`${API_BASE}/optimization/studies/${studyId}/report/generate`, { method: 'POST', }); if (!response.ok) { const error = await response.json(); throw new Error(error.detail || 'Failed to generate report'); } return response.json(); } // Optuna dashboard async launchOptunaDashboard(studyId: string): Promise<{ url: string; pid: number }> { const response = await fetch(`${API_BASE}/optimization/studies/${studyId}/optuna-dashboard`, { method: 'POST', }); if (!response.ok) { const error = await response.json(); throw new Error(error.detail || 'Failed to launch Optuna dashboard'); } return response.json(); } async checkOptunaAvailable(): Promise<{ available: boolean; path: string | null; message: string; install_instructions?: string; }> { const response = await fetch(`${API_BASE}/optimization/optuna-dashboard/check`); if (!response.ok) { return { available: false, path: null, message: 'Failed to check optuna-dashboard availability', install_instructions: 'pip install optuna-dashboard' }; } return response.json(); } // Optimizer state async getOptimizerState(studyId: string): Promise<{ available: boolean; source?: string; phase?: string; phase_description?: string; phase_progress?: number; current_strategy?: string; sampler?: { name: string; description: string; }; objectives?: Array<{ name: string; direction: string; current_best?: number; unit?: string; }>; plan?: { total_phases: number; current_phase: number; phases: string[]; }; completed_trials?: number; total_trials?: number; }> { const response = await fetch(`${API_BASE}/optimization/studies/${studyId}/optimizer-state`); if (!response.ok) { return { available: false }; } return response.json(); } // Model files async getModelFiles(studyId: string): Promise { const response = await fetch(`${API_BASE}/optimization/studies/${studyId}/model-files`); if (!response.ok) throw new Error('Failed to fetch model files'); return response.json(); } async openFolder(studyId: string, folderType: 'model' | 'results' | 'setup' = 'model'): Promise<{ success: boolean; message: string; path: string }> { const response = await fetch(`${API_BASE}/optimization/studies/${studyId}/open-folder?folder_type=${folderType}`, { method: 'POST', }); if (!response.ok) { const error = await response.json(); throw new Error(error.detail || 'Failed to open folder'); } return response.json(); } async getBestSolution(studyId: string): Promise<{ study_id: string; best_trial: { trial_number: number; objective: number; design_variables: Record; user_attrs?: Record; timestamp?: string; } | null; first_trial: { trial_number: number; objective: number; design_variables: Record; } | null; improvements: Record; total_trials: number; }> { const response = await fetch(`${API_BASE}/optimization/studies/${studyId}/best-solution`); if (!response.ok) throw new Error('Failed to fetch best solution'); return response.json(); } async exportData(studyId: string, format: 'csv' | 'json' | 'config'): Promise<{ filename?: string; content: string; content_type?: string; study_id?: string; total_trials?: number; trials?: any[]; }> { const response = await fetch(`${API_BASE}/optimization/studies/${studyId}/export/${format}`); if (!response.ok) throw new Error(`Failed to export ${format}`); return response.json(); } // NX Model introspection async introspectNxModel(studyId: string, force: boolean = false): Promise<{ study_id: string; cached: boolean; introspection: { success: boolean; part_file: string; expressions: { user: Array<{ name: string; value: number; units?: string; formula?: string; }>; internal: any[]; user_count: number; total_count: number; }; mass_properties: { mass_kg: number; mass_g: number; volume_mm3: number; surface_area_mm2: number; center_of_gravity_mm: [number, number, number]; }; }; }> { const url = force ? `${API_BASE}/optimization/studies/${studyId}/nx/introspect?force=true` : `${API_BASE}/optimization/studies/${studyId}/nx/introspect`; const response = await fetch(url); if (!response.ok) throw new Error('Failed to introspect NX model'); return response.json(); } async getNxExpressions(studyId: string): Promise<{ study_id: string; expressions: Array<{ name: string; value: number; units?: string; formula?: string; }>; count: number; }> { const response = await fetch(`${API_BASE}/optimization/studies/${studyId}/nx/expressions`); if (!response.ok) throw new Error('Failed to get NX expressions'); return response.json(); } } export const apiClient = new ApiClient();