Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions sdk/cliproxy/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -879,6 +879,11 @@ func (s *Service) registerModelsForAuth(a *coreauth.Auth) {
if a.Attributes != nil {
codexPlanType = strings.TrimSpace(a.Attributes["plan_type"])
}
if authKind != "apikey" {
if override := codexOAuthPlanOverride(); override != "" {
codexPlanType = override
}
Comment on lines +882 to +885
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Restrict plan override to OAuth auth_kind

The new override gate uses if authKind != "apikey", which treats auth_kind: "api_key" as non-API-key and applies CODEX_OAUTH_PLAN_OVERRIDE to that credential. In this codebase, api_key is a recognized account type (AccountInfo() returns "api_key"), so Codex API-key auths using that spelling can now be forced onto OAuth plan model sets whenever the env var is set. This is a regression from the “OAuth-only override” intent and can expose or hide models unexpectedly for API-key clients.

Useful? React with 👍 / 👎.

}
switch strings.ToLower(codexPlanType) {
case "pro":
models = registry.GetCodexProModels()
Expand Down Expand Up @@ -1180,6 +1185,20 @@ func (s *Service) resolveConfigCodexKey(auth *coreauth.Auth) *config.CodexKey {
return nil
}

func codexOAuthPlanOverride() string {
raw := strings.TrimSpace(os.Getenv("CODEX_OAUTH_PLAN_OVERRIDE"))
if raw == "" {
return ""
}
switch strings.ToLower(raw) {
case "free", "plus", "pro", "team", "business", "go":
return raw
default:
log.Warnf("ignoring invalid CODEX_OAUTH_PLAN_OVERRIDE value: %q", raw)
return ""
}
}
Comment on lines +1188 to +1200
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The codexOAuthPlanOverride function is called during model registration, which can occur frequently (e.g., on every auth update or periodic refresh). Since it reads from the environment and performs validation with a potential warning log, it's better to avoid repeated log spam if an invalid value is provided. Additionally, normalizing the return value to lowercase simplifies the logic for callers and ensures consistency.

var codexOverrideWarnOnce sync.Once

func codexOAuthPlanOverride() string {
	raw := strings.TrimSpace(os.Getenv("CODEX_OAUTH_PLAN_OVERRIDE"))
	if raw == "" {
		return ""
	}
	val := strings.ToLower(raw)
	switch val {
	case "free", "plus", "pro", "team", "business", "go":
		return val
	default:
		codexOverrideWarnOnce.Do(func() {
			log.Warnf("ignoring invalid CODEX_OAUTH_PLAN_OVERRIDE value: %q", raw)
		})
		return ""
	}
}


func (s *Service) oauthExcludedModels(provider, authKind string) []string {
cfg := s.cfg
if cfg == nil {
Expand Down
51 changes: 51 additions & 0 deletions sdk/cliproxy/service_codex_plan_override_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package cliproxy

import (
"testing"

"github.com/router-for-me/CLIProxyAPI/v6/internal/registry"
coreauth "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/auth"
)

func TestRegisterModelsForAuth_CodexOAuthPlanOverride(t *testing.T) {
t.Setenv("CODEX_OAUTH_PLAN_OVERRIDE", "pro")

service := &Service{}
auth := &coreauth.Auth{
ID: "auth-codex-override",
Provider: "codex",
Status: coreauth.StatusActive,
Attributes: map[string]string{
"auth_kind": "oauth",
"plan_type": "free",
},
}

modelRegistry := registry.GetGlobalRegistry()
modelRegistry.UnregisterClient(auth.ID)
t.Cleanup(func() {
modelRegistry.UnregisterClient(auth.ID)
})

service.registerModelsForAuth(auth)

models := modelRegistry.GetModelsForClient(auth.ID)
if len(models) == 0 {
t.Fatal("expected codex models to be registered")
}

has54 := false
for _, model := range models {
if model == nil {
continue
}
if model.ID == "gpt-5.4" {
has54 = true
break
}
}

if !has54 {
t.Fatal("expected CODEX_OAUTH_PLAN_OVERRIDE=pro to expose gpt-5.4")
}
}
Loading