import api from "./client"; import type { Agent, StackDetail, StackStats, StackSummary } from "@/types"; export type RemoteStackSummary = StackSummary & { agent_id: number; agent_name: string }; export type RemoteStackDetail = StackDetail & { agent_id: number; agent_name: string }; export interface AgentSystem { hostname: string; docker_version: string; host_os: string; cpu_cores: number; mem_total: number; mem_used: number; disk_total: number; disk_used: number; containers_running: number; containers_total: number; compose_running?: number; // agents < 0.31.1 don't report it } export const agentsApi = { list: (refresh = true) => api.get(`/api/agents?refresh=${refresh}`).then((r) => r.data), create: (body: { name: string; url: string; token: string }) => api.post("/api/agents", body).then((r) => r.data), update: (id: number, body: { name?: string; url?: string; token?: string }) => api.put(`/api/agents/${id}`, body).then((r) => r.data), remove: (id: number) => api.delete(`/api/agents/${id}`).then((r) => r.data), ping: (id: number) => api.post<{ status: string; hostname?: string }>(`/api/agents/${id}/ping`).then((r) => r.data), system: (id: number) => api.get(`/api/agents/${id}/system`).then((r) => r.data), stacks: (id: number) => api.get(`/api/agents/${id}/stacks`).then((r) => r.data), stackStats: (id: number) => api.get>(`/api/agents/${id}/stacks/stats`).then((r) => r.data), createStack: (id: number, body: { name: string; yaml: string; env?: string }) => api .post<{ id: string; name: string }>(`/api/agents/${id}/stacks`, body) .then((r) => r.data), stack: (id: number, stackId: string) => api.get(`/api/agents/${id}/stacks/${stackId}`).then((r) => r.data), logs: (id: number, stackId: string, tail = 200) => api .get<{ logs: string }>(`/api/agents/${id}/stacks/${stackId}/logs?tail=${tail}`) .then((r) => r.data), update_stack: (id: number, stackId: string, body: { yaml?: string; env?: string }) => api.put(`/api/agents/${id}/stacks/${stackId}`, body).then((r) => r.data), action: (id: number, stackId: string, action: string) => api.post(`/api/agents/${id}/stacks/${stackId}/${action}`).then((r) => r.data), backupDownload: async ( id: number, stackId: string, opts: { includeVolumes: boolean; stopFirst: boolean } ) => { const res = await api.get(`/api/agents/${id}/stacks/${stackId}/backup`, { params: { include_volumes: opts.includeVolumes, stop_first: opts.stopFirst }, responseType: "blob", }); const cd = res.headers["content-disposition"] as string | undefined; const name = cd?.match(/filename="?([^"]+)"?/)?.[1] ?? `backup-${stackId}.tar.gz`; const url = URL.createObjectURL(res.data as Blob); const a = document.createElement("a"); a.href = url; a.download = name; document.body.appendChild(a); a.click(); a.remove(); URL.revokeObjectURL(url); }, backupPush: ( id: number, stackId: string, body: { destination_id: number; include_volumes: boolean; stop_first: boolean } ) => api .post<{ ok: boolean; destination: string; name: string }>( `/api/agents/${id}/stacks/${stackId}/backup/push`, body ) .then((r) => r.data), restoreUpload: ( id: number, file: File, opts: { targetId?: string; overwrite: boolean; restoreVolumes: boolean } ) => { const form = new FormData(); form.append("file", file); if (opts.targetId) form.append("target_id", opts.targetId); form.append("overwrite", String(opts.overwrite)); form.append("restore_volumes", String(opts.restoreVolumes)); return api .post<{ stack_id: string; name: string; volumes_restored: number }>( `/api/agents/${id}/stacks/restore`, form ) .then((r) => r.data); }, restoreFrom: ( id: number, body: { destination_id: number; name: string; target_id?: string; overwrite: boolean; restore_volumes: boolean; } ) => api .post<{ stack_id: string; name: string; volumes_restored: number }>( `/api/agents/${id}/stacks/restore-from`, body ) .then((r) => r.data), };