Skip to content

Commit 2cec338

Browse files
committed
Implement per-supplier relay snapshots and UI cleanup
1 parent 51446f9 commit 2cec338

6 files changed

Lines changed: 595 additions & 176 deletions

File tree

docs/assets/screenshot-enhance.png

33.9 KB
Loading

main_test.go

Lines changed: 158 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ func TestLoadSettingsMigratesCurrentOfficialAuthToActiveProfile(t *testing.T) {
7676
}
7777
settings.ActiveRelayID = "second"
7878
writeTestFile(t, filepath.Join(home, ".codex", "auth.json"), fakeChatGPTAuthJSON(t, "active@example.com"))
79+
writeTestFile(t, filepath.Join(home, ".codex", "config.toml"), `model_provider = "openai"`+"\n")
7980
if err := atomicWriteJSON(settingsPath(), settings); err != nil {
8081
t.Fatalf("failed to write settings: %v", err)
8182
}
@@ -95,6 +96,12 @@ func TestLoadSettingsMigratesCurrentOfficialAuthToActiveProfile(t *testing.T) {
9596
if active.OfficialAuthContents == "" {
9697
t.Fatal("official auth contents should be migrated")
9798
}
99+
if active.AuthContents == "" {
100+
t.Fatal("auth contents should be migrated")
101+
}
102+
if active.ConfigContents == "" {
103+
t.Fatal("config contents should be migrated for active profile")
104+
}
98105
}
99106

