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

@@ -19,15 +19,13 @@ import { ReviewDecision } from "./utils/agent/review";
import { AutoApprovalMode } from "./utils/auto-approval-mode";
import { checkForUpdates } from "./utils/check-updates";
import {
getApiKey,
loadConfig,
PRETTY_PRINT,
INSTRUCTIONS_FILEPATH,
} from "./utils/config";
import { createInputItem } from "./utils/input-utils";
import {
isModelSupportedForResponses,
preloadModels,
} from "./utils/model-utils.js";
import { isModelSupportedForResponses } from "./utils/model-utils.js";
import { parseToolCall } from "./utils/parsers";
import { onExit, setInkRenderer } from "./utils/terminal";
import chalk from "chalk";
@@ -97,6 +95,7 @@ const cli = meow(
help: { type: "boolean", aliases: ["h"] },
view: { type: "string" },
model: { type: "string", aliases: ["m"] },
provider: { type: "string", aliases: ["p"] },
image: { type: "string", isMultiple: true, aliases: ["i"] },
quiet: {
type: "boolean",
@@ -227,7 +226,19 @@ if (cli.flags.config) {
// API key handling
// ---------------------------------------------------------------------------
const apiKey = process.env["OPENAI_API_KEY"];
const fullContextMode = Boolean(cli.flags.fullContext);
let config = loadConfig(undefined, undefined, {
cwd: process.cwd(),
disableProjectDoc: Boolean(cli.flags.noProjectDoc),
projectDocPath: cli.flags.projectDoc as string | undefined,
isFullContext: fullContextMode,
});
const prompt = cli.input[0];
const model = cli.flags.model ?? config.model;
const imagePaths = cli.flags.image as Array<string> | undefined;
const provider = cli.flags.provider ?? config.provider;
const apiKey = getApiKey(provider);
if (!apiKey) {
// eslint-disable-next-line no-console
@@ -242,24 +253,13 @@ if (!apiKey) {
process.exit(1);
}
const fullContextMode = Boolean(cli.flags.fullContext);
let config = loadConfig(undefined, undefined, {
cwd: process.cwd(),
disableProjectDoc: Boolean(cli.flags.noProjectDoc),
projectDocPath: cli.flags.projectDoc as string | undefined,
isFullContext: fullContextMode,
});
const prompt = cli.input[0];
const model = cli.flags.model;
const imagePaths = cli.flags.image as Array<string> | undefined;
config = {
apiKey,
...config,
model: model ?? config.model,
flexMode: Boolean(cli.flags.flexMode),
notify: Boolean(cli.flags.notify),
flexMode: Boolean(cli.flags.flexMode),
provider,
};
// Check for updates after loading config
@@ -281,7 +281,10 @@ if (cli.flags.flexMode) {
}
}
if (!(await isModelSupportedForResponses(config.model))) {
if (
!(await isModelSupportedForResponses(config.model)) &&
(!provider || provider.toLowerCase() === "openai")
) {
// eslint-disable-next-line no-console
console.error(
`The model "${config.model}" does not appear in the list of models ` +
@@ -378,8 +381,6 @@ const approvalPolicy: ApprovalPolicy =
? AutoApprovalMode.AUTO_EDIT
: config.approvalMode || AutoApprovalMode.SUGGEST;
preloadModels();
const instance = render(
<App
prompt={prompt}