init
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
const API_BASE = import.meta.env.VITE_API_URL ?? "";
|
||||
|
||||
export interface ChatSession {
|
||||
id: number;
|
||||
title: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
export interface ChatMessage {
|
||||
id: number;
|
||||
role: string;
|
||||
content: string;
|
||||
created_at: string;
|
||||
}
|
||||
|
||||
export interface SessionDetail extends ChatSession {
|
||||
messages: ChatMessage[];
|
||||
}
|
||||
|
||||
export interface PomodoroStatus {
|
||||
status: string;
|
||||
duration_min: number;
|
||||
task_note: string;
|
||||
elapsed_seconds: number;
|
||||
remaining_seconds: number;
|
||||
session_id: number | null;
|
||||
started_at?: string | null;
|
||||
finished_at?: string | null;
|
||||
}
|
||||
|
||||
export interface PomodoroHistoryItem {
|
||||
id: number;
|
||||
status: string;
|
||||
duration_min: number;
|
||||
task_note: string;
|
||||
result: string | null;
|
||||
completed: boolean;
|
||||
elapsed_seconds: number;
|
||||
finished_at: string | null;
|
||||
}
|
||||
|
||||
async function request<T>(path: string, options?: RequestInit): Promise<T> {
|
||||
const response = await fetch(`${API_BASE}${path}`, options);
|
||||
if (!response.ok) {
|
||||
const text = await response.text();
|
||||
throw new Error(text || response.statusText);
|
||||
}
|
||||
return response.json() as Promise<T>;
|
||||
}
|
||||
|
||||
export const api = {
|
||||
health: () => request<{ status: string }>("/api/v1/health"),
|
||||
|
||||
listSessions: () => request<ChatSession[]>("/api/v1/chat/sessions"),
|
||||
|
||||
createSession: (title = "Новый чат") =>
|
||||
request<ChatSession>("/api/v1/chat/sessions", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ title }),
|
||||
}),
|
||||
|
||||
getSession: (id: number) => request<SessionDetail>(`/api/v1/chat/sessions/${id}`),
|
||||
|
||||
deleteSession: (id: number) =>
|
||||
request<{ ok: boolean }>(`/api/v1/chat/sessions/${id}`, { method: "DELETE" }),
|
||||
|
||||
sendMessage: async function* (sessionId: number, content: string) {
|
||||
const response = await fetch(`${API_BASE}/api/v1/chat/sessions/${sessionId}/messages`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ content }),
|
||||
});
|
||||
|
||||
if (!response.ok || !response.body) {
|
||||
throw new Error("Failed to send message");
|
||||
}
|
||||
|
||||
const reader = response.body.getReader();
|
||||
const decoder = new TextDecoder();
|
||||
let buffer = "";
|
||||
|
||||
while (true) {
|
||||
const { done, value } = await reader.read();
|
||||
if (done) break;
|
||||
|
||||
buffer += decoder.decode(value, { stream: true });
|
||||
const parts = buffer.split("\n\n");
|
||||
buffer = parts.pop() ?? "";
|
||||
|
||||
for (const part of parts) {
|
||||
const lines = part.split("\n");
|
||||
let event = "message";
|
||||
let data = "";
|
||||
|
||||
for (const line of lines) {
|
||||
if (line.startsWith("event: ")) event = line.slice(7);
|
||||
if (line.startsWith("data: ")) data = line.slice(6);
|
||||
}
|
||||
|
||||
if (data) {
|
||||
yield { event, data: JSON.parse(data) };
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
pomodoroStatus: () => request<PomodoroStatus>("/api/v1/pomodoro/status"),
|
||||
|
||||
pomodoroStart: (duration_min: number, task_note: string) =>
|
||||
request<PomodoroStatus>("/api/v1/pomodoro/start", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ duration_min, task_note }),
|
||||
}),
|
||||
|
||||
pomodoroPause: () =>
|
||||
request<PomodoroStatus>("/api/v1/pomodoro/pause", { method: "POST" }),
|
||||
|
||||
pomodoroResume: () =>
|
||||
request<PomodoroStatus>("/api/v1/pomodoro/resume", { method: "POST" }),
|
||||
|
||||
pomodoroStop: (result: string, completed: boolean) =>
|
||||
request<PomodoroStatus>("/api/v1/pomodoro/stop", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ result, completed }),
|
||||
}),
|
||||
|
||||
pomodoroHistory: () => request<PomodoroHistoryItem[]>("/api/v1/pomodoro/history"),
|
||||
};
|
||||
Reference in New Issue
Block a user