import { IS_PLATFORM } from "../constants/config"; // Utility function for authenticated API calls export const authenticatedFetch = (url, options = {}) => { const token = localStorage.getItem('auth-token'); const defaultHeaders = {}; // Only set Content-Type for non-FormData requests if (!(options.body instanceof FormData)) { defaultHeaders['Content-Type'] = 'application/json'; } if (!IS_PLATFORM && token) { defaultHeaders['Authorization'] = `Bearer ${token}`; } return fetch(url, { ...options, headers: { ...defaultHeaders, ...options.headers, }, }).then((response) => { const refreshedToken = response.headers.get('X-Refreshed-Token'); if (refreshedToken) { localStorage.setItem('auth-token', refreshedToken); } return response; }); }; // API endpoints export const api = { // Auth endpoints (no token required) auth: { status: () => fetch('/api/auth/status'), login: (username, password) => fetch('/api/auth/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username, password }), }), register: (username, password) => fetch('/api/auth/register', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username, password }), }), user: () => authenticatedFetch('/api/auth/user'), logout: () => authenticatedFetch('/api/auth/logout', { method: 'POST' }), }, // Protected endpoints // config endpoint removed - no longer needed (frontend uses window.location) projects: () => authenticatedFetch('/api/projects'), sessions: (projectName, limit = 5, offset = 0) => authenticatedFetch(`/api/projects/${projectName}/sessions?limit=${limit}&offset=${offset}`), // Unified endpoint — all providers through one URL unifiedSessionMessages: (sessionId, provider = 'claude', { projectName = '', projectPath = '', limit = null, offset = 0 } = {}) => { const params = new URLSearchParams(); params.append('provider', provider); if (projectName) params.append('projectName', projectName); if (projectPath) params.append('projectPath', projectPath); if (limit !== null) { params.append('limit', String(limit)); params.append('offset', String(offset)); } const queryString = params.toString(); return authenticatedFetch(`/api/sessions/${encodeURIComponent(sessionId)}/messages${queryString ? `?${queryString}` : ''}`); }, renameProject: (projectName, displayName) => authenticatedFetch(`/api/projects/${projectName}/rename`, { method: 'PUT', body: JSON.stringify({ displayName }), }), deleteSession: (projectName, sessionId) => authenticatedFetch(`/api/projects/${projectName}/sessions/${sessionId}`, { method: 'DELETE', }), renameSession: (sessionId, summary, provider) => authenticatedFetch(`/api/sessions/${sessionId}/rename`, { method: 'PUT', body: JSON.stringify({ summary, provider }), }), deleteCodexSession: (sessionId) => authenticatedFetch(`/api/codex/sessions/${sessionId}`, { method: 'DELETE', }), deleteGeminiSession: (sessionId) => authenticatedFetch(`/api/gemini/sessions/${sessionId}`, { method: 'DELETE', }), deleteProject: (projectName, force = false, deleteData = false) => { const params = new URLSearchParams(); if (force) params.set('force', 'true'); if (deleteData) params.set('deleteData', 'true'); const qs = params.toString(); return authenticatedFetch(`/api/projects/${projectName}${qs ? `?${qs}` : ''}`, { method: 'DELETE', }); }, searchConversationsUrl: (query, limit = 50) => { const token = localStorage.getItem('auth-token'); const params = new URLSearchParams({ q: query, limit: String(limit) }); if (token) params.set('token', token); return `/api/search/conversations?${params.toString()}`; }, createWorkspace: (workspaceData) => authenticatedFetch('/api/projects/create-workspace', { method: 'POST', body: JSON.stringify(workspaceData), }), readFile: (projectName, filePath) => authenticatedFetch(`/api/projects/${projectName}/file?filePath=${encodeURIComponent(filePath)}`), readFileBlob: (projectName, filePath) => authenticatedFetch(`/api/projects/${projectName}/files/content?path=${encodeURIComponent(filePath)}`), saveFile: (projectName, filePath, content) => authenticatedFetch(`/api/projects/${projectName}/file`, { method: 'PUT', body: JSON.stringify({ filePath, content }), }), getFiles: (projectName, options = {}) => authenticatedFetch(`/api/projects/${projectName}/files`, options), // File operations createFile: (projectName, { path, type, name }) => authenticatedFetch(`/api/projects/${projectName}/files/create`, { method: 'POST', body: JSON.stringify({ path, type, name }), }), renameFile: (projectName, { oldPath, newName }) => authenticatedFetch(`/api/projects/${projectName}/files/rename`, { method: 'PUT', body: JSON.stringify({ oldPath, newName }), }), deleteFile: (projectName, { path, type }) => authenticatedFetch(`/api/projects/${projectName}/files`, { method: 'DELETE', body: JSON.stringify({ path, type }), }), uploadFiles: (projectName, formData) => authenticatedFetch(`/api/projects/${projectName}/files/upload`, { method: 'POST', body: formData, headers: {}, // Let browser set Content-Type for FormData }), // TaskMaster endpoints taskmaster: { // Initialize TaskMaster in a project init: (projectName) => authenticatedFetch(`/api/taskmaster/init/${projectName}`, { method: 'POST', }), // Add a new task addTask: (projectName, { prompt, title, description, priority, dependencies }) => authenticatedFetch(`/api/taskmaster/add-task/${projectName}`, { method: 'POST', body: JSON.stringify({ prompt, title, description, priority, dependencies }), }), // Parse PRD to generate tasks parsePRD: (projectName, { fileName, numTasks, append }) => authenticatedFetch(`/api/taskmaster/parse-prd/${projectName}`, { method: 'POST', body: JSON.stringify({ fileName, numTasks, append }), }), // Get available PRD templates getTemplates: () => authenticatedFetch('/api/taskmaster/prd-templates'), // Apply a PRD template applyTemplate: (projectName, { templateId, fileName, customizations }) => authenticatedFetch(`/api/taskmaster/apply-template/${projectName}`, { method: 'POST', body: JSON.stringify({ templateId, fileName, customizations }), }), // Update a task updateTask: (projectName, taskId, updates) => authenticatedFetch(`/api/taskmaster/update-task/${projectName}/${taskId}`, { method: 'PUT', body: JSON.stringify(updates), }), }, // Browse filesystem for project suggestions browseFilesystem: (dirPath = null) => { const params = new URLSearchParams(); if (dirPath) params.append('path', dirPath); return authenticatedFetch(`/api/browse-filesystem?${params}`); }, createFolder: (folderPath) => authenticatedFetch('/api/create-folder', { method: 'POST', body: JSON.stringify({ path: folderPath }), }), // User endpoints user: { gitConfig: () => authenticatedFetch('/api/user/git-config'), updateGitConfig: (gitName, gitEmail) => authenticatedFetch('/api/user/git-config', { method: 'POST', body: JSON.stringify({ gitName, gitEmail }), }), onboardingStatus: () => authenticatedFetch('/api/user/onboarding-status'), completeOnboarding: () => authenticatedFetch('/api/user/complete-onboarding', { method: 'POST', }), }, // Generic GET method for any endpoint get: (endpoint) => authenticatedFetch(`/api${endpoint}`), // Generic POST method for any endpoint post: (endpoint, body) => authenticatedFetch(`/api${endpoint}`, { method: 'POST', ...(body instanceof FormData ? { body } : { body: JSON.stringify(body) }), }), // Generic PUT method for any endpoint put: (endpoint, body) => authenticatedFetch(`/api${endpoint}`, { method: 'PUT', body: JSON.stringify(body), }), // Generic DELETE method for any endpoint delete: (endpoint, options = {}) => authenticatedFetch(`/api${endpoint}`, { method: 'DELETE', ...options, }), };