feat: support multiple providers via Responses-Completion transformation (#247)

https://github.com/user-attachments/assets/9ecb51be-fa65-4e99-8512-abb898dda569

Implemented it as a transformation between Responses API and Completion
API so that it supports existing providers that implement the Completion
API and minimizes the changes needed to the codex repo.

---------

Co-authored-by: Thibault Sottiaux <tibo@openai.com>
Co-authored-by: Fouad Matin <169186268+fouad-openai@users.noreply.github.com>
Co-authored-by: Fouad Matin <fouad@openai.com>
This commit is contained in:
Daniel Nakov
2025-04-20 23:59:34 -04:00
committed by GitHub
parent 693bd59ecc
commit eafbc75612
11 changed files with 1870 additions and 83 deletions

View File

@@ -10,6 +10,7 @@ import type { FullAutoErrorMode } from "./auto-approval-mode.js";
import { log } from "./agent/log.js";
import { AutoApprovalMode } from "./auto-approval-mode.js";
import { providers } from "./providers.js";
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
import { load as loadYaml, dump as dumpYaml } from "js-yaml";
import { homedir } from "os";
@@ -40,12 +41,33 @@ export function setApiKey(apiKey: string): void {
OPENAI_API_KEY = apiKey;
}
export function getBaseUrl(provider: string = "openai"): string | undefined {
const providerInfo = providers[provider.toLowerCase()];
if (providerInfo) {
return providerInfo.baseURL;
}
return undefined;
}
export function getApiKey(provider: string = "openai"): string | undefined {
const providerInfo = providers[provider.toLowerCase()];
if (providerInfo) {
if (providerInfo.name === "Ollama") {
return process.env[providerInfo.envKey] ?? "dummy";
}
return process.env[providerInfo.envKey];
}
return undefined;
}
// Formatting (quiet mode-only).
export const PRETTY_PRINT = Boolean(process.env["PRETTY_PRINT"] || "");
// Represents config as persisted in config.json.
export type StoredConfig = {
model?: string;
provider?: string;
approvalMode?: AutoApprovalMode;
fullAutoErrorMode?: FullAutoErrorMode;
memory?: MemoryConfig;
@@ -76,6 +98,7 @@ export type MemoryConfig = {
export type AppConfig = {
apiKey?: string;
model: string;
provider?: string;
instructions: string;
approvalMode?: AutoApprovalMode;
fullAutoErrorMode?: FullAutoErrorMode;
@@ -270,6 +293,7 @@ export const loadConfig = (
(options.isFullContext
? DEFAULT_FULL_CONTEXT_MODEL
: DEFAULT_AGENTIC_MODEL),
provider: storedConfig.provider,
instructions: combinedInstructions,
notify: storedConfig.notify === true,
approvalMode: storedConfig.approvalMode,
@@ -389,6 +413,7 @@ export const saveConfig = (
// Create the config object to save
const configToSave: StoredConfig = {
model: config.model,
provider: config.provider,
approvalMode: config.approvalMode,
};