64 lines
1.7 KiB
TypeScript
64 lines
1.7 KiB
TypeScript
type Message = {
|
|
role: "system" | "user" | "assistant";
|
|
content: string;
|
|
};
|
|
|
|
type OpenRouterConfig = {
|
|
baseURL?: string;
|
|
defaultModel?: string;
|
|
};
|
|
|
|
export class OpenRouterClient {
|
|
private apiKey: string;
|
|
private baseURL: string;
|
|
private defaultModel: string;
|
|
private freeModels = [
|
|
"openai/gpt-oss-120b:free",
|
|
"openrouter/free",
|
|
"deepseek/deepseek-chat:free",
|
|
"meta/llama-3.3-70b-instruct:free",
|
|
];
|
|
private providers = ["openai", "google", "anthropic", "deepseek", "meta", "xai"];
|
|
|
|
constructor(apiKey: string, config?: OpenRouterConfig) {
|
|
this.apiKey = apiKey;
|
|
this.baseURL = config?.baseURL ?? "https://openrouter.ai/api/v1";
|
|
this.defaultModel = config?.defaultModel ?? "openai/gpt-oss-120b:free";
|
|
}
|
|
|
|
getFreeModels(): string[] {
|
|
return [...this.freeModels];
|
|
}
|
|
|
|
getProviders(): string[] {
|
|
return [...this.providers];
|
|
}
|
|
|
|
async createChatCompletion(
|
|
messages: Message[],
|
|
model?: string,
|
|
options?: { temperature?: number; max_tokens?: number }
|
|
): Promise<unknown> {
|
|
const response = await fetch(`${this.baseURL}/chat/completions`, {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
Authorization: `Bearer ${this.apiKey}`,
|
|
"HTTP-Referer": "https://aitrader.local",
|
|
"X-Title": "AITrader",
|
|
},
|
|
body: JSON.stringify({
|
|
model: model ?? this.defaultModel,
|
|
messages,
|
|
...(options?.temperature != null && { temperature: options.temperature }),
|
|
...(options?.max_tokens != null && { max_tokens: options.max_tokens }),
|
|
}),
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error(`OpenRouter API error: ${response.status}`);
|
|
}
|
|
|
|
return response.json();
|
|
}
|
|
} |