/** * API client for the Foxy Dev Team backend. */ const BASE_URL = ''; // ─── Types ────────────────────────────────────────────────────────────────── export interface Project { id: number; name: string; slug: string; description: string; status: string; workflow_type: string; project_type: string; test_mode: boolean; install_path?: string; gitea_repo?: string; deployment_target?: string; deploy_server_id?: number; git_server_id?: number; deploy_server_name?: string; git_server_name?: string; created_at: string; updated_at: string; tasks: Task[]; audit_logs: AuditLog[]; agent_executions: AgentExecution[]; } export interface ProjectSummary { id: number; name: string; slug: string; status: string; workflow_type: string; project_type: string; test_mode: boolean; install_path?: string; task_count: number; tasks_done: number; deploy_server_name?: string; git_server_name?: string; created_at: string; updated_at: string; } export interface Task { id: number; project_id: number; task_id: string; type: string; title: string; priority: string; assigned_to?: string; status: string; dependencies: string[]; acceptance_criteria?: string; agent_payloads: Record; created_at: string; updated_at: string; } export interface AuditLog { id: number; project_id: number; timestamp: string; agent: string; action: string; target?: string; message?: string; source: string; } export interface AgentExecution { id: number; project_id: number; agent_name: string; status: string; pid?: number; started_at: string; finished_at?: string; exit_code?: number; error_output?: string; } export interface AgentStatus { name: string; display_name: string; model: string; current_status: string; current_project?: string; total_executions: number; success_count: number; failure_count: number; } export interface WorkflowDef { type: string; label: string; path: string; steps: { agent: string; label: string; model: string; awaiting_status: string; running_status: string; }[]; } export interface ProjectTypeInfo { value: string; emoji: string; label: string; description: string; } export interface DeployServer { id: number; name: string; host: string; user: string; ssh_port: number; description: string; created_at: string; } export interface GitServer { id: number; name: string; url: string; org: string; description: string; created_at: string; } export interface AppConfig { OPENCLAW_WORKSPACE: string; GITEA_SERVER: string; DEPLOYMENT_SERVER: string; DEPLOYMENT_USER: string; TELEGRAM_CHAT_ID: string; LOG_LEVEL: string; GITEA_OPENCLAW_TOKEN: string; DEPLOYMENT_PWD: string; TELEGRAM_BOT_TOKEN: string; } // ─── HTTP Helpers ─────────────────────────────────────────────────────────── async function request(path: string, options?: RequestInit): Promise { const res = await fetch(`${BASE_URL}${path}`, { ...options, headers: { 'Content-Type': 'application/json', ...options?.headers, }, }); if (!res.ok) { const err = await res.json().catch(() => ({ detail: res.statusText })); throw new Error(err.detail || `HTTP ${res.status}`); } return res.json(); } // ─── API ──────────────────────────────────────────────────────────────────── export const api = { // Projects listProjects: (params?: Record) => { const qs = params ? '?' + new URLSearchParams(params).toString() : ''; return request(`/api/projects${qs}`); }, getProject: (id: number) => request(`/api/projects/${id}`), createProject: (data: { name: string; description: string; workflow_type: string; project_type: string; test_mode?: boolean; install_path?: string; deploy_server_id?: number | null; git_server_id?: number | null; }) => request('/api/projects', { method: 'POST', body: JSON.stringify(data) }), startProject: (id: number) => request<{ status: string }>(`/api/projects/${id}/start`, { method: 'POST' }), pauseProject: (id: number) => request<{ status: string }>(`/api/projects/${id}/pause`, { method: 'POST' }), stopProject: (id: number) => request<{ status: string }>(`/api/projects/${id}/stop`, { method: 'POST' }), resetProject: (id: number) => request<{ status: string }>(`/api/projects/${id}/reset`, { method: 'POST' }), deleteProject: (id: number) => request<{ message: string }>(`/api/projects/${id}`, { method: 'DELETE' }), getProgress: (id: number) => request<{ current_step: number; total_steps: number; percentage: number }>(`/api/projects/${id}/progress`), // Project Types listProjectTypes: () => request('/api/projects/types'), // Agents listAgents: () => request('/api/agents'), getAgentHistory: (name: string) => request(`/api/agents/${name}/history`), // Logs listLogs: (params?: Record) => { const qs = params ? '?' + new URLSearchParams(params).toString() : ''; return request(`/api/logs${qs}`); }, // Workflows listWorkflows: () => request('/api/workflows'), // Config getConfig: () => request('/api/config'), updateConfig: (data: Record) => request<{ message: string }>('/api/config', { method: 'PUT', body: JSON.stringify(data) }), // Deploy Servers listDeployServers: () => request('/api/config/deploy-servers'), createDeployServer: (data: { name: string; host: string; user?: string; password?: string; ssh_port?: number; description?: string }) => request('/api/config/deploy-servers', { method: 'POST', body: JSON.stringify(data) }), deleteDeployServer: (id: number) => request<{ message: string }>(`/api/config/deploy-servers/${id}`, { method: 'DELETE' }), // Git Servers listGitServers: () => request('/api/config/git-servers'), createGitServer: (data: { name: string; url: string; token?: string; org?: string; description?: string }) => request('/api/config/git-servers', { method: 'POST', body: JSON.stringify(data) }), deleteGitServer: (id: number) => request<{ message: string }>(`/api/config/git-servers/${id}`, { method: 'DELETE' }), // Health health: () => request<{ status: string; version: string }>('/api/health'), };