Skip to content

Commit 5dc1714

Browse files
Merge branch 'main' into feat/watch-mode
2 parents 3945241 + 146a61b commit 5dc1714

10 files changed

+438
-347
lines changed

codex-cli/src/cli.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,7 @@ async function runQuietMode({
494494
model: config.model,
495495
config: config,
496496
instructions: config.instructions,
497+
provider: config.provider,
497498
approvalPolicy,
498499
additionalWritableRoots,
499500
disableResponseStorage: config.disableResponseStorage,

codex-cli/src/components/chat/terminal-chat.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,7 @@ export default function TerminalChat({
584584
{overlayMode === "model" && (
585585
<ModelOverlay
586586
currentModel={model}
587+
providers={config.providers}
587588
currentProvider={provider}
588589
hasLastResponse={Boolean(lastResponseId)}
589590
onSelect={(newModel) => {

codex-cli/src/components/model-overlay.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import {
33
getAvailableModels,
44
RECOMMENDED_MODELS as _RECOMMENDED_MODELS,
55
} from "../utils/model-utils.js";
6-
import { providers } from "../utils/providers.js";
76
import { Box, Text, useInput } from "ink";
87
import React, { useEffect, useState } from "react";
98

@@ -19,13 +18,15 @@ type Props = {
1918
currentModel: string;
2019
currentProvider?: string;
2120
hasLastResponse: boolean;
21+
providers?: Record<string, { name: string; baseURL: string; envKey: string }>;
2222
onSelect: (model: string) => void;
2323
onSelectProvider?: (provider: string) => void;
2424
onExit: () => void;
2525
};
2626

2727
export default function ModelOverlay({
2828
currentModel,
29+
providers = {},
2930
currentProvider = "openai",
3031
hasLastResponse,
3132
onSelect,

codex-cli/src/utils/agent/agent-loop.ts

-16
Original file line numberDiff line numberDiff line change
@@ -543,22 +543,6 @@ export class AgentLoop {
543543
);
544544
} else {
545545
turnInput = [...abortOutputs, ...input].map(stripInternalFields);
546-
547-
// When response storage is disabled we have to maintain our own
548-
// running transcript so that the next request still contains the
549-
// full conversational history. We skipped the transcript update in
550-
// the branch above – ensure we do it here as well.
551-
if (this.disableResponseStorage) {
552-
const newUserItems: Array<ResponseInputItem> = input.filter((it) => {
553-
if (it.type === "message" && it.role === "system") {
554-
return false;
555-
} else if (it.type === "reasoning") {
556-
return false;
557-
}
558-
return true;
559-
});
560-
this.transcript.push(...newUserItems.map(stripInternalFields));
561-
}
562546
}
563547

564548
this.onLoading(true);

codex-cli/src/utils/agent/exec.ts

+16-3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { exec as rawExec } from "./sandbox/raw-exec.js";
99
import { formatCommandForDisplay } from "../../format-command.js";
1010
import fs from "fs";
1111
import os from "os";
12+
import path from "path";
1213
import { parse } from "shell-quote";
1314
import { resolvePathAgainstWorkdir } from "src/approvals.js";
1415

@@ -63,7 +64,7 @@ export function exec(
6364

6465
export function execApplyPatch(
6566
patchText: string,
66-
workdir: string | undefined,
67+
workdir: string | undefined = undefined,
6768
): ExecResult {
6869
// This is a temporary measure to understand what are the common base commands
6970
// until we start persisting and uploading rollouts
@@ -72,8 +73,20 @@ export function execApplyPatch(
7273
const result = process_patch(
7374
patchText,
7475
(p) => fs.readFileSync(resolvePathAgainstWorkdir(p, workdir), "utf8"),
75-
(p, c) =>
76-
fs.writeFileSync(resolvePathAgainstWorkdir(p, workdir), c, "utf8"),
76+
(p, c) => {
77+
const resolvedPath = resolvePathAgainstWorkdir(p, workdir);
78+
79+
// Ensure the parent directory exists before writing the file. This
80+
// mirrors the behaviour of the standalone apply_patch CLI (see
81+
// write_file() in apply-patch.ts) and prevents errors when adding a
82+
// new file in a not‑yet‑created sub‑directory.
83+
const dir = path.dirname(resolvedPath);
84+
if (dir !== ".") {
85+
fs.mkdirSync(dir, { recursive: true });
86+
}
87+
88+
fs.writeFileSync(resolvedPath, c, "utf8");
89+
},
7790
(p) => fs.unlinkSync(resolvePathAgainstWorkdir(p, workdir)),
7891
);
7992
return {

codex-cli/src/utils/config.ts

+20-13
Original file line numberDiff line numberDiff line change
@@ -42,33 +42,33 @@ export function setApiKey(apiKey: string): void {
4242
}
4343

4444
export function getBaseUrl(provider: string = "openai"): string | undefined {
45-
// If the provider is `openai` and `OPENAI_BASE_URL` is set, use it
46-
if (provider === "openai" && OPENAI_BASE_URL !== "") {
47-
return OPENAI_BASE_URL;
48-
}
49-
50-
// Check for a PROVIDER-specific override: e.g. OLLAMA_BASE_URL
45+
// Check for a PROVIDER-specific override: e.g. OPENAI_BASE_URL or OLLAMA_BASE_URL.
5146
const envKey = `${provider.toUpperCase()}_BASE_URL`;
5247
if (process.env[envKey]) {
5348
return process.env[envKey];
5449
}
5550

56-
// Use the default URL from providers if available
57-
const providerInfo = providers[provider.toLowerCase()];
51+
// Get providers config from config file.
52+
const config = loadConfig();
53+
const providersConfig = config.providers ?? providers;
54+
const providerInfo = providersConfig[provider.toLowerCase()];
5855
if (providerInfo) {
5956
return providerInfo.baseURL;
6057
}
6158

62-
// If the provider not found in the providers list and `OPENAI_BASE_URL` is set, use it
59+
// If the provider not found in the providers list and `OPENAI_BASE_URL` is set, use it.
6360
if (OPENAI_BASE_URL !== "") {
6461
return OPENAI_BASE_URL;
6562
}
6663

64+
// We tried.
6765
return undefined;
6866
}
6967

7068
export function getApiKey(provider: string = "openai"): string | undefined {
71-
const providerInfo = providers[provider.toLowerCase()];
69+
const config = loadConfig();
70+
const providersConfig = config.providers ?? providers;
71+
const providerInfo = providersConfig[provider.toLowerCase()];
7272
if (providerInfo) {
7373
if (providerInfo.name === "Ollama") {
7474
return process.env[providerInfo.envKey] ?? "dummy";
@@ -81,12 +81,10 @@ export function getApiKey(provider: string = "openai"): string | undefined {
8181
return OPENAI_API_KEY;
8282
}
8383

84+
// We tried.
8485
return undefined;
8586
}
8687

87-
// Formatting (quiet mode-only).
88-
export const PRETTY_PRINT = Boolean(process.env["PRETTY_PRINT"] || "");
89-
9088
// Represents config as persisted in config.json.
9189
export type StoredConfig = {
9290
model?: string;
@@ -98,6 +96,7 @@ export type StoredConfig = {
9896
notify?: boolean;
9997
/** Disable server-side response storage (send full transcript each request) */
10098
disableResponseStorage?: boolean;
99+
providers?: Record<string, { name: string; baseURL: string; envKey: string }>;
101100
history?: {
102101
maxSize?: number;
103102
saveHistory?: boolean;
@@ -134,13 +133,17 @@ export type AppConfig = {
134133

135134
/** Enable the "flex-mode" processing mode for supported models (o3, o4-mini) */
136135
flexMode?: boolean;
136+
providers?: Record<string, { name: string; baseURL: string; envKey: string }>;
137137
history?: {
138138
maxSize: number;
139139
saveHistory: boolean;
140140
sensitivePatterns: Array<string>;
141141
};
142142
};
143143

144+
// Formatting (quiet mode-only).
145+
export const PRETTY_PRINT = Boolean(process.env["PRETTY_PRINT"] || "");
146+
144147
// ---------------------------------------------------------------------------
145148
// Project doc support (codex.md)
146149
// ---------------------------------------------------------------------------
@@ -399,6 +402,9 @@ export const loadConfig = (
399402
};
400403
}
401404

405+
// Merge default providers with user configured providers in the config.
406+
config.providers = { ...providers, ...storedConfig.providers };
407+
402408
return config;
403409
};
404410

@@ -431,6 +437,7 @@ export const saveConfig = (
431437
const configToSave: StoredConfig = {
432438
model: config.model,
433439
provider: config.provider,
440+
providers: config.providers,
434441
approvalMode: config.approvalMode,
435442
};
436443

0 commit comments

Comments
 (0)