import type { AgentThread, Message } from "./types"; export type { AgentThread, Message }; export interface ThreadCreateRequest { prompt: string; repo?: string | null; model_id?: string | null; effort?: string | null; } export interface ThreadMessageRequest { content: string; model_id?: string | null; effort?: string | null; } const API_BASE = (import.meta.env.VITE_DASHBOARD_API_BASE_URL ?? "").replace(/\/$/, ""); async function agentsRequest(path: string, init: RequestInit = {}): Promise { const res = await fetch(`${API_BASE}/dashboard/api${path}`, { ...init, credentials: "include", headers: { "Content-Type": "application/json", ...(init.headers ?? {}), }, }); if (!res.ok) { let message = res.statusText; try { const body = await res.json(); if (body?.detail) { message = typeof body.detail === "string" ? body.detail : JSON.stringify(body.detail); } } catch { /* ignore */ } throw new Error(message); } if (res.status === 204) return undefined as T; return (await res.json()) as T; } export const agentsApi = { listThreads: () => agentsRequest("/threads"), getThread: (threadId: string) => agentsRequest(`/threads/${encodeURIComponent(threadId)}`), createThread: (body: ThreadCreateRequest) => agentsRequest("/threads", { method: "POST", body: JSON.stringify(body), }), sendMessage: (threadId: string, body: ThreadMessageRequest) => agentsRequest(`/threads/${encodeURIComponent(threadId)}/messages`, { method: "POST", body: JSON.stringify(body), }), cancelThread: (threadId: string) => agentsRequest(`/threads/${encodeURIComponent(threadId)}/cancel`, { method: "POST", }), deleteThread: (threadId: string) => agentsRequest(`/threads/${encodeURIComponent(threadId)}`, { method: "DELETE", }), streamUrl: (threadId: string) => `${API_BASE}/dashboard/api/threads/${encodeURIComponent(threadId)}/stream`, }; export function formatRelativeTime(ts: number): string { const diff = Date.now() - ts; const mins = Math.floor(diff / 60000); if (mins < 60) return `${mins}m`; const hours = Math.floor(mins / 60); if (hours < 24) return `${hours}h`; const days = Math.floor(hours / 24); if (days < 7) return `${days}d`; const weeks = Math.floor(days / 7); return `${weeks}w`; } export type ThreadGroup = "today" | "last30" | "older"; export function groupThreads(threads: AgentThread[]): Record { const todayStart = new Date(); todayStart.setHours(0, 0, 0, 0); const thirtyDaysAgo = Date.now() - 30 * 24 * 60 * 60 * 1000; const groups: Record = { today: [], last30: [], older: [], }; for (const thread of [...threads].sort((a, b) => b.updatedAt - a.updatedAt)) { if (thread.updatedAt >= todayStart.getTime()) { groups.today.push(thread); } else if (thread.updatedAt >= thirtyDaysAgo) { groups.last30.push(thread); } else { groups.older.push(thread); } } return groups; }