tori/web/src/api.ts
Fam Zheng 815477a73b feat: template examples + recent templates quick buttons
- Add TemplateExample struct and examples scanning (local dir + git repo)
- Exclude examples/ from copy_dir_recursive
- Frontend: recent templates (localStorage), template-specific example buttons
2026-03-08 08:56:40 +00:00

123 lines
4.0 KiB
TypeScript

import type { Project, Workflow, ExecutionLogEntry, Comment, Timer, KbArticle, KbArticleSummary, PlanStepInfo, LlmCallLogEntry, ChatMessage } from './types'
const BASE = `${import.meta.env.BASE_URL.replace(/\/$/, '')}/api`
async function request<T>(path: string, options?: RequestInit): Promise<T> {
const res = await fetch(`${BASE}${path}`, {
headers: { 'Content-Type': 'application/json' },
...options,
})
if (!res.ok) {
const text = await res.text()
throw new Error(`API error ${res.status}: ${text}`)
}
return res.json()
}
export const api = {
listProjects: () => request<Project[]>('/projects'),
createProject: (name: string, description = '') =>
request<Project>('/projects', {
method: 'POST',
body: JSON.stringify({ name, description }),
}),
getProject: (id: string) => request<Project | null>(`/projects/${id}`),
updateProject: (id: string, data: { name?: string; description?: string }) =>
request<Project | null>(`/projects/${id}`, {
method: 'PUT',
body: JSON.stringify(data),
}),
deleteProject: (id: string) =>
request<boolean>(`/projects/${id}`, { method: 'DELETE' }),
listWorkflows: (projectId: string) =>
request<Workflow[]>(`/projects/${projectId}/workflows`),
createWorkflow: (projectId: string, requirement: string, templateId?: string) =>
request<Workflow>(`/projects/${projectId}/workflows`, {
method: 'POST',
body: JSON.stringify({ requirement, template_id: templateId || undefined }),
}),
listTemplates: () =>
request<{ id: string; name: string; description: string; examples: { label: string; text: string }[] }[]>('/templates'),
listSteps: (workflowId: string) =>
request<ExecutionLogEntry[]>(`/workflows/${workflowId}/steps`),
listComments: (workflowId: string) =>
request<Comment[]>(`/workflows/${workflowId}/comments`),
createComment: (workflowId: string, content: string) =>
request<Comment>(`/workflows/${workflowId}/comments`, {
method: 'POST',
body: JSON.stringify({ content }),
}),
getReport: (workflowId: string) =>
request<{ report: string }>(`/workflows/${workflowId}/report`),
listPlanSteps: (workflowId: string) =>
request<PlanStepInfo[]>(`/workflows/${workflowId}/plan`),
listLlmCalls: (workflowId: string) =>
request<LlmCallLogEntry[]>(`/workflows/${workflowId}/llm-calls`),
listTimers: (projectId: string) =>
request<Timer[]>(`/projects/${projectId}/timers`),
createTimer: (projectId: string, data: { name: string; interval_secs: number; requirement: string }) =>
request<Timer>(`/projects/${projectId}/timers`, {
method: 'POST',
body: JSON.stringify(data),
}),
updateTimer: (timerId: string, data: { name?: string; interval_secs?: number; requirement?: string; enabled?: boolean }) =>
request<Timer>(`/timers/${timerId}`, {
method: 'PUT',
body: JSON.stringify(data),
}),
deleteTimer: (timerId: string) =>
request<void>(`/timers/${timerId}`, { method: 'DELETE' }),
getKb: () => request<{ content: string }>('/kb'),
listArticles: () => request<KbArticleSummary[]>('/kb/articles'),
createArticle: (title: string) =>
request<KbArticle>('/kb/articles', {
method: 'POST',
body: JSON.stringify({ title }),
}),
getArticle: (id: string) => request<KbArticle>(`/kb/articles/${id}`),
updateArticle: (id: string, data: { title?: string; content?: string }) =>
request<KbArticle>(`/kb/articles/${id}`, {
method: 'PUT',
body: JSON.stringify(data),
}),
deleteArticle: (id: string) =>
request<boolean>(`/kb/articles/${id}`, { method: 'DELETE' }),
chat: (messages: ChatMessage[]) =>
request<{ reply: string }>('/chat', {
method: 'POST',
body: JSON.stringify({ messages }),
}),
getSettings: () => request<Record<string, string>>('/settings'),
putSetting: (key: string, value: string) =>
request<Record<string, string>>(`/settings/${key}`, {
method: 'PUT',
body: JSON.stringify({ value }),
}),
}