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:
@@ -3,7 +3,7 @@ import path from "node:path";
|
|||||||
import readline from "node:readline";
|
import readline from "node:readline";
|
||||||
import { fileURLToPath } from "node:url";
|
import { fileURLToPath } from "node:url";
|
||||||
|
|
||||||
import { SandboxMode } from "./threadOptions";
|
import { SandboxMode, ModelReasoningEffort } from "./threadOptions";
|
||||||
|
|
||||||
export type CodexExecArgs = {
|
export type CodexExecArgs = {
|
||||||
input: string;
|
input: string;
|
||||||
@@ -22,6 +22,8 @@ export type CodexExecArgs = {
|
|||||||
skipGitRepoCheck?: boolean;
|
skipGitRepoCheck?: boolean;
|
||||||
// --output-schema
|
// --output-schema
|
||||||
outputSchemaFile?: string;
|
outputSchemaFile?: string;
|
||||||
|
// --config model_reasoning_effort
|
||||||
|
modelReasoningEffort?: ModelReasoningEffort;
|
||||||
};
|
};
|
||||||
|
|
||||||
const INTERNAL_ORIGINATOR_ENV = "CODEX_INTERNAL_ORIGINATOR_OVERRIDE";
|
const INTERNAL_ORIGINATOR_ENV = "CODEX_INTERNAL_ORIGINATOR_OVERRIDE";
|
||||||
@@ -56,6 +58,10 @@ export class CodexExec {
|
|||||||
commandArgs.push("--output-schema", args.outputSchemaFile);
|
commandArgs.push("--output-schema", args.outputSchemaFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (args.modelReasoningEffort) {
|
||||||
|
commandArgs.push("--config", `model_reasoning_effort="${args.modelReasoningEffort}"`);
|
||||||
|
}
|
||||||
|
|
||||||
if (args.images?.length) {
|
if (args.images?.length) {
|
||||||
for (const image of args.images) {
|
for (const image of args.images) {
|
||||||
commandArgs.push("--image", image);
|
commandArgs.push("--image", image);
|
||||||
|
|||||||
@@ -30,5 +30,10 @@ export { Codex } from "./codex";
|
|||||||
|
|
||||||
export type { CodexOptions } from "./codexOptions";
|
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";
|
export type { TurnOptions } from "./turnOptions";
|
||||||
|
|||||||
@@ -85,6 +85,7 @@ export class Thread {
|
|||||||
workingDirectory: options?.workingDirectory,
|
workingDirectory: options?.workingDirectory,
|
||||||
skipGitRepoCheck: options?.skipGitRepoCheck,
|
skipGitRepoCheck: options?.skipGitRepoCheck,
|
||||||
outputSchemaFile: schemaPath,
|
outputSchemaFile: schemaPath,
|
||||||
|
modelReasoningEffort: options?.modelReasoningEffort,
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
for await (const item of generator) {
|
for await (const item of generator) {
|
||||||
|
|||||||
@@ -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 SandboxMode = "read-only" | "workspace-write" | "danger-full-access";
|
||||||
|
|
||||||
|
export type ModelReasoningEffort = "minimal" | "low" | "medium" | "high";
|
||||||
|
|
||||||
export type ThreadOptions = {
|
export type ThreadOptions = {
|
||||||
model?: string;
|
model?: string;
|
||||||
sandboxMode?: SandboxMode;
|
sandboxMode?: SandboxMode;
|
||||||
workingDirectory?: string;
|
workingDirectory?: string;
|
||||||
skipGitRepoCheck?: boolean;
|
skipGitRepoCheck?: boolean;
|
||||||
|
modelReasoningEffort?: ModelReasoningEffort;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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 () => {
|
it("writes output schema to a temporary file and forwards it", async () => {
|
||||||
const { url, close, requests } = await startResponsesTestProxy({
|
const { url, close, requests } = await startResponsesTestProxy({
|
||||||
statusCode: 200,
|
statusCode: 200,
|
||||||
|
|||||||
Reference in New Issue
Block a user