fix(groups): tighten reasoning policy

Remove unsupported none handling, align the auth cache version with the current baseline, consolidate the unshipped migrations, and update the public API contract.
This commit is contained in:
zhaozewu
2026-07-21 11:16:04 +08:00
parent 6af622c340
commit 6c93f01c97
8 changed files with 13 additions and 15 deletions
@@ -381,6 +381,8 @@ func TestAPIContracts(t *testing.T) {
"fallback_group_id_on_invalid_request": null,
"require_oauth_only": false,
"require_privacy_set": false,
"max_reasoning_effort": "",
"reasoning_effort_mappings": null,
"rpm_limit": 0,
"created_at": "2025-01-02T03:04:05Z",
"updated_at": "2025-01-02T03:04:05Z"
@@ -14,7 +14,7 @@ import (
"github.com/dgraph-io/ristretto"
)
const apiKeyAuthSnapshotVersion = 18 // v18: include group reasoning effort ceiling and mappings
const apiKeyAuthSnapshotVersion = 16 // v16: include group reasoning effort ceiling and mappings
type apiKeyAuthCacheConfig struct {
l1Size int
@@ -42,18 +42,18 @@ func TestAPIKeyService_RejectsV10AuthSnapshotWithoutModelsListConfig(t *testing.
}
}
func TestAPIKeyService_RejectsV17AuthSnapshotWithoutReasoningEffortMappings(t *testing.T) {
func TestAPIKeyService_RejectsV15AuthSnapshotWithoutReasoningEffortPolicy(t *testing.T) {
svc := &APIKeyService{}
apiKey, ok, err := svc.applyAuthCacheEntry("k-legacy-reasoning-mappings", &APIKeyAuthCacheEntry{
Snapshot: &APIKeyAuthSnapshot{Version: 17},
Snapshot: &APIKeyAuthSnapshot{Version: 15},
})
if err != nil {
t.Fatalf("expected stale snapshot to be ignored without error, got %v", err)
}
if ok {
t.Fatal("expected v17 auth snapshot to be rejected after reasoning effort mappings were added")
t.Fatal("expected v15 auth snapshot to be rejected after reasoning effort policy was added")
}
if apiKey != nil {
t.Fatalf("expected no API key from stale snapshot, got %#v", apiKey)
@@ -23,8 +23,6 @@ func NormalizeMaxReasoningEffort(raw string) string {
switch value {
case "":
return ""
case "none":
return "none"
case "minimal":
return "minimal"
case "low":
@@ -75,8 +73,6 @@ func normalizeMaxReasoningEffortForPlatform(platform, raw string) (string, error
func reasoningEffortRank(raw string) (int, bool) {
switch NormalizeMaxReasoningEffort(raw) {
case "none":
return 0, true
case "minimal":
return 1, true
case "low":
@@ -16,6 +16,7 @@ func TestNormalizeMaxReasoningEffort(t *testing.T) {
{name: "empty", in: "", want: ""},
{name: "separator", in: "x-high", want: "xhigh"},
{name: "max is distinct", in: "max", want: "max"},
{name: "none is unsupported", in: "none", want: ""},
{name: "invalid", in: "banana", want: ""},
}
for _, tt := range tests {
@@ -58,7 +59,7 @@ func TestNormalizeReasoningEffortMappings(t *testing.T) {
}
_, err := NormalizeReasoningEffortMappings(PlatformOpenAI, []ReasoningEffortMapping{{From: "none", To: "low"}})
require.ErrorContains(t, err, "not supported for platform")
require.ErrorContains(t, err, "empty or unknown")
_, err = NormalizeReasoningEffortMappings(PlatformOpenAI, []ReasoningEffortMapping{{From: "ultra", To: "high"}})
require.ErrorContains(t, err, "empty or unknown")
@@ -96,6 +97,7 @@ func TestApplyOpenAIReasoningEffortPolicy(t *testing.T) {
{name: "normalizes request alias", body: `{"reasoning_effort":"x-high"}`, max: "xhigh", path: "reasoning_effort", want: "xhigh", changed: true},
{name: "caps max below its distinct rank", body: `{"reasoning_effort":"max"}`, max: "xhigh", path: "reasoning_effort", want: "xhigh", changed: true},
{name: "keeps xhigh below max", body: `{"reasoning_effort":"xhigh"}`, max: "max", path: "reasoning_effort", want: "xhigh", changed: false},
{name: "ignores stale none ceiling", body: `{"reasoning_effort":"high"}`, max: "none", path: "reasoning_effort", want: "high", changed: false},
{name: "caps both shapes", body: `{"reasoning":{"effort":"high"},"reasoning_effort":"xhigh"}`, max: "low", path: "reasoning.effort", want: "low", changed: true},
{name: "maps before cap", body: `{"reasoning":{"effort":"MAX"}}`, max: "medium", mappings: []ReasoningEffortMapping{{From: "max", To: "xhigh"}}, path: "reasoning.effort", want: "medium", changed: true},
{name: "does not chain mappings", body: `{"reasoning_effort":"max"}`, mappings: []ReasoningEffortMapping{{From: "max", To: "xhigh"}, {From: "xhigh", To: "low"}}, path: "reasoning_effort", want: "xhigh", changed: true},
@@ -1,3 +0,0 @@
-- Add a per-group ceiling for OpenAI/Codex reasoning effort.
ALTER TABLE groups
ADD COLUMN IF NOT EXISTS max_reasoning_effort VARCHAR(20) NOT NULL DEFAULT '';
@@ -0,0 +1,4 @@
-- Add per-group controls for explicit OpenAI/Codex reasoning effort values.
ALTER TABLE groups
ADD COLUMN IF NOT EXISTS max_reasoning_effort VARCHAR(20) NOT NULL DEFAULT '',
ADD COLUMN IF NOT EXISTS reasoning_effort_mappings JSONB NOT NULL DEFAULT '[]'::jsonb;
@@ -1,3 +0,0 @@
-- Add exact rewrites for explicit OpenAI/Codex reasoning effort values.
ALTER TABLE groups
ADD COLUMN IF NOT EXISTS reasoning_effort_mappings JSONB NOT NULL DEFAULT '[]'::jsonb;