Skip to content

Commit 421ceb7

Browse files
committed
feat: allow max reasoning effort policies
1 parent 7b668ab commit 421ceb7

13 files changed

Lines changed: 90 additions & 8 deletions

File tree

docs-site/src/content/docs/operators/api-keys.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ Catalog models are derived from current routable model metadata. Manual model id
152152
Enforced request fields let the key override selected client request values:
153153

154154
1. enforced model
155-
2. enforced reasoning effort
155+
2. enforced reasoning effort (`minimal`, `low`, `medium`, `high`, `xhigh`, or `max`)
156156
3. enforced service tier
157157

158158
Leave a field unset when the client request should pass through unchanged.

lib/codex_pooler/access/api_keys/policy.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ defmodule CodexPooler.Access.APIKeys.Policy do
77
@status_active "active"
88
@status_paused "paused"
99
@status_revoked "revoked"
10-
@reasoning_efforts ~w(minimal low medium high xhigh)
10+
@reasoning_efforts ~w(minimal low medium high xhigh max)
1111
@service_tiers ~w(auto default flex priority scale)
1212

1313
@type access_error :: %{required(:code) => atom(), required(:message) => String.t()}

lib/codex_pooler/access/schemas/api_key.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ defmodule CodexPooler.Access.APIKey do
55
import Ecto.Changeset
66

77
@derive {Inspect, except: [:key_hash]}
8-
@reasoning_efforts ~w(minimal low medium high xhigh)
8+
@reasoning_efforts ~w(minimal low medium high xhigh max)
99
@service_tiers ~w(auto default flex priority scale)
1010

1111
@type t :: %__MODULE__{}

lib/codex_pooler/gateway/payloads/payload_normalizer.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,7 @@ defmodule CodexPooler.Gateway.Payloads.PayloadNormalizer do
385385

386386
defp normalize_thinking_string(value) do
387387
case value |> String.trim() |> String.downcase() do
388-
effort when effort in ["low", "medium", "high", "xhigh"] -> %{"effort" => effort}
388+
effort when effort in ["low", "medium", "high", "xhigh", "max"] -> %{"effort" => effort}
389389
enabled when enabled in ["enabled", "true", "on"] -> %{"effort" => "medium"}
390390
disabled when disabled in ["disabled", "false", "off"] -> nil
391391
_unknown -> nil

lib/codex_pooler_web/live/admin/forms/api_key_policy_form.ex

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,8 @@ defmodule CodexPoolerWeb.Admin.ApiKeyPolicyForm do
101101
{"Low", "low"},
102102
{"Medium", "medium"},
103103
{"High", "high"},
104-
{"Extra high", "xhigh"}
104+
{"Extra high", "xhigh"},
105+
{"Max", "max"}
105106
]
106107
end
107108

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
defmodule CodexPooler.Repo.Migrations.AllowMaxReasoningEffort do
2+
use Ecto.Migration
3+
4+
def up do
5+
execute """
6+
ALTER TABLE api_keys
7+
DROP CONSTRAINT api_keys_enforced_reasoning_effort_check
8+
"""
9+
10+
execute """
11+
ALTER TABLE api_keys
12+
ADD CONSTRAINT api_keys_enforced_reasoning_effort_check
13+
CHECK (enforced_reasoning_effort IS NULL OR enforced_reasoning_effort = ANY (ARRAY['minimal'::text, 'low'::text, 'medium'::text, 'high'::text, 'xhigh'::text, 'max'::text]))
14+
"""
15+
end
16+
17+
def down do
18+
execute """
19+
ALTER TABLE api_keys
20+
DROP CONSTRAINT api_keys_enforced_reasoning_effort_check
21+
"""
22+
23+
execute """
24+
UPDATE api_keys
25+
SET enforced_reasoning_effort = NULL
26+
WHERE enforced_reasoning_effort = 'max'
27+
"""
28+
29+
execute """
30+
ALTER TABLE api_keys
31+
ADD CONSTRAINT api_keys_enforced_reasoning_effort_check
32+
CHECK (enforced_reasoning_effort IS NULL OR enforced_reasoning_effort = ANY (ARRAY['minimal'::text, 'low'::text, 'medium'::text, 'high'::text, 'xhigh'::text]))
33+
"""
34+
end
35+
end

