180 lines
5.0 KiB
TypeScript
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
|
|
}
|