Files
AIUI/frontend/src/services/api.ts
T
2026-04-26 14:52:50 +03:00

95 lines
2.4 KiB
TypeScript

import type { Message, OpenAIMessage, OpenAIStreamChunk } from '@/types';
export async function* streamChatCompletion(
messages: Message[],
apiUrl: string,
apiKey: string,
model: string,
temperature: number,
maxTokens: number,
systemPrompt: string,
abortSignal: AbortSignal
): AsyncGenerator<OpenAIStreamChunk, void, unknown> {
const formattedMessages: OpenAIMessage[] = [
{ role: 'system', content: systemPrompt },
...messages.map((m) => ({ role: m.role, content: m.content }) as OpenAIMessage),
];
const response = await fetch('/api/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
apiUrl,
apiKey,
model,
temperature,
max_tokens: maxTokens,
messages: formattedMessages,
stream: true,
}),
signal: abortSignal,
});
if (!response.ok) {
const errorData = await response.json().catch(() => ({}));
throw new Error(errorData.error?.message || `HTTP error! status: ${response.status}`);
}
const reader = response.body?.getReader();
if (!reader) {
throw new Error('No response body');
}
const decoder = new TextDecoder();
let buffer = '';
try {
while (true) {
const { done, value } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
const lines = buffer.split('\n');
buffer = lines.pop() || '';
for (const line of lines) {
const trimmed = line.trim();
if (!trimmed || trimmed === 'data: [DONE]') continue;
if (trimmed.startsWith('data: ')) {
try {
const data: OpenAIStreamChunk = JSON.parse(trimmed.slice(6));
yield data;
} catch {
// Ignore parse errors for incomplete chunks
}
}
}
}
} finally {
reader.releaseLock();
}
}
export async function fetchModels(
apiUrl: string,
apiKey: string
): Promise<string[]> {
const response = await fetch('/api/v1/models', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ apiUrl, apiKey }),
});
if (!response.ok) {
const errorData = await response.json().catch(() => ({}));
throw new Error(errorData.error?.message || `HTTP error! status: ${response.status}`);
}
const data = await response.json();
return data.models || [];
}