diff --git a/sdk/typescript/src/exec.ts b/sdk/typescript/src/exec.ts index 45ae5fc6..5c7b1846 100644 --- a/sdk/typescript/src/exec.ts +++ b/sdk/typescript/src/exec.ts @@ -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); diff --git a/sdk/typescript/src/index.ts b/sdk/typescript/src/index.ts index 8e6a71df..cfd0dc43 100644 --- a/sdk/typescript/src/index.ts +++ b/sdk/typescript/src/index.ts @@ -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"; diff --git a/sdk/typescript/src/thread.ts b/sdk/typescript/src/thread.ts index 2306df25..08488521 100644 --- a/sdk/typescript/src/thread.ts +++ b/sdk/typescript/src/thread.ts @@ -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) { diff --git a/sdk/typescript/src/threadOptions.ts b/sdk/typescript/src/threadOptions.ts index 7f01488d..53895c9a 100644 --- a/sdk/typescript/src/threadOptions.ts +++ b/sdk/typescript/src/threadOptions.ts @@ -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; }; diff --git a/sdk/typescript/tests/run.test.ts b/sdk/typescript/tests/run.test.ts index f495b1e6..f6eefa0c 100644 --- a/sdk/typescript/tests/run.test.ts +++ b/sdk/typescript/tests/run.test.ts @@ -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,