import { AxiosError } from "axios"; import { apiClient } from "./client"; export interface ToolInstance { id: string; name: string; display_name: string; tool_type_id: string; tool_type_name: string; tool_type_interfaces: string[]; status: string; url: string | null; port: number | null; selected_config_profile_id: string | null; ssh_key_ids: string[]; created_at: string; } export interface Session { id: string; display_name: string; tool_type_name: string; tool_icon: string; tool_type_interfaces: string[]; repository_name: string; repository_id: string; project_name: string; project_id: string; workspace_name?: string | null; status: string; url: string | null; container_status?: string; probe_status?: string; created_at?: string; } export async function listInstances( projectId: string, repoId: string, ): Promise { const response = await apiClient.get( `/projects/${projectId}/repositories/${repoId}/instances`, ); return response.data.instances; } export async function createInstance( projectId: string, repoId: string, toolTypeId: string, displayName?: string, workspaceId?: string, configProfileId?: string, sshKeyIds?: string[], ): Promise { const response = await apiClient.post( `/projects/${projectId}/repositories/${repoId}/instances`, { tool_type_id: toolTypeId, display_name: displayName, workspace_id: workspaceId || undefined, config_profile_id: configProfileId, ssh_key_ids: sshKeyIds || [], }, ); return response.data; } export async function startInstance( projectId: string, repoId: string, instanceId: string, configProfileId?: string, sshKeyIds?: string[], retries = 2, ): Promise<{ status: string; url?: string }> { try { const response = await apiClient.post( `/projects/${projectId}/repositories/${repoId}/instances/${instanceId}/start`, { config_profile_id: configProfileId, ssh_key_ids: sshKeyIds || [] }, ); return response.data; } catch (error) { // Retry on network errors (e.g. Docker creating network interfaces) const axiosError = error as AxiosError; if (retries > 0 && !axiosError.response) { await new Promise((r) => setTimeout(r, 1500)); return startInstance( projectId, repoId, instanceId, configProfileId, sshKeyIds, retries - 1, ); } throw error; } } export async function stopInstance( projectId: string, repoId: string, instanceId: string, ): Promise<{ status: string }> { const response = await apiClient.post( `/projects/${projectId}/repositories/${repoId}/instances/${instanceId}/stop`, ); return response.data; } export async function restartInstance( projectId: string, repoId: string, instanceId: string, configProfileId?: string, sshKeyIds?: string[], retries = 2, ): Promise<{ status: string; url?: string }> { try { const response = await apiClient.post( `/projects/${projectId}/repositories/${repoId}/instances/${instanceId}/restart`, { config_profile_id: configProfileId, ssh_key_ids: sshKeyIds || [] }, ); return response.data; } catch (error) { // Retry on network errors (e.g. Docker creating network interfaces) const axiosError = error as AxiosError; if (retries > 0 && !axiosError.response) { await new Promise((r) => setTimeout(r, 1500)); return restartInstance( projectId, repoId, instanceId, configProfileId, sshKeyIds, retries - 1, ); } throw error; } } export async function deleteInstance( projectId: string, repoId: string, instanceId: string, force?: boolean, ): Promise { await apiClient.delete( `/projects/${projectId}/repositories/${repoId}/instances/${instanceId}`, { params: { force } }, ); } export async function getInstance( projectId: string, repoId: string, instanceId: string, ): Promise { const response = await apiClient.get( `/projects/${projectId}/repositories/${repoId}/instances/${instanceId}`, ); return response.data; } export async function getUserSessions(): Promise { const response = await apiClient.get("/users/me/sessions"); return response.data.sessions; } export interface InstanceHealth { healthy: boolean; container_status: string; container_health: string | null; container_exit_code: number | null; tunnel_status: string; tunnel_status_code: number | null; probe_status: string; last_probe_output: string | null; error: string | null; } export async function checkInstanceHealth( projectId: string, repoId: string, instanceId: string, ): Promise { const response = await apiClient.get( `/projects/${projectId}/repositories/${repoId}/instances/${instanceId}/health`, ); return response.data; } export async function renameInstance( projectId: string, repoId: string, instanceId: string, displayName: string, ): Promise<{ id: string; name: string; display_name: string }> { const response = await apiClient.patch( `/projects/${projectId}/repositories/${repoId}/instances/${instanceId}`, { display_name: displayName }, ); return response.data; } export async function recreateInstanceTunnel( projectId: string, repoId: string, instanceId: string, ): Promise<{ status: string; url?: string }> { const response = await apiClient.post( `/projects/${projectId}/repositories/${repoId}/instances/${instanceId}/recreate-tunnel`, ); return response.data; }