This repository has been archived on 2026-08-16. You can view files and clone it, but cannot push or open issues or pull requests.
ollie-webui/src/lib/api.ts

180 lines
5.0 KiB
TypeScript

export interface SessionSummary {
id: string
state: string
model: string
agent: string
// Available in 9P mode, not in DBus list (fetch config for these)
cwd?: string
backend?: string
}
// Compat alias for components still using the old name.
export type IdxEntry = SessionSummary
export interface SessionConfig {
model?: string
backend?: string
agent?: string
cwd?: string
state?: string
[key: string]: string | undefined
}
export async function listSessions(): Promise<SessionSummary[]> {
const r = await fetch('/sessions')
if (!r.ok) return []
const data = await r.json()
return Array.isArray(data) ? (data as SessionSummary[]) : []
}
export async function getSessionCfg(id: string): Promise<SessionConfig> {
const r = await fetch(`/sessions/${id}/config`)
if (!r.ok) throw new Error(`config ${r.status}`)
const data = await r.json()
return (data && typeof data === 'object' && !Array.isArray(data))
? (data as SessionConfig)
: {}
}
export async function getChatLines(id: string): Promise<string[]> {
const r = await fetch(`/sessions/${id}/chat`)
if (!r.ok) return []
const text = await r.text()
if (!text.trim()) return []
return text.trimEnd().split('\n')
}
export async function getChatWithOffset(id: string, offset: number): Promise<{ text: string; newOffset: number }> {
const r = await fetch(`/sessions/${id}/chat?offset=${offset}`)
if (!r.ok) return { text: '', newOffset: offset }
const text = await r.text()
const newOffset = parseInt(r.headers.get('X-Chat-Offset') ?? String(offset), 10)
return { text, newOffset }
}
export async function sendPrompt(id: string, prompt: string): Promise<void> {
await fetch(`/sessions/${id}/submit`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ prompt }),
})
}
export async function interruptSession(id: string): Promise<void> {
await fetch(`/sessions/${id}/interrupt`, { method: 'POST' })
}
export async function createSession(params: {
cwd?: string
backend?: string
model?: string
agent?: string
}): Promise<string | null> {
const r = await fetch('/sessions', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(params),
})
if (!r.ok) return null
const data = await r.json()
return data.id ?? null
}
export async function killSession(id: string): Promise<void> {
await fetch(`/sessions/${id}`, { method: 'DELETE' })
}
export async function renameSession(id: string, newName: string): Promise<void> {
await fetch(`/sessions/${id}`, {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: newName }),
})
}
export async function setConfig(id: string, key: string, value: string): Promise<void> {
await fetch(`/sessions/${id}/config`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ key, value }),
})
}
export async function getState(id: string): Promise<string> {
const r = await fetch(`/sessions/${id}/state`)
if (!r.ok) return 'unknown'
const data = await r.json()
return data.state ?? 'unknown'
}
export async function getBackends(): Promise<string[]> {
const r = await fetch('/backends')
if (!r.ok) return []
const data = await r.json()
return Array.isArray(data) ? (data as string[]) : []
}
export async function getAgents(): Promise<string[]> {
const r = await fetch('/agents')
if (!r.ok) return []
const data = await r.json()
return Array.isArray(data) ? (data as string[]) : []
}
export async function getModels(sessionId: string): Promise<string[]> {
const r = await fetch(`/sessions/${sessionId}/models`)
if (!r.ok) return []
const data = await r.json()
return Array.isArray(data) ? (data as string[]) : []
}
export async function getUsage(id: string): Promise<string> {
const r = await fetch(`/sessions/${id}/usage`)
if (!r.ok) return ''
const data = await r.json()
return data.usage ?? ''
}
export async function getCost(id: string): Promise<string> {
const r = await fetch(`/sessions/${id}/cost`)
if (!r.ok) return ''
const data = await r.json()
return data.cost ?? ''
}
// --- Compat: sendCtl maps to interrupt for "stop" ---
export async function sendCtl(id: string, ctl: string): Promise<void> {
if (ctl === 'stop') {
await interruptSession(id)
}
}
// --- Models cache (for NewSession) ---
const MODELS_CACHE_KEY = 'ollie:models'
export function loadModelsCache(): Record<string, string[]> {
try {
const raw = localStorage.getItem(MODELS_CACHE_KEY)
if (raw) return JSON.parse(raw)
} catch {}
return {}
}
export async function fetchModels(): Promise<Record<string, string[]>> {
// In dbus mode we don't have a global models endpoint.
// Return cached data; individual session model lists are fetched via getModels().
return loadModelsCache()
}
// --- 9P browsing stubs (not available in dbus mode) ---
export async function browse9p(_path: string): Promise<any> {
return null
}
export async function write9p(_path: string, _content: string): Promise<boolean> {
return false
}