Files
fusion/packages/dashboard/app/api.ts
Dustin Byrne c802108a02 refactor(HAI-116): rename kb to hai across all packages, CLI, and docs
- Rename npm packages from @kb/* to @hai/* and update all workspace references
- Rename CLI binary from kb to hai and config directory from .kb to .hai
- Update dashboard UI branding, titles, and references from kb to hai
- Update all test files, CI workflows, and documentation to reflect new naming
- Run comprehensive grep verification to ensure no stale kb references remain
2026-03-26 22:44:11 -04:00

154 lines
4.7 KiB
TypeScript

import type { Task, TaskDetail, TaskAttachment, TaskCreateInput, AgentLogEntry, Column, MergeResult, Settings } from "@kb/core";
async function api<T = unknown>(path: string, opts: RequestInit = {}): Promise<T> {
const res = await fetch(`/api${path}`, {
headers: { "Content-Type": "application/json" },
...opts,
});
const data = await res.json();
if (!res.ok) throw new Error((data as { error?: string }).error || "Request failed");
return data as T;
}
export function fetchTasks(): Promise<Task[]> {
return api<Task[]>("/tasks");
}
export async function fetchTaskDetail(id: string): Promise<TaskDetail> {
const maxAttempts = 2; // 1 initial + 1 retry
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
const res = await fetch(`/api/tasks/${id}`, {
headers: { "Content-Type": "application/json" },
});
const data = await res.json();
if (res.ok) return data as TaskDetail;
if (attempt === maxAttempts) {
throw new Error((data as { error?: string }).error || "Request failed");
}
}
// unreachable
throw new Error("Request failed");
}
export function createTask(input: TaskCreateInput): Promise<Task> {
return api<Task>("/tasks", {
method: "POST",
body: JSON.stringify(input),
});
}
export function updateTask(id: string, updates: { title?: string; description?: string; prompt?: string; dependencies?: string[] }): Promise<Task> {
return api<Task>(`/tasks/${id}`, {
method: "PATCH",
body: JSON.stringify(updates),
});
}
export function moveTask(id: string, column: Column): Promise<Task> {
return api<Task>(`/tasks/${id}/move`, {
method: "POST",
body: JSON.stringify({ column }),
});
}
export function deleteTask(id: string): Promise<Task> {
return api<Task>(`/tasks/${id}`, { method: "DELETE" });
}
export function mergeTask(id: string): Promise<MergeResult> {
return api<MergeResult>(`/tasks/${id}/merge`, { method: "POST" });
}
export function retryTask(id: string): Promise<Task> {
return api<Task>(`/tasks/${id}/retry`, { method: "POST" });
}
export function pauseTask(id: string): Promise<Task> {
return api<Task>(`/tasks/${id}/pause`, { method: "POST" });
}
export function unpauseTask(id: string): Promise<Task> {
return api<Task>(`/tasks/${id}/unpause`, { method: "POST" });
}
export function fetchConfig(): Promise<{ maxConcurrent: number }> {
return api<{ maxConcurrent: number }>("/config");
}
export function fetchSettings(): Promise<Settings> {
return api<Settings>("/settings");
}
export function updateSettings(settings: Partial<Settings>): Promise<Settings> {
return api<Settings>("/settings", {
method: "PUT",
body: JSON.stringify(settings),
});
}
export async function uploadAttachment(id: string, file: File): Promise<TaskAttachment> {
const formData = new FormData();
formData.append("file", file);
const res = await fetch(`/api/tasks/${id}/attachments`, {
method: "POST",
body: formData,
});
const data = await res.json();
if (!res.ok) throw new Error((data as { error?: string }).error || "Upload failed");
return data as TaskAttachment;
}
export async function deleteAttachment(id: string, filename: string): Promise<Task> {
return api<Task>(`/tasks/${id}/attachments/${filename}`, { method: "DELETE" });
}
export function fetchAgentLogs(taskId: string): Promise<AgentLogEntry[]> {
return api<AgentLogEntry[]>(`/tasks/${taskId}/logs`);
}
// --- Models API ---
/** Available AI model info returned by the models endpoint */
export interface ModelInfo {
provider: string;
id: string;
name: string;
reasoning: boolean;
contextWindow: number;
}
/** Fetch available AI models from the model registry */
export function fetchModels(): Promise<ModelInfo[]> {
return api<ModelInfo[]>("/models");
}
// --- Auth API ---
/** OAuth provider with current authentication status */
export interface AuthProvider {
id: string;
name: string;
authenticated: boolean;
}
/** Fetch authentication status for all OAuth providers */
export function fetchAuthStatus(): Promise<{ providers: AuthProvider[] }> {
return api<{ providers: AuthProvider[] }>("/auth/status");
}
/** Initiate OAuth login for a provider. Returns the auth URL to open in a new tab. */
export function loginProvider(provider: string): Promise<{ url: string; instructions?: string }> {
return api<{ url: string; instructions?: string }>("/auth/login", {
method: "POST",
body: JSON.stringify({ provider }),
});
}
/** Logout from a provider, removing stored credentials. */
export function logoutProvider(provider: string): Promise<{ success: boolean }> {
return api<{ success: boolean }>("/auth/logout", {
method: "POST",
body: JSON.stringify({ provider }),
});
}