100107
func TestRelayStatusDetectsBoundOfficialAuthWithoutCurrentAuthFile(t *testing.T) {
@@ -388,7 +395,6 @@ func TestOfficialModeWritesBoundOfficialAuth(t *testing.T) {
388395
t.Fatalf("failed to save settings: %v", err)
389396
}
390397
writeTestFile(t, filepath.Join(home, ".codex", "config.toml"), `model_provider = "CodexPlusPlus"`+"\n\n[model_providers.CodexPlusPlus]\nbase_url = \"https://api.example.com\"\n")
391-
392398
result := (&server{}).clearRelayInjection()
393399

394400
if result["status"] != "ok" {
@@ -404,6 +410,103 @@ func TestOfficialModeWritesBoundOfficialAuth(t *testing.T) {
404410
}
405411
}
406412

413+
func TestActivateOfficialAuthWritesBoundOfficialAuth(t *testing.T) {
414+
home := t.TempDir()
415+
t.Setenv("HOME", home)
416+
officialAuth := fakeChatGPTAuthJSON(t, "bound@example.com")
417+
currentAuth := fakeChatGPTAuthJSON(t, "current@example.com")
418+
writeTestFile(t, filepath.Join(home, ".codex", "auth.json"), currentAuth)
419+
settings := defaultSettings()
420+
settings.RelayProfiles = []relayProfile{{
421+
ID: "official",
422+
Name: "Official",
423+
RelayMode: "official",
424+
Protocol: "responses",
425+
OfficialAuthContents: officialAuth,
426+
OfficialAccountLabel: "bound@example.com",
427+
}}
428+
settings.ActiveRelayID = "official"
429+
if err := saveSettings(settings); err != nil {
430+
t.Fatalf("failed to save settings: %v", err)
431+
}
432+
433+
result := (&server{}).activateOfficialAuth(map[string]any{
434+
"request": map[string]any{"profileId": "official"},
435+
})
436+
437+
if result["status"] != "ok" {
438+
t.Fatalf("activate official auth should succeed: %#v", result)
439+
}
440+
status := chatGPTAuthStatus(filepath.Join(home, ".codex"))
441+
if !status.Authenticated || status.AccountLabel != "bound@example.com" {
442+
t.Fatalf("bound official auth was not activated: %#v", status)
443+
}
444+
}
445+
446+
func TestImportCurrentRelayFilesUpdatesTargetProfileSnapshot(t *testing.T) {
447+
home := t.TempDir()
448+
t.Setenv("HOME", home)
449+
writeTestFile(t, filepath.Join(home, ".codex", "config.toml"), "model_provider = \"openai\"\n")
450+
writeTestFile(t, filepath.Join(home, ".codex", "auth.json"), fakeChatGPTAuthJSON(t, "import@example.com"))
451+
settings := defaultSettings()
452+
settings.RelayProfiles = []relayProfile{{ID: "one", Name: "One", RelayMode: "official", Protocol: "responses"}}
453+
settings.ActiveRelayID = "one"
454+
if err := saveSettings(settings); err != nil {
455+
t.Fatalf("failed to save settings: %v", err)
456+
}
457+
458+
result := (&server{}).importCurrentRelayFiles(map[string]any{
459+
"request": map[string]any{"profileId": "one"},
460+
})
461+
462+
if result["status"] != "ok" {
463+
t.Fatalf("import current relay files should succeed: %#v", result)
464+
}
465+
loaded := loadSettings()
466+
profile := activeRelayProfile(loaded)
467+
if !strings.Contains(profile.ConfigContents, `model_provider = "openai"`) {
468+
t.Fatalf("config snapshot mismatch:\n%s", profile.ConfigContents)
469+
}
470+
if profile.AuthContents == "" || profile.OfficialAuthContents == "" {
471+
t.Fatalf("auth snapshot should be imported: %#v", profile)
472+
}
473+
if profile.OfficialAccountLabel != "import@example.com" {
474+
t.Fatalf("official account label mismatch: %q", profile.OfficialAccountLabel)
475+
}
476+
}
477+
478+
func TestClearRelayInjectionFallsBackToLegacyOfficialAuthContents(t *testing.T) {
479+
home := t.TempDir()
480+
t.Setenv("HOME", home)
481+
officialAuth := fakeChatGPTAuthJSON(t, "legacy@example.com")
482+
settings := defaultSettings()
483+
settings.RelayProfiles = []relayProfile{{
484+
ID: "legacy",
485+
Name: "Legacy",
486+
RelayMode: "official",
487+
Protocol: "responses",
488+
OfficialAuthContents: officialAuth,
489+
OfficialAccountLabel: "legacy@example.com",
490+
AuthContents: "",
491+
ConfigContents: "",
492+
}}
493+
settings.ActiveRelayID = "legacy"
494+
if err := saveSettings(settings); err != nil {
495+
t.Fatalf("failed to save settings: %v", err)
496+
}
497+
writeTestFile(t, filepath.Join(home, ".codex", "config.toml"), `model_provider = "CodexPlusPlus"`+"\n")
498+
499+
result := (&server{}).clearRelayInjection()
500+
501+
if result["status"] != "ok" {
502+
t.Fatalf("official switch should succeed with legacy auth fallback: %#v", result)
503+
}
504+
auth, _ := os.ReadFile(filepath.Join(home, ".codex", "auth.json"))
505+
if chatGPTAuthStatusFromContents(string(auth), "auth").AccountLabel != "legacy@example.com" {
506+
t.Fatalf("legacy official auth should be written to live auth.json, got:\n%s", string(auth))
507+
}
508+
}
509+
407510
func TestMixedModeWritesBoundOfficialAuthAndRelayConfig(t *testing.T) {
408511
home := t.TempDir()
409512
t.Setenv("HOME", home)
@@ -437,9 +540,13 @@ func TestMixedModeWritesBoundOfficialAuthAndRelayConfig(t *testing.T) {
437540
if !strings.Contains(string(config), `experimental_bearer_token = "relay-key"`) {
438541
t.Fatalf("mixed relay config missing bearer token:\n%s", string(config))
439542
}
543+
auth, _ := os.ReadFile(filepath.Join(home, ".codex", "auth.json"))
544+
if chatGPTAuthStatusFromContents(string(auth), "auth").AccountLabel != "mixed@example.com" {
545+
t.Fatalf("mixed relay should use profile auth snapshot, got:\n%s", string(auth))
546+
}
440547
}
441548

442-
func TestPureAPIModeKeepsOfficialBindingInactive(t *testing.T) {
549+
func TestPureAPIModeKeepsCurrentAuthWhenProfileSnapshotMissing(t *testing.T) {
443550
home := t.TempDir()
444551
t.Setenv("HOME", home)
445552
officialAuth := fakeChatGPTAuthJSON(t, "stored@example.com")
@@ -467,7 +574,7 @@ func TestPureAPIModeKeepsOfficialBindingInactive(t *testing.T) {
467574
t.Fatalf("pure API switch should succeed: %#v", result)
468575
}
469576
auth, _ := os.ReadFile(filepath.Join(home, ".codex", "auth.json"))
470-
if string(auth) != currentAuth {
577+
if chatGPTAuthStatusFromContents(string(auth), "auth").AccountLabel != "current@example.com" {
471578
t.Fatalf("pure API mode should preserve auth.json, got:\n%s", string(auth))
472579
}
473580
config, _ := os.ReadFile(filepath.Join(home, ".codex", "config.toml"))
@@ -480,6 +587,39 @@ func TestPureAPIModeKeepsOfficialBindingInactive(t *testing.T) {
480587
}
481588
}
482589

590+
func TestPureAPIModeWritesProfileAuthSnapshotWhenPresent(t *testing.T) {
591+
home := t.TempDir()
592+
t.Setenv("HOME", home)
593+
currentAuth := fakeChatGPTAuthJSON(t, "current@example.com")
594+
profileAuth := fakeChatGPTAuthJSON(t, "profile@example.com")
595+
writeTestFile(t, filepath.Join(home, ".codex", "auth.json"), currentAuth)
596+
settings := defaultSettings()
597+
settings.RelayProfiles = []relayProfile{{
598+
ID: "pure",
599+
Name: "Pure",
600+
BaseURL: "https://api.example.com",
601+
APIKey: "pure-key",
602+
RelayMode: "pureApi",
603+
Protocol: "responses",
604+
ConfigContents: buildTestRelayConfig("https://api.example.com", "pure-key"),
605+
AuthContents: profileAuth,
606+
}}
607+
settings.ActiveRelayID = "pure"
608+
if err := saveSettings(settings); err != nil {
609+
t.Fatalf("failed to save settings: %v", err)
610+
}
611+
612+
result := (&server{}).applyRelayInjection(true)
613+
614+
if result["status"] != "ok" {
615+
t.Fatalf("pure API switch should succeed: %#v", result)
616+
}
617+
auth, _ := os.ReadFile(filepath.Join(home, ".codex", "auth.json"))
618+
if chatGPTAuthStatusFromContents(string(auth), "auth").AccountLabel != "profile@example.com" {
619+
t.Fatalf("pure API should restore saved auth snapshot, got:\n%s", string(auth))
620+
}
621+
}
622+
483623
func TestPureAPIModeWritesImportedConfigWithoutAuthOverwrite(t *testing.T) {
484624
home := t.TempDir()
485625
t.Setenv("HOME", home)
@@ -513,7 +653,7 @@ func TestPureAPIModeWritesImportedConfigWithoutAuthOverwrite(t *testing.T) {
513653
t.Fatalf("pure API switch should succeed: %#v", result)
514654
}
515655
auth, _ := os.ReadFile(filepath.Join(home, ".codex", "auth.json"))
516-
if string(auth) != currentAuth {
656+
if chatGPTAuthStatusFromContents(string(auth), "auth").AccountLabel != "current@example.com" {
517657
t.Fatalf("pure API mode should preserve auth.json, got:\n%s", string(auth))
518658
}
519659
config, _ := os.ReadFile(filepath.Join(home, ".codex", "config.toml"))
@@ -586,6 +726,20 @@ func writeTestFile(t *testing.T, path, contents string) {
586726
}
587727
}
588728

729+
func buildTestRelayConfig(baseURL, apiKey string) string {
730+
return strings.Join([]string{
731+
`model_provider = "CodexPlusPlus"`,
732+
``,
733+
`[model_providers.CodexPlusPlus]`,
734+
`name = "CodexPlusPlus"`,
735+
`wire_api = "responses"`,
736+
`requires_openai_auth = true`,
737+
`base_url = "` + baseURL + `"`,
738+
`experimental_bearer_token = "` + apiKey + `"`,
739+
``,
740+
}, "\n")
741+
}
742+
589743
func fakeChatGPTAuthJSON(t *testing.T, email string) string {
590744
t.Helper()
591745
payload, err := json.Marshal(map[string]string{"email": email})

manager.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,8 +224,12 @@ func (s *server) dispatch(ctx context.Context, command string, args map[string]a
224224
return s.readRelayFiles()
225225
case "save_relay_file":
226226
return s.saveRelayFile(args)
227+
case "import_current_relay_files":
228+
return s.importCurrentRelayFiles(args)
227229
case "bind_official_auth":
228230
return s.bindOfficialAuth(args)
231+
case "activate_official_auth":
232+
return s.activateOfficialAuth(args)
229233
case "unbind_official_auth":
230234
return s.unbindOfficialAuth(args)
231235
case "clear_current_official_auth":

0 commit comments

Comments
 (0)