Skip to main content
Glama
openai-client.ts4.66 kB
import OpenAI from "openai"; import { logger } from "./logger.js"; import type { ChatMessage } from "./types.js"; export interface ChatOptions { reasoning?: boolean; provider?: "openai" | "openrouter"; } export class OpenAIClient { private apiKey: string; private baseUrl: string; constructor(apiKey: string, baseUrl = "https://api.openai.com/v1") { this.apiKey = apiKey; this.baseUrl = baseUrl; } /** * Build provider-specific reasoning parameters */ private buildReasoningParams( provider: string | undefined, enabled: boolean ): Record<string, unknown> { if (!enabled || !provider) { return {}; } switch (provider) { case "openai": return { reasoning: { enabled: true } }; case "openrouter": // OpenRouter reasoning support varies by model // Many models don't support reasoning parameters, so return empty // User should check OpenRouter docs for specific model support logger.debug("Reasoning requested for OpenRouter model - not all models support this"); return {}; default: return {}; } } /** * Extract reasoning from various response field formats */ private extractReasoning(message: Record<string, unknown>): string | undefined { // Try different field names used by different providers const reasoning = (message.reasoning as string | undefined) || (message.thinking as string | undefined) || (message.reasoning_content as string | undefined); if (reasoning) { return reasoning; } // Handle reasoning_details array format const reasoningDetails = message.reasoning_details as Array<{ text: string }> | undefined; if (reasoningDetails && Array.isArray(reasoningDetails) && reasoningDetails.length > 0) { return reasoningDetails.map((block) => block.text).join("\n"); } return undefined; } /** * Create a client instance with the stored credentials */ private getClient(): OpenAI { return new OpenAI({ apiKey: this.apiKey, baseURL: this.baseUrl, }); } /** * Send a chat message and get a response */ async chat( modelId: string, messages: ChatMessage[], options?: ChatOptions ): Promise<{ content: string; reasoning?: string }> { try { logger.debug("Sending chat request to OpenAI", { model: modelId, messageCount: messages.length, reasoning: options?.reasoning, }); const openaiMessages = messages.map((msg) => ({ role: msg.role as "user" | "assistant", content: msg.content, })); const client = this.getClient(); // Build provider-specific reasoning params const reasoningParams = this.buildReasoningParams( options?.provider, options?.reasoning ?? false ); const response = await client.chat.completions.create({ model: modelId, messages: openaiMessages, ...reasoningParams, }); const textContent = response.choices[0]?.message?.content; if (!textContent) { throw new Error("No content in response from OpenAI"); } logger.debug("Received response from OpenAI", { model: modelId, tokens: response.usage?.total_tokens, }); // Extract reasoning if present and requested let reasoning: string | undefined; if (options?.reasoning) { reasoning = this.extractReasoning( response.choices[0].message as unknown as Record<string, unknown> ); } return { content: textContent, reasoning, }; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); logger.error("OpenAI API error", { model: modelId, error: errorMessage, }); throw new Error(`Failed to get response from OpenAI: ${errorMessage}`); } } /** * Validate that a model is accessible */ async validateModel(modelId: string): Promise<boolean> { try { logger.debug("Validating model", { model: modelId }); // Try a minimal request to validate the model const client = this.getClient(); await client.chat.completions.create({ model: modelId, messages: [{ role: "user" as const, content: "" }], max_tokens: 1, }); return true; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); logger.warn("Model validation failed", { model: modelId, error: errorMessage, }); return false; } } }

Implementation Reference

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/danielwpz/polybrain-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server