返回 ViMax
api.ts
根目录 / web / src / api.ts
1 import type {AgentConfig, AgentEvent, Artifact, JsonValue, Message, SessionSummary, WorkspaceUpload} from './types';
2
3 export async function getSessions() {
4 return request<{activeSessionId: string; sessions: SessionSummary[]}>('/api/sessions');
5 }
6
7 export async function deleteSession(sessionId: string) {
8 return request<{activeSessionId: string; sessions: SessionSummary[]}>(`/api/sessions?session=${encodeURIComponent(sessionId)}`, {method: 'DELETE'});
9 }
10
11 export async function getAgentConfig() {
12 return request<AgentConfig>('/api/config');
13 }
14
15 export async function saveAgentConfig(config: AgentConfig) {
16 return request<AgentConfig>('/api/config', {method: 'PUT', body: JSON.stringify(config)});
17 }
18
19 export async function getHistory(sessionId: string) {
20 return request<{messages: Message[]}>(`/api/history?session=${encodeURIComponent(sessionId)}`);
21 }
22
23 export async function getArtifacts(sessionId: string) {
24 return request<{artifacts: Artifact[]}>(`/api/artifacts?session=${encodeURIComponent(sessionId)}`);
25 }
26
27 export async function uploadWorkspaceFile(sessionId: string, file: File) {
28 const url = `/api/uploads?session=${encodeURIComponent(sessionId)}&name=${encodeURIComponent(file.name)}`;
29 const response = await fetch(url, {
30 method: 'POST',
31 headers: {'Content-Type': file.type || 'application/octet-stream'},
32 body: file,
33 });
34 const payload = await response.json();
35 if (!response.ok) throw new Error(payload.error || `Upload failed with HTTP ${response.status}`);
36 return payload as {file: WorkspaceUpload};
37 }
38
39 export async function getJsonArtifact(artifact: Artifact): Promise<JsonValue> {
40 const separator = artifact.url.includes('?') ? '&' : '?';
41 const response = await fetch(`${artifact.url}${separator}updated=${encodeURIComponent(artifact.updatedAt)}`, {
42 cache: 'no-store',
43 headers: {Accept: 'application/json'},
44 });
45 const payload = await response.json();
46 if (!response.ok) {
47 const message = payload && typeof payload === 'object' && 'error' in payload ? String(payload.error) : `Request failed with HTTP ${response.status}`;
48 throw new Error(message);
49 }
50 return payload as JsonValue;
51 }
52
53 export async function startAgent(options: {sessionId?: string; newSession?: boolean; projectName?: string}) {
54 return request<{ok: boolean}>('/api/agent/start', {method: 'POST', body: JSON.stringify(options)});
55 }
56
57 export async function sendMessage(text: string) {
58 return request<{ok: boolean}>('/api/messages', {method: 'POST', body: JSON.stringify({text})});
59 }
60
61 export async function stopAgent() {
62 return request<{ok: boolean}>('/api/agent/stop', {method: 'POST', body: '{}'});
63 }
64
65 export function subscribeToEvents(onEvent: (event: AgentEvent) => void, onConnection: (connected: boolean) => void) {
66 const source = new EventSource('/api/events');
67 source.onopen = () => onConnection(true);
68 source.onerror = () => onConnection(false);
69 source.onmessage = (message) => {
70 try {
71 onEvent(JSON.parse(message.data) as AgentEvent);
72 } catch {
73 onEvent({type: 'error', message: 'Received an invalid event from the local bridge'});
74 }
75 };
76 return () => source.close();
77 }
78
79 async function request<T>(url: string, init: RequestInit = {}): Promise<T> {
80 const response = await fetch(url, {
81 ...init,
82 headers: {'Content-Type': 'application/json', ...(init.headers || {})},
83 });
84 const payload = await response.json();
85 if (!response.ok) throw new Error(payload.error || `Request failed with HTTP ${response.status}`);
86 return payload as T;
87 }
88
88 lines TYPESCRIPT