102 lines
3.0 KiB
TypeScript
102 lines
3.0 KiB
TypeScript
|
|
import type {
|
||
|
|
PresentationData,
|
||
|
|
Agent,
|
||
|
|
Approval,
|
||
|
|
FeedEntry,
|
||
|
|
GpuStatus,
|
||
|
|
StatusData,
|
||
|
|
TerminalLine,
|
||
|
|
WorkloadData,
|
||
|
|
} from '../types'
|
||
|
|
|
||
|
|
async function fetchJson<T>(url: string, timeoutMs = 10000): Promise<T | null> {
|
||
|
|
const ctrl = new AbortController()
|
||
|
|
const timer = setTimeout(() => ctrl.abort(), timeoutMs)
|
||
|
|
try {
|
||
|
|
const r = await fetch(url, { signal: ctrl.signal })
|
||
|
|
if (!r.ok) return null
|
||
|
|
return (await r.json()) as T
|
||
|
|
} catch {
|
||
|
|
return null
|
||
|
|
} finally {
|
||
|
|
clearTimeout(timer)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function fetchAgents() {
|
||
|
|
const j = await fetchJson<{ agents?: Agent[] }>('/api/agents', 8000)
|
||
|
|
return j?.agents || []
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function fetchStatus() {
|
||
|
|
return (await fetchJson<StatusData>('/api/status', 8000)) as StatusData
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function fetchFeed() {
|
||
|
|
const j = await fetchJson<{ entries?: FeedEntry[] }>('/api/feed', 8000)
|
||
|
|
return j?.entries || []
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function fetchApprovals() {
|
||
|
|
const j = await fetchJson<{ approvals?: Approval[] }>('/api/approvals', 8000)
|
||
|
|
return j?.approvals || []
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function fetchApprovalHistory(status: string = 'pending') {
|
||
|
|
const j = await fetchJson<{
|
||
|
|
approvals?: Approval[]
|
||
|
|
stats?: { pending: number; approved: number; denied: number; total: number }
|
||
|
|
}>(`/api/approvals?status=${encodeURIComponent(status)}&limit=200`, 8000)
|
||
|
|
return { approvals: j?.approvals || [], stats: j?.stats }
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function fetchGpu(): Promise<GpuStatus | null> {
|
||
|
|
return fetchJson<GpuStatus>('/api/gpu', 8000)
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function fetchTerminals(): Promise<Record<string, TerminalLine[]>> {
|
||
|
|
const j = await fetchJson<{ terminals?: Record<string, TerminalLine[]> }>('/api/terminals', 8000)
|
||
|
|
return j?.terminals || {}
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function fetchWorkload(): Promise<WorkloadData | null> {
|
||
|
|
return fetchJson<WorkloadData>('/api/workload?fast=true', 25000)
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function fetchNodeDetail(nodeId: string) {
|
||
|
|
const j = await fetchJson<Record<string, unknown>>(`/api/nodes/${nodeId}`, 15000)
|
||
|
|
return j || { error: 'timeout' }
|
||
|
|
}
|
||
|
|
|
||
|
|
export function probeNode(nodeId: string) {
|
||
|
|
return fetch(`/api/nodes/${nodeId}/probe`, { method: 'POST' })
|
||
|
|
}
|
||
|
|
|
||
|
|
export function askNode(nodeId: string, message: string) {
|
||
|
|
return fetch(`/api/nodes/${nodeId}/ask`, {
|
||
|
|
method: 'POST',
|
||
|
|
headers: { 'Content-Type': 'application/json' },
|
||
|
|
body: JSON.stringify({ message }),
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
export function sendPrompt(message: string, agentId?: string) {
|
||
|
|
return fetch('/api/prompt', {
|
||
|
|
method: 'POST',
|
||
|
|
headers: { 'Content-Type': 'application/json' },
|
||
|
|
body: JSON.stringify({ message, agent_id: agentId || undefined }),
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function fetchPresentation(): Promise<PresentationData | null> {
|
||
|
|
return fetchJson<PresentationData>('/api/presentation', 60000)
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function decideApproval(id: string, approved: boolean, decidedBy: string, note: string) {
|
||
|
|
return fetch(`/api/approvals/${id}/decide`, {
|
||
|
|
method: 'POST',
|
||
|
|
headers: { 'Content-Type': 'application/json' },
|
||
|
|
body: JSON.stringify({ approved, decided_by: decidedBy, note }),
|
||
|
|
})
|
||
|
|
}
|