MVP: Pulse, Memory, History modules
- Mobile-first PWA with dark glassmorphic theme - Pulse: status card, recent sessions, memory snapshot - Memory: view/edit agent + user memory with usage bars - History: session list, platform filter, search, session replay - TanStack Query hooks for all Hermes WebAPI endpoints - Bottom tab navigation, safe-area support
This commit is contained in:
+88
@@ -0,0 +1,88 @@
|
||||
const BASE = process.env.NEXT_PUBLIC_HERMES_API || "http://localhost:8787";
|
||||
|
||||
async function get<T>(path: string): Promise<T> {
|
||||
const res = await fetch(`${BASE}${path}`);
|
||||
if (!res.ok) throw new Error(`${res.status} ${res.statusText}`);
|
||||
return res.json();
|
||||
}
|
||||
|
||||
async function post<T>(path: string, body?: unknown): Promise<T> {
|
||||
const res = await fetch(`${BASE}${path}`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: body ? JSON.stringify(body) : undefined,
|
||||
});
|
||||
if (!res.ok) throw new Error(`${res.status} ${res.statusText}`);
|
||||
return res.json();
|
||||
}
|
||||
|
||||
async function patch<T>(path: string, body: unknown): Promise<T> {
|
||||
const res = await fetch(`${BASE}${path}`, {
|
||||
method: "PATCH",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
if (!res.ok) throw new Error(`${res.status} ${res.statusText}`);
|
||||
return res.json();
|
||||
}
|
||||
|
||||
async function del<T>(path: string, body?: unknown): Promise<T> {
|
||||
const res = await fetch(`${BASE}${path}`, {
|
||||
method: "DELETE",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: body ? JSON.stringify(body) : undefined,
|
||||
});
|
||||
if (!res.ok) throw new Error(`${res.status} ${res.statusText}`);
|
||||
return res.json();
|
||||
}
|
||||
|
||||
import type {
|
||||
Session, Message, MemoryResponse, SkillSummary, SkillDetail,
|
||||
CronJob, ConfigResponse, SearchResult,
|
||||
} from "./types";
|
||||
|
||||
// Sessions
|
||||
export const fetchSessions = (limit = 50, offset = 0, source?: string) =>
|
||||
get<{ items: Session[]; total: number }>(
|
||||
`/api/sessions?limit=${limit}&offset=${offset}${source ? `&source=${source}` : ""}`
|
||||
);
|
||||
|
||||
export const fetchSession = (id: string) =>
|
||||
get<{ session: Session }>(`/api/sessions/${id}`);
|
||||
|
||||
export const fetchMessages = (sessionId: string, limit = 200, offset = 0) =>
|
||||
get<{ items: Message[]; total: number }>(
|
||||
`/api/sessions/${sessionId}/messages?limit=${limit}&offset=${offset}`
|
||||
);
|
||||
|
||||
export const searchSessions = (q: string, limit = 20) =>
|
||||
get<{ query: string; count: number; results: SearchResult[] }>(
|
||||
`/api/sessions/search?q=${encodeURIComponent(q)}&limit=${limit}`
|
||||
);
|
||||
|
||||
// Memory
|
||||
export const fetchMemory = () => get<MemoryResponse>("/api/memory");
|
||||
|
||||
export const addMemory = (target: string, content: string) =>
|
||||
post<{ success: boolean }>("/api/memory", { target, content });
|
||||
|
||||
export const patchMemory = (target: string, old_text: string, content: string) =>
|
||||
patch<{ success: boolean }>("/api/memory", { target, old_text, content });
|
||||
|
||||
export const deleteMemory = (target: string, old_text: string) =>
|
||||
del<{ success: boolean }>("/api/memory", { target, old_text });
|
||||
|
||||
// Skills
|
||||
export const fetchSkills = (category?: string) =>
|
||||
get<{ success: boolean; skills: SkillSummary[] }>(
|
||||
`/api/skills${category ? `?category=${category}` : ""}`
|
||||
);
|
||||
|
||||
export const fetchSkill = (name: string) =>
|
||||
get<SkillDetail>(`/api/skills/${name}`);
|
||||
|
||||
// Config
|
||||
export const fetchConfig = () => get<ConfigResponse>("/api/config");
|
||||
|
||||
// Health
|
||||
export const fetchHealth = () => get<{ status: string }>("/api/health");
|
||||
Reference in New Issue
Block a user