mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-09-03 06:35:00 +08:00
feat(registry): remote-refresh Codex client model catalog (#4276)
Load codex_client_models.json like models.json with validation, revisioned handler reloads, CI bake, and Home-aware updater gates so list IDs still come from Home while templates can refresh on the edge.
This commit is contained in:
@@ -10,8 +10,8 @@
|
||||
//
|
||||
// --auths-dir <path> Directory containing auth JSON files (default: config auth-dir)
|
||||
// --config <path> Config file path (default: "config.yaml")
|
||||
// --output <path> Output JSON file path (default: "codex_models.json")
|
||||
// --client-version <ver> Codex client_version query value (default: "0.133.0")
|
||||
// --output <path> Output JSON file path (default: "codex_client_models.json")
|
||||
// --client-version <ver> Codex client_version query value (default: "0.144.1")
|
||||
// --pretty Pretty-print the output JSON (default: true)
|
||||
package main
|
||||
|
||||
@@ -62,7 +62,7 @@ func main() {
|
||||
|
||||
flag.StringVar(&authsDir, "auths-dir", "", "Directory containing auth JSON files (overrides config auth-dir)")
|
||||
flag.StringVar(&configPath, "config", "", "Configure File Path")
|
||||
flag.StringVar(&outputPath, "output", "codex_models.json", "Output JSON file path")
|
||||
flag.StringVar(&outputPath, "output", "codex_client_models.json", "Output JSON file path")
|
||||
flag.StringVar(&clientVersion, "client-version", defaultClientVersion, "Codex client_version query value")
|
||||
flag.BoolVar(&pretty, "pretty", true, "Pretty-print the output JSON")
|
||||
flag.Parse()
|
||||
@@ -296,11 +296,14 @@ func codexModelsURL(clientVersion string) (string, error) {
|
||||
|
||||
func countModels(raw []byte) (int, error) {
|
||||
var payload struct {
|
||||
Models []map[string]any `json:"models"`
|
||||
Models []json.RawMessage `json:"models"`
|
||||
}
|
||||
if err := json.Unmarshal(raw, &payload); err != nil {
|
||||
return 0, fmt.Errorf("failed to parse response JSON: %w", err)
|
||||
}
|
||||
// Keep this check intentionally loose: fetch_codex_models dumps the upstream
|
||||
// Codex API payload. Strict CPA catalog validation belongs in
|
||||
// cmd/validate_codex_models and registry.ValidateCodexClientModelsJSON.
|
||||
if payload.Models == nil {
|
||||
return 0, fmt.Errorf("response JSON does not contain models array")
|
||||
}
|
||||
|
||||
48
cmd/fetch_codex_models/main_test.go
Normal file
48
cmd/fetch_codex_models/main_test.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package main
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestCodexModelsURL(t *testing.T) {
|
||||
got, err := codexModelsURL(" 0.144.1 ")
|
||||
if err != nil {
|
||||
t.Fatalf("codexModelsURL: %v", err)
|
||||
}
|
||||
want := "https://chatgpt.com/backend-api/codex/models?client_version=0.144.1"
|
||||
if got != want {
|
||||
t.Fatalf("codexModelsURL = %q, want %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCountModels(t *testing.T) {
|
||||
count, err := countModels([]byte(`{"models":[{"slug":"a"},{"slug":"b"}]}`))
|
||||
if err != nil {
|
||||
t.Fatalf("countModels(valid): %v", err)
|
||||
}
|
||||
if count != 2 {
|
||||
t.Fatalf("countModels(valid) = %d, want 2", count)
|
||||
}
|
||||
|
||||
// Upstream dumps may omit CPA catalog-required fields; counting must still work.
|
||||
count, err = countModels([]byte(`{"models":[{"slug":"gpt-5.6-sol"}]}`))
|
||||
if err != nil {
|
||||
t.Fatalf("countModels(incomplete upstream model): %v", err)
|
||||
}
|
||||
if count != 1 {
|
||||
t.Fatalf("countModels(incomplete upstream model) = %d, want 1", count)
|
||||
}
|
||||
|
||||
count, err = countModels([]byte(`{"models":[]}`))
|
||||
if err != nil {
|
||||
t.Fatalf("countModels(empty): %v", err)
|
||||
}
|
||||
if count != 0 {
|
||||
t.Fatalf("countModels(empty) = %d, want 0", count)
|
||||
}
|
||||
|
||||
if _, err := countModels([]byte(`{"models":`)); err == nil {
|
||||
t.Fatal("countModels(malformed) error = nil, want error")
|
||||
}
|
||||
if _, err := countModels([]byte(`{}`)); err == nil {
|
||||
t.Fatal("countModels(missing models) error = nil, want error")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user