test/codex_pooler/access/api_key_creation_test.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ defmodule CodexPooler.Access.APIKeyCreationTest do
335335
key_hash: <<"typed-policy-valid">>,
336336
status: "active",
337337
enforced_model_identifier: "gpt-5.4-mini",
338-
enforced_reasoning_effort: "medium",
338+
enforced_reasoning_effort: "max",
339339
enforced_service_tier: "scale"
340340
})
341341

test/codex_pooler/access_test.exs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,12 @@ defmodule CodexPooler.AccessTest do
599599

600600
assert {:error, :api_key_policy_malformed} =
601601
Access.normalize_api_key_policy(%{metadata: %{"labels" => "production"}})
602+
603+
assert {:error, :api_key_policy_malformed} =
604+
Access.normalize_api_key_policy(%{enforced_reasoning_effort: "ultra"})
605+
606+
assert {:error, :api_key_policy_malformed} =
607+
Access.normalize_api_key_policy(%{enforced_reasoning_effort: 123})
602608
end
603609

604610
@tag :api_key_policy_contract
@@ -621,6 +627,14 @@ defmodule CodexPooler.AccessTest do
621627
})
622628
end
623629

630+
@tag :api_key_policy_contract
631+
test "normalizes max enforced reasoning effort" do
632+
assert {:ok, policy} =
633+
Access.normalize_api_key_policy(%{enforced_reasoning_effort: " Max "})
634+
635+
assert policy.enforced_reasoning_effort == "max"
636+
end
637+
624638
@tag :api_key_policy_contract
625639
@tag :empty_allow_lists
626640
test "empty model allow-list denies all models" do

test/codex_pooler/db_invariants/access_policy_test.exs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,20 @@ defmodule CodexPooler.DBInvariants.AccessPolicyTest do
9292
)
9393
end)
9494

95+
[[max_reasoning_id]] =
96+
Repo.query!(
97+
"""
98+
INSERT INTO api_keys (
99+
pool_id, display_name, key_prefix, key_hash, status, created_by_user_id,
100+
enforced_reasoning_effort
101+
) VALUES ($1, 'Max reasoning effort', 'sk_policy_max_reasoning', $2, 'active', $3, 'max')
102+
RETURNING id
103+
""",
104+
[pool_id, <<"policy-max-reasoning">>, user_id]
105+
).rows
106+
107+
assert count_rows("api_keys", max_reasoning_id) == 1
108+
95109
assert_db_error(:check_violation, fn ->
96110
Repo.query!(
97111
"""

test/codex_pooler/gateway/payloads/payload_normalizer_test.exs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,22 @@ defmodule CodexPooler.Gateway.Payloads.PayloadNormalizerTest do
471471
}}
472472
end
473473

474+
test "normalizes max thinking alias to reasoning effort" do
475+
payload = %{"model" => "gpt-4.1", "input" => "hello", "thinking" => "max"}
476+
request_options = RequestOptions.build(%{}, "/backend-api/codex/responses", payload)
477+
model = %Model{upstream_model_id: "provider-model"}
478+
479+
assert {:ok, encoded} =
480+
PayloadNormalizer.upstream_payload(
481+
payload,
482+
model,
483+
"/backend-api/codex/responses",
484+
request_options
485+
)
486+
487+
assert Jason.decode!(encoded)["reasoning"] == %{"effort" => "max"}
488+
end
489+
474490
test "omits enforced auto and default service tiers from upstream JSON" do
475491
model = %Model{upstream_model_id: "provider-model"}
476492

0 commit comments

Comments
 (0)