feat: add auto update

This commit is contained in:
2026-05-19 15:53:30 +02:00
parent bd3121d688
commit ba4de62a34
22 changed files with 3323 additions and 110 deletions

View File

@ -122,6 +122,7 @@ export interface ImageEntry {
agent_id: string;
hostname: string;
alias: string;
ip_address: string;
id: string;
tags: string[];
size: number;
@ -132,6 +133,7 @@ export interface VolumeEntry {
agent_id: string;
hostname: string;
alias: string;
ip_address: string;
name: string;
driver: string;
mountpoint: string;
@ -141,6 +143,7 @@ export interface NetworkEntry {
agent_id: string;
hostname: string;
alias: string;
ip_address: string;
id: string;
name: string;
driver: string;
@ -201,6 +204,92 @@ export function connectLogs(
return () => ws.close();
}
export async function fsList(
agentId: string,
path: string
): Promise<{ name: string; is_dir: boolean; has_compose: boolean }[]> {
const r = await apiFetch(`${BASE}/agents/${agentId}/fs/list?path=${encodeURIComponent(path)}`);
if (!r.ok) throw new Error(`fsList: ${r.status}`);
return r.json();
}
export async function fsRead(agentId: string, path: string): Promise<string> {
const r = await apiFetch(`${BASE}/agents/${agentId}/fs/read?path=${encodeURIComponent(path)}`);
if (!r.ok) throw new Error(`fsRead: ${r.status}`);
const json = await r.json();
return json.content as string;
}
export async function fsWrite(agentId: string, path: string, content: string): Promise<void> {
const r = await apiFetch(`${BASE}/agents/${agentId}/fs/write`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ path, content }),
});
if (!r.ok) throw new Error(`fsWrite: ${r.status}`);
}
export async function fsMkdir(agentId: string, path: string): Promise<void> {
const r = await apiFetch(`/api/v1/agents/${agentId}/fs/mkdir`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ path }),
});
if (!r.ok) throw new Error(`mkdir: ${r.status}`);
}
export async function composeAction(
agentId: string,
path: string,
action: "up" | "down" | "pull"
): Promise<{ ok: boolean; output: string }> {
const r = await apiFetch(`${BASE}/agents/${agentId}/compose`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ path, action }),
});
if (!r.ok) throw new Error(`composeAction: ${r.status}`);
return r.json();
}
export interface AutoUpdatePolicy {
enabled: boolean;
interval_minutes: number;
last_checked_at: string | null;
last_updated_at: string | null;
}
export async function getAutoUpdatePolicy(agentId: string, containerId: string): Promise<AutoUpdatePolicy> {
const r = await apiFetch(`${BASE}/agents/${agentId}/containers/${containerId}/auto-update`);
if (!r.ok) throw new Error(`getAutoUpdatePolicy: ${r.status}`);
return r.json();
}
export async function setAutoUpdatePolicy(
agentId: string,
containerId: string,
policy: Pick<AutoUpdatePolicy, "enabled" | "interval_minutes">
): Promise<AutoUpdatePolicy> {
const r = await apiFetch(`${BASE}/agents/${agentId}/containers/${containerId}/auto-update`, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(policy),
});
if (!r.ok) throw new Error(`setAutoUpdatePolicy: ${r.status}`);
return r.json();
}
export async function updateNow(agentId: string, containerId: string): Promise<{ command_id: string }> {
const r = await apiFetch(`${BASE}/agents/${agentId}/containers/${containerId}/update-now`, {
method: "POST",
});
if (!r.ok) {
const text = await r.text().catch(() => "");
throw new Error(text || `updateNow: ${r.status}`);
}
return r.json();
}
export function connectEvents(
onEvent: (evt: { type: string; agent_id?: string; payload: unknown }) => void
): () => void {