|
5 | 5 | "encoding/json" |
6 | 6 | "errors" |
7 | 7 | "fmt" |
| 8 | + "os" |
| 9 | + "path/filepath" |
8 | 10 | "strings" |
9 | 11 | "sync" |
10 | 12 | "testing" |
@@ -471,6 +473,82 @@ func TestSetModelKeepsStateWhenPersistFails(t *testing.T) { |
471 | 473 | } |
472 | 474 | } |
473 | 475 |
|
| 476 | +func TestSetModelDoesNotRewriteGlobalSettings(t *testing.T) { |
| 477 | + home := t.TempDir() |
| 478 | + t.Setenv("HOME", home) |
| 479 | + |
| 480 | + configDir := filepath.Join(home, ".codebot") |
| 481 | + if err := os.MkdirAll(configDir, 0o755); err != nil { |
| 482 | + t.Fatalf("mkdir config dir: %v", err) |
| 483 | + } |
| 484 | + initial := `{ |
| 485 | + "provider": "openai", |
| 486 | + "model": "gpt-5.4", |
| 487 | + "small_model": "gpt-5.4", |
| 488 | + "providers": { |
| 489 | + "openai": {"api_key": "openai-key"}, |
| 490 | + "anthropic": {"api_key": "anthropic-key"} |
| 491 | + } |
| 492 | +}` |
| 493 | + settingsPath := filepath.Join(configDir, "settings.json") |
| 494 | + if err := os.WriteFile(settingsPath, []byte(initial), 0o600); err != nil { |
| 495 | + t.Fatalf("write settings: %v", err) |
| 496 | + } |
| 497 | + |
| 498 | + dir := t.TempDir() |
| 499 | + mgr := storage.NewManager(dir) |
| 500 | + store, err := mgr.Create(dir) |
| 501 | + if err != nil { |
| 502 | + t.Fatalf("create session: %v", err) |
| 503 | + } |
| 504 | + |
| 505 | + s := NewSession(SessionConfig{ |
| 506 | + Agent: agentcore.NewAgent(agentcore.WithModel(&stubChatModel{})), |
| 507 | + Store: store, |
| 508 | + Manager: mgr, |
| 509 | + Settings: config.Resolved{ |
| 510 | + Provider: "openai", |
| 511 | + Model: "gpt-5.4", |
| 512 | + Providers: map[string]config.ProviderConfig{ |
| 513 | + "openai": {APIKey: "openai-key"}, |
| 514 | + "anthropic": {APIKey: "anthropic-key"}, |
| 515 | + }, |
| 516 | + ContextWindow: 128000, |
| 517 | + AutoCompaction: false, |
| 518 | + MaxTurns: 30, |
| 519 | + }, |
| 520 | + Cwd: dir, |
| 521 | + CreateModel: func(_ string, _ string, _ string, _ string) (agentcore.ChatModel, error) { |
| 522 | + return &stubChatModel{}, nil |
| 523 | + }, |
| 524 | + }) |
| 525 | + t.Cleanup(s.Close) |
| 526 | + |
| 527 | + if err := s.SetModel("anthropic", "claude-sonnet-4-5"); err != nil { |
| 528 | + t.Fatalf("set model: %v", err) |
| 529 | + } |
| 530 | + |
| 531 | + got, err := config.LoadSettingsStrict(dir) |
| 532 | + if err != nil { |
| 533 | + t.Fatalf("load settings: %v", err) |
| 534 | + } |
| 535 | + if got.Provider != "openai" { |
| 536 | + t.Fatalf("provider rewritten: got %q want %q", got.Provider, "openai") |
| 537 | + } |
| 538 | + if got.Model != "gpt-5.4" { |
| 539 | + t.Fatalf("model rewritten: got %q want %q", got.Model, "gpt-5.4") |
| 540 | + } |
| 541 | + if got.SmallModel != "gpt-5.4" { |
| 542 | + t.Fatalf("small model rewritten: got %q want %q", got.SmallModel, "gpt-5.4") |
| 543 | + } |
| 544 | + if s.Provider() != "anthropic" { |
| 545 | + t.Fatalf("session provider not switched: got %q want %q", s.Provider(), "anthropic") |
| 546 | + } |
| 547 | + if s.ModelName() != "claude-sonnet-4-5" { |
| 548 | + t.Fatalf("session model not switched: got %q want %q", s.ModelName(), "claude-sonnet-4-5") |
| 549 | + } |
| 550 | +} |
| 551 | + |
474 | 552 | func TestResolveAndSetModelSupportsExplicitProviderSyntax(t *testing.T) { |
475 | 553 | t.Parallel() |
476 | 554 |
|
@@ -927,68 +1005,6 @@ func TestPromptDoesNotQueueTaskManagementReminderFromUserText(t *testing.T) { |
927 | 1005 | } |
928 | 1006 | } |
929 | 1007 |
|
930 | | -func TestTaskManagementReminderQueuedForUntrackedOrBroadWork(t *testing.T) { |
931 | | - t.Parallel() |
932 | | - |
933 | | - cases := []struct { |
934 | | - name string |
935 | | - store *localtools.TaskStore |
936 | | - run func(s *Session) |
937 | | - }{ |
938 | | - { |
939 | | - name: "missing task list", |
940 | | - store: localtools.NewTaskStore(), |
941 | | - run: func(s *Session) { |
942 | | - args := json.RawMessage(`{"path":"main.go"}`) |
943 | | - for i := 0; i < 3; i++ { |
944 | | - toolID := fmt.Sprintf("read-%d", i) |
945 | | - s.handleAgentEvent(agentcore.Event{Type: agentcore.EventToolExecStart, ToolID: toolID, Tool: "read", Args: args}) |
946 | | - s.handleAgentEvent(agentcore.Event{Type: agentcore.EventToolExecEnd, ToolID: toolID, Tool: "read"}) |
947 | | - } |
948 | | - }, |
949 | | - }, |
950 | | - { |
951 | | - name: "single broad task", |
952 | | - store: func() *localtools.TaskStore { |
953 | | - store := localtools.NewTaskStore() |
954 | | - store.Create("Implement the entire project", "An overly broad task", "Implementing the entire project", nil) |
955 | | - return store |
956 | | - }(), |
957 | | - run: func(s *Session) { |
958 | | - s.handleAgentEvent(agentcore.Event{Type: agentcore.EventToolExecStart, ToolID: "task-1", Tool: "task_create"}) |
959 | | - s.handleAgentEvent(agentcore.Event{Type: agentcore.EventToolExecEnd, ToolID: "task-1", Tool: "task_create"}) |
960 | | - editArgs := json.RawMessage(`{"file":"main.go"}`) |
961 | | - s.handleAgentEvent(agentcore.Event{Type: agentcore.EventToolExecStart, ToolID: "edit-1", Tool: "edit", Args: editArgs}) |
962 | | - s.handleAgentEvent(agentcore.Event{Type: agentcore.EventToolExecEnd, ToolID: "edit-1", Tool: "edit"}) |
963 | | - }, |
964 | | - }, |
965 | | - } |
966 | | - |
967 | | - for _, tc := range cases { |
968 | | - t.Run(tc.name, func(t *testing.T) { |
969 | | - ag := agentcore.NewAgent(agentcore.WithModel(&stubChatModel{})) |
970 | | - s := NewSession(SessionConfig{ |
971 | | - Agent: ag, |
972 | | - Settings: config.Resolved{MaxTurns: 30}, |
973 | | - Cwd: t.TempDir(), |
974 | | - TaskStore: tc.store, |
975 | | - }) |
976 | | - t.Cleanup(s.Close) |
977 | | - |
978 | | - s.beginTurn() |
979 | | - tc.run(s) |
980 | | - |
981 | | - msg := s.buildUserMessage(agentcore.TextBlock("continue")) |
982 | | - if len(msg.Content) != 2 { |
983 | | - t.Fatalf("expected one injected reminder plus user block, got %#v", msg.Content) |
984 | | - } |
985 | | - if !strings.Contains(msg.Content[0].Text, "<system-reminder>") { |
986 | | - t.Fatalf("expected injected system reminder, got %#v", msg.Content) |
987 | | - } |
988 | | - }) |
989 | | - } |
990 | | -} |
991 | | - |
992 | 1008 | func TestTaskManagementReminderSteersBeforeStopWithOpenInProgressTask(t *testing.T) { |
993 | 1009 | t.Parallel() |
994 | 1010 |
|
|
0 commit comments