Add modelReasoningEffort option to TypeScript SDK (#6237)

## Summary
- Adds `ModelReasoningEffort` type to TypeScript SDK with values:
`minimal`, `low`, `medium`, `high`
- Adds `modelReasoningEffort` option to `ThreadOptions`
- Forwards the option to the codex CLI via `--config
model_reasoning_effort="<value>"`
- Includes test coverage for the new option

## Changes
- `sdk/typescript/src/threadOptions.ts`: Define `ModelReasoningEffort`
type and add to `ThreadOptions`
- `sdk/typescript/src/index.ts`: Export `ModelReasoningEffort` type
- `sdk/typescript/src/exec.ts`: Forward `modelReasoningEffort` to CLI as
config flag
- `sdk/typescript/src/thread.ts`: Pass option through to exec (+ debug
logging)
- `sdk/typescript/tests/run.test.ts`: Add test for
`modelReasoningEffort` flag forwarding

---------

Co-authored-by: Eric Traut <etraut@openai.com>
This commit is contained in:
Dan Hernandez
2025-11-05 08:51:03 -08:00
committed by GitHub
parent 9b538a8672
commit 9a10e80ab7
5 changed files with 48 additions and 2 deletions

View File

@@ -3,7 +3,7 @@ import path from "node:path";
import readline from "node:readline";
import { fileURLToPath } from "node:url";
import { SandboxMode } from "./threadOptions";
import { SandboxMode, ModelReasoningEffort } from "./threadOptions";
export type CodexExecArgs = {
input: string;
@@ -22,6 +22,8 @@ export type CodexExecArgs = {
skipGitRepoCheck?: boolean;
// --output-schema
outputSchemaFile?: string;
// --config model_reasoning_effort
modelReasoningEffort?: ModelReasoningEffort;
};
const INTERNAL_ORIGINATOR_ENV = "CODEX_INTERNAL_ORIGINATOR_OVERRIDE";
@@ -56,6 +58,10 @@ export class CodexExec {
commandArgs.push("--output-schema", args.outputSchemaFile);
}
if (args.modelReasoningEffort) {
commandArgs.push("--config", `model_reasoning_effort="${args.modelReasoningEffort}"`);
}
if (args.images?.length) {
for (const image of args.images) {
commandArgs.push("--image", image);

View File

@@ -30,5 +30,10 @@ export { Codex } from "./codex";
export type { CodexOptions } from "./codexOptions";
export type { ThreadOptions, ApprovalMode, SandboxMode } from "./threadOptions";
export type {
ThreadOptions,
ApprovalMode,
SandboxMode,
ModelReasoningEffort,
} from "./threadOptions";
export type { TurnOptions } from "./turnOptions";

View File

@@ -85,6 +85,7 @@ export class Thread {
workingDirectory: options?.workingDirectory,
skipGitRepoCheck: options?.skipGitRepoCheck,
outputSchemaFile: schemaPath,
modelReasoningEffort: options?.modelReasoningEffort,
});
try {
for await (const item of generator) {

View File

@@ -2,9 +2,12 @@ export type ApprovalMode = "never" | "on-request" | "on-failure" | "untrusted";
export type SandboxMode = "read-only" | "workspace-write" | "danger-full-access";
export type ModelReasoningEffort = "minimal" | "low" | "medium" | "high";
export type ThreadOptions = {
model?: string;
sandboxMode?: SandboxMode;
workingDirectory?: string;
skipGitRepoCheck?: boolean;
modelReasoningEffort?: ModelReasoningEffort;
};

View File

@@ -223,6 +223,37 @@ describe("Codex", () => {
}
});
it("passes modelReasoningEffort to exec", async () => {
const { url, close } = await startResponsesTestProxy({
statusCode: 200,
responseBodies: [
sse(
responseStarted("response_1"),
assistantMessage("Reasoning effort applied", "item_1"),
responseCompleted("response_1"),
),
],
});
const { args: spawnArgs, restore } = codexExecSpy();
try {
const client = new Codex({ codexPathOverride: codexExecPath, baseUrl: url, apiKey: "test" });
const thread = client.startThread({
modelReasoningEffort: "high",
});
await thread.run("apply reasoning effort");
const commandArgs = spawnArgs[0];
expect(commandArgs).toBeDefined();
expectPair(commandArgs, ["--config", 'model_reasoning_effort="high"']);
} finally {
restore();
await close();
}
});
it("writes output schema to a temporary file and forwards it", async () => {
const { url, close, requests } = await startResponsesTestProxy({
statusCode: 200,