Skip to content

Commit 9b6d742

Browse files
authored
fix(openai-codex): send the verbosity setting in requests (#1977)
The Codex provider accepted a verbosity setting but never sent it, so choosing low or high had no effect. buildRequestBody() now adds text.verbosity for models with supportsVerbosity, falling back to "medium" like OpenAI Native, and omits it for other models. Closes #1958
1 parent a101c61 commit 9b6d742

2 files changed

Lines changed: 69 additions & 0 deletions

File tree

‎src/api/providers/__tests__/openai-codex.spec.ts‎

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,3 +1012,65 @@ describe("OpenAiCodexHandler Responses Lite requests", () => {
10121012
})
10131013
})
10141014
})
1015+
1016+
describe("OpenAiCodexHandler verbosity", () => {
1017+
afterEach(() => {
1018+
vitest.restoreAllMocks()
1019+
vitest.unstubAllGlobals()
1020+
})
1021+
1022+
function createHandler(options: ConstructorParameters<typeof OpenAiCodexHandler>[0]) {
1023+
const handler = new OpenAiCodexHandler(options)
1024+
vitest.spyOn(openAiCodexOAuthManager, "getAccessToken").mockResolvedValue("test-token")
1025+
vitest.spyOn(openAiCodexOAuthManager, "getAccountId").mockResolvedValue("acct_test")
1026+
const create = vitest.fn().mockResolvedValue(
1027+
asyncStreamFrom([
1028+
{ type: "response.output_text.delta", delta: "ok" },
1029+
{ type: "response.completed", response: { id: "r1", status: "completed", output: [] } },
1030+
]),
1031+
)
1032+
Reflect.set(handler, "client", { responses: { create } })
1033+
return { handler, create }
1034+
}
1035+
1036+
const sendRequest = {
1037+
chat: (handler: OpenAiCodexHandler) => collectStream(handler.createMessage("System prompt", [])),
1038+
"one-shot": (handler: OpenAiCodexHandler) => handler.completePrompt("Hello"),
1039+
}
1040+
1041+
// gpt-5 uses ordinary Responses; gpt-6.1-sol goes through Responses Lite.
1042+
const supportedCases = (["gpt-5", "gpt-6.1-sol"] as const).flatMap((apiModelId) =>
1043+
(["chat", "one-shot"] as const).flatMap((call) =>
1044+
(
1045+
[
1046+
["low", "low"],
1047+
["medium", "medium"],
1048+
["high", "high"],
1049+
[undefined, "medium"],
1050+
] as const
1051+
).map(([setting, expected]) => ({ apiModelId, call, verbosity: setting ?? "unset", setting, expected })),
1052+
),
1053+
)
1054+
1055+
it.each(supportedCases)(
1056+
"$apiModelId $call request sends text.verbosity $expected when verbosity is $verbosity",
1057+
async ({ apiModelId, call, setting, expected }) => {
1058+
const { handler, create } = createHandler({ apiModelId, ...(setting ? { verbosity: setting } : {}) })
1059+
1060+
await sendRequest[call](handler)
1061+
1062+
expect(create.mock.calls[0][0].text).toEqual({ verbosity: expected })
1063+
},
1064+
)
1065+
1066+
it.each(["chat", "one-shot"] as const)(
1067+
"omits text.verbosity for a model without verbosity support (%s)",
1068+
async (call) => {
1069+
const { handler, create } = createHandler({ apiModelId: "gpt-5-codex", verbosity: "high" })
1070+
1071+
await sendRequest[call](handler)
1072+
1073+
expect(create.mock.calls[0][0]).not.toHaveProperty("text")
1074+
},
1075+
)
1076+
})

‎src/api/providers/openai-codex.ts‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
SERVICE_TIER_KEY,
1414
type ReasoningEffort,
1515
type ReasoningEffortExtended,
16+
type VerbosityLevel,
1617
ApiProviderError,
1718
} from "@roo-code/types"
1819
import { TelemetryService } from "@roo-code/telemetry"
@@ -406,6 +407,7 @@ export class OpenAiCodexHandler extends BaseProvider implements SingleCompletion
406407
}>
407408
tool_choice?: any
408409
parallel_tool_calls?: boolean
410+
text?: { verbosity: VerbosityLevel }
409411
}
410412

411413
// Per the implementation guide: Codex backend may reject max_output_tokens
@@ -446,6 +448,11 @@ export class OpenAiCodexHandler extends BaseProvider implements SingleCompletion
446448
parallel_tool_calls: metadata?.parallelToolCalls ?? true,
447449
}
448450

451+
// Include text.verbosity only when the model explicitly supports it
452+
if (model.info.supportsVerbosity === true) {
453+
body.text = { verbosity: model.verbosity || "medium" }
454+
}
455+
449456
return body
450457
}
451458

0 commit comments

Comments
 (0)