| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| (function() { |
| 'use strict'; |
|
|
| |
| const API_BASE = window.location.origin; |
|
|
| |
| |
| |
| async function apiCall(endpoint, data = null) { |
| const url = `${API_BASE}/api/${endpoint}`; |
|
|
| const options = { |
| method: data ? 'POST' : 'GET', |
| headers: { |
| 'Content-Type': 'application/json', |
| } |
| }; |
|
|
| if (data) { |
| options.body = JSON.stringify(data); |
| } |
|
|
| try { |
| const response = await fetch(url, options); |
|
|
| if (!response.ok) { |
| throw new Error(`HTTP error! status: ${response.status}`); |
| } |
|
|
| const result = await response.json(); |
| return result; |
| } catch (error) { |
| console.error(`API call failed: ${endpoint}`, error); |
| throw error; |
| } |
| } |
|
|
| |
| |
| |
| window.pywebview = { |
| api: { |
| |
|
|
| generate_simplex_points: async function(n, d, k, seed) { |
| return await apiCall('generate_simplex_points', { n, d, k, seed }); |
| }, |
|
|
| save_synthetic_dataset: async function(points) { |
| return await apiCall('save_synthetic_dataset', { points }); |
| }, |
|
|
| |
|
|
| load_mnist: async function(max_samples, subset) { |
| return await apiCall('load_mnist', { max_samples, subset }); |
| }, |
|
|
| |
|
|
| upload_csv: async function(name, content, delimiter) { |
| return await apiCall('upload_csv', { name, content, delimiter }); |
| }, |
|
|
| upload_images: async function(files) { |
| return await apiCall('upload_images', { files }); |
| }, |
|
|
| list_datasets: async function() { |
| return await apiCall('list_datasets'); |
| }, |
|
|
| prepare_csv_dataset: async function(dataset_id, selected_columns, handle_missing) { |
| return await apiCall('prepare_csv_dataset', { |
| dataset_id, |
| selected_columns, |
| handle_missing |
| }); |
| }, |
|
|
| |
|
|
| compute_embeddings: async function(dataset_id, method) { |
| return await apiCall('compute_embeddings', { dataset_id, method }); |
| }, |
|
|
| |
|
|
| run_tsne: async function(dataset_id, perplexity, learning_rate, n_iter, |
| early_exaggeration, momentum, init_method, init_data, seed) { |
| return await apiCall('run_tsne', { |
| dataset_id, |
| perplexity, |
| learning_rate, |
| n_iter, |
| early_exaggeration, |
| momentum, |
| init_method, |
| init_data, |
| seed |
| }); |
| }, |
|
|
| stop_tsne: async function() { |
| |
| return { success: true }; |
| }, |
|
|
| |
|
|
| run_clustering: async function(dataset_id, method, k, eps, min_samples) { |
| return await apiCall('run_clustering', { |
| dataset_id, |
| method, |
| k, |
| eps, |
| min_samples |
| }); |
| }, |
|
|
| |
|
|
| export_results: async function(dataset_id) { |
| return await apiCall('export_results', { dataset_id }); |
| }, |
|
|
| get_image_at_index: async function(dataset_id, index) { |
| return await apiCall('get_image_at_index', { dataset_id, index }); |
| } |
| }, |
|
|
| |
|
|
| |
| |
| |
| isFlaskMode: function() { |
| return true; |
| }, |
|
|
| |
| |
| |
| checkMCPStatus: async function() { |
| try { |
| const status = await apiCall('mcp_status'); |
| return status; |
| } catch (error) { |
| return { connected: false, available: false }; |
| } |
| } |
| }; |
|
|
| |
|
|
| |
| |
| |
| |
| let progressInterval = null; |
|
|
| window.startProgressPolling = function() { |
| if (progressInterval) { |
| clearInterval(progressInterval); |
| } |
|
|
| |
| progressInterval = setInterval(async () => { |
| try { |
| const progress = await apiCall('tsne_progress'); |
| if (progress && progress.current !== undefined) { |
| window.updateProgress(progress.current, progress.total, progress.message); |
|
|
| |
| if (progress.current >= progress.total) { |
| clearInterval(progressInterval); |
| progressInterval = null; |
| } |
| } |
| } catch (error) { |
| |
| } |
| }, 500); |
| }; |
|
|
| window.stopProgressPolling = function() { |
| if (progressInterval) { |
| clearInterval(progressInterval); |
| progressInterval = null; |
| } |
| }; |
|
|
| |
|
|
| |
| |
| |
| async function showConnectionStatus() { |
| try { |
| const health = await apiCall('health'); |
| const statusDiv = document.createElement('div'); |
| statusDiv.id = 'connection-status'; |
| statusDiv.style.cssText = ` |
| position: fixed; |
| top: 10px; |
| right: 10px; |
| padding: 8px 12px; |
| background: ${health.mcp_connected ? '#10b981' : '#f59e0b'}; |
| color: white; |
| border-radius: 6px; |
| font-size: 0.85em; |
| font-weight: 600; |
| z-index: 9999; |
| box-shadow: 0 2px 8px rgba(0,0,0,0.2); |
| `; |
| statusDiv.innerHTML = health.mcp_connected |
| ? '🟢 MCP Connected' |
| : '🟡 Local Mode'; |
|
|
| document.body.appendChild(statusDiv); |
|
|
| |
| statusDiv.title = health.mcp_connected |
| ? 'Connected to MCP server for heavy computations' |
| : 'Using local fallback (computations may be slower)'; |
|
|
| } catch (error) { |
| console.error('Failed to check connection status:', error); |
| } |
| } |
|
|
| |
|
|
| |
| |
| |
| function initAdapter() { |
| console.log('Flask API Adapter initialized'); |
| console.log(`API Base URL: ${API_BASE}`); |
|
|
| |
| showConnectionStatus(); |
|
|
| |
| window.dispatchEvent(new Event('pywebviewready')); |
| } |
|
|
| |
| if (document.readyState === 'loading') { |
| document.addEventListener('DOMContentLoaded', initAdapter); |
| } else { |
| initAdapter(); |
| } |
|
|
| |
|
|
| |
| |
| |
| window.downloadFile = function(content, filename, type) { |
| const blob = new Blob([content], { type: type }); |
| const url = URL.createObjectURL(blob); |
| const a = document.createElement('a'); |
| a.href = url; |
| a.download = filename; |
| a.click(); |
| URL.revokeObjectURL(url); |
| }; |
|
|
| })(); |
|
|