| 1 | package config |
| 2 | |
| 3 | import ( |
| 4 | "os" |
| 5 | "path/filepath" |
| 6 | "testing" |
| 7 | ) |
| 8 | |
| 9 | // A bare model name resolves to its first owner. Splitting an earlier account |
| 10 | // by route must not let a later account overtake models it never owned, on |
| 11 | // disk and for project references that are only resolved in memory. |
| 12 | func TestOpenCodeGoV10SplitKeepsBareModelOwnership(t *testing.T) { |
| 13 | home := t.TempDir() |
| 14 | t.Setenv("REASONIX_HOME", home) |
| 15 | t.Setenv("REASONIX_CREDENTIALS_STORE", "file") |
| 16 | t.Setenv("ACCOUNT_A_KEY", "test-account-a") |
| 17 | t.Setenv("ACCOUNT_B_KEY", "test-account-b") |
| 18 | path := filepath.Join(home, "config.toml") |
| 19 | if err := os.WriteFile(path, []byte(openCodeGoUpgradeFixture), 0o600); err != nil { |
| 20 | t.Fatal(err) |
| 21 | } |
| 22 | if _, err := ApplyUserConfigUpgradesOnStartup(path); err != nil { |
| 23 | t.Fatal(err) |
| 24 | } |
| 25 | var cfg Config |
| 26 | if _, err := decodeTOMLFile(path, &cfg); err != nil { |
| 27 | t.Fatal(err) |
| 28 | } |
| 29 | var names []string |
| 30 | for _, p := range cfg.Providers { |
| 31 | names = append(names, p.Name) |
| 32 | } |
| 33 | if len(names) != 5 || names[0] != "go" || names[1] != "go-chat-2" || names[4] != "go-chat" { |
| 34 | t.Fatalf("split groups did not follow their source: %v", names) |
| 35 | } |
| 36 | cfg.loadOpenCodeGoJournal(path) |
| 37 | for _, ref := range []string{"deepseek-v4-pro", "deepseek-v4-flash"} { |
| 38 | e, ok := cfg.ResolveModel(ref) |
| 39 | if !ok || e.APIKeyEnv != "ACCOUNT_A_KEY" || e.Name != "go-chat-2" { |
| 40 | t.Fatalf("bare %q changed account: %+v", ref, e) |
| 41 | } |
| 42 | } |
| 43 | |
| 44 | root := t.TempDir() |
| 45 | project := `default_model = "deepseek-v4-pro" |
| 46 | [agent] |
| 47 | planner_model = "go/deepseek-v4-flash" |
| 48 | ` |
| 49 | if err := os.WriteFile(filepath.Join(root, "reasonix.toml"), []byte(project), 0o600); err != nil { |
| 50 | t.Fatal(err) |
| 51 | } |
| 52 | merged, err := LoadForRoot(root) |
| 53 | if err != nil { |
| 54 | t.Fatal(err) |
| 55 | } |
| 56 | for _, ref := range []string{merged.DefaultModel, merged.Agent.PlannerModel} { |
| 57 | e, ok := merged.ResolveModel(ref) |
| 58 | if !ok || e.APIKeyEnv != "ACCOUNT_A_KEY" { |
| 59 | t.Fatalf("project ref %q resolved to another account: %+v", ref, e) |
| 60 | } |
| 61 | } |
| 62 | } |
| 63 |