MCPcopy
hub / github.com/continuedev/continue / OpenAIApi

Class OpenAIApi

packages/openai-adapters/src/apis/OpenAI.ts:35–292  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

33} from "./openaiResponses.js";
34
35export class OpenAIApi implements BaseLlmApi {
36 openai: OpenAI;
37 apiBase: string = "https://api.openai.com/v1/";
38
39 constructor(protected config: z.infer<typeof OpenAIConfigSchema>) {
40 this.apiBase = config.apiBase ?? this.apiBase;
41
42 // Always create the original OpenAI client for fallback
43 this.openai = new OpenAI({
44 // Necessary because `new OpenAI()` will throw an error if there is no API Key
45 apiKey: config.apiKey ?? "",
46 baseURL: this.apiBase,
47 fetch: customFetch(config.requestOptions),
48 timeout: config?.requestOptions?.timeout || undefined,
49 });
50 }
51 modifyChatBody<T extends ChatCompletionCreateParams>(body: T): T {
52 // Add stream_options to include usage in streaming responses
53 if (body.stream) {
54 (body as any).stream_options = { include_usage: true };
55 }
56
57 // DeepSeek reasoner models use max_completion_tokens instead of max_tokens
58 if (
59 body.max_tokens &&
60 (this.apiBase?.includes("api.deepseek.com") ||
61 body.model.includes("deepseek-reasoner"))
62 ) {
63 body.max_completion_tokens = body.max_tokens;
64 body.max_tokens = undefined;
65 }
66
67 // o-series models - only apply for official OpenAI API
68 const isOfficialOpenAIAPI = this.apiBase === "https://api.openai.com/v1/";
69 if (isOfficialOpenAIAPI) {
70 if (body.model.startsWith("o") || body.model.includes("gpt-5")) {
71 // a) use max_completion_tokens instead of max_tokens
72 body.max_completion_tokens = body.max_tokens;
73 body.max_tokens = undefined;
74
75 // b) use "developer" message role rather than "system"
76 body.messages = body.messages.map((message) => {
77 if (message.role === "system") {
78 return { ...message, role: "developer" } as any;
79 }
80 return message;
81 });
82 }
83 if (body.tools?.length && !body.model.startsWith("o3")) {
84 body.parallel_tool_calls = false;
85 }
86 }
87 return body;
88 }
89
90 protected shouldUseResponsesEndpoint(model: string): boolean {
91 if (this.config.useResponsesApi === false) {
92 return false;

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected