feat(llm): add OpenRouter API client with error handling and timeout
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
import type { LlmConfig } from '../config/llmConfig.js';
|
||||
import type { RenderedPrompt } from './promptTemplate.js';
|
||||
|
||||
const OPENROUTER_URL = 'https://openrouter.ai/api/v1/chat/completions';
|
||||
|
||||
export interface CompletionRequest extends RenderedPrompt {
|
||||
maxTokens?: number;
|
||||
temperature?: number;
|
||||
}
|
||||
|
||||
export interface OpenRouterClient {
|
||||
complete(request: CompletionRequest): Promise<string | null>;
|
||||
}
|
||||
|
||||
export function createOpenRouterClient(config: LlmConfig): OpenRouterClient {
|
||||
return {
|
||||
async complete(request: CompletionRequest): Promise<string | null> {
|
||||
try {
|
||||
const response = await fetch(OPENROUTER_URL, {
|
||||
method: 'POST',
|
||||
signal: AbortSignal.timeout(config.timeoutMs),
|
||||
headers: {
|
||||
'Authorization': `Bearer ${config.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
model: config.model,
|
||||
max_tokens: request.maxTokens ?? config.maxTokens,
|
||||
temperature: request.temperature ?? config.temperature,
|
||||
messages: [
|
||||
{ role: 'system', content: request.system },
|
||||
{ role: 'user', content: request.user },
|
||||
],
|
||||
}),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
console.warn(`OpenRouter API error: ${response.status} ${response.statusText}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
const content = data?.choices?.[0]?.message?.content;
|
||||
return content ?? null;
|
||||
} catch (error) {
|
||||
console.warn('OpenRouter request failed:', (error as Error).message);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user