| user | 5a7d60d | 2025-07-27 21:22:04 +0400 | [diff] [blame] | 1 | package config |
| 2 | |
| 3 | import ( |
| 4 | "context" |
| 5 | "os" |
| 6 | "testing" |
| 7 | |
| 8 | "github.com/iomodo/staff/llm" |
| 9 | "github.com/iomodo/staff/llm/openai" |
| 10 | ) |
| 11 | |
| 12 | // TestOpenAIIntegration tests the OpenAI integration with real API calls |
| 13 | // This test requires OPENAI_API_KEY environment variable to be set |
| 14 | func TestOpenAIIntegration(t *testing.T) { |
| 15 | apiKey := os.Getenv("OPENAI_API_KEY") |
| 16 | if apiKey == "" { |
| 17 | t.Skip("OPENAI_API_KEY not set, skipping OpenAI integration test") |
| 18 | } |
| 19 | |
| 20 | // Create OpenAI config |
| 21 | config := llm.Config{ |
| 22 | Provider: llm.ProviderOpenAI, |
| 23 | APIKey: apiKey, |
| 24 | BaseURL: "https://api.openai.com/v1", |
| 25 | } |
| 26 | |
| 27 | // Create OpenAI provider |
| 28 | factory := &openai.OpenAIFactory{} |
| 29 | provider, err := factory.CreateProvider(config) |
| 30 | if err != nil { |
| 31 | t.Fatalf("Failed to create OpenAI provider: %v", err) |
| 32 | } |
| 33 | defer provider.Close() |
| 34 | |
| 35 | // Test chat completion |
| 36 | t.Run("ChatCompletion", func(t *testing.T) { |
| 37 | req := llm.ChatCompletionRequest{ |
| 38 | Model: "gpt-3.5-turbo", |
| 39 | Messages: []llm.Message{ |
| 40 | { |
| 41 | Role: llm.RoleSystem, |
| 42 | Content: "You are a helpful assistant.", |
| 43 | }, |
| 44 | { |
| 45 | Role: llm.RoleUser, |
| 46 | Content: "Hello! Just say 'Hello from OpenAI' and nothing else.", |
| 47 | }, |
| 48 | }, |
| 49 | } |
| 50 | |
| 51 | resp, err := provider.ChatCompletion(context.Background(), req) |
| 52 | if err != nil { |
| 53 | t.Fatalf("ChatCompletion failed: %v", err) |
| 54 | } |
| 55 | |
| 56 | if len(resp.Choices) == 0 { |
| 57 | t.Fatal("No choices returned") |
| 58 | } |
| 59 | |
| 60 | message := resp.Choices[0].Message |
| 61 | if message.Content == "" { |
| 62 | t.Fatal("Empty response content") |
| 63 | } |
| 64 | |
| 65 | t.Logf("OpenAI Response: %s", message.Content) |
| 66 | }) |
| 67 | |
| 68 | // Test embeddings |
| 69 | t.Run("Embeddings", func(t *testing.T) { |
| 70 | req := llm.EmbeddingRequest{ |
| 71 | Model: "text-embedding-ada-002", |
| 72 | Input: "Hello, world!", |
| 73 | } |
| 74 | |
| 75 | resp, err := provider.CreateEmbeddings(context.Background(), req) |
| 76 | if err != nil { |
| 77 | t.Fatalf("CreateEmbeddings failed: %v", err) |
| 78 | } |
| 79 | |
| 80 | if len(resp.Data) == 0 { |
| 81 | t.Fatal("No embeddings returned") |
| 82 | } |
| 83 | |
| 84 | embedding := resp.Data[0] |
| 85 | if len(embedding.Embedding) == 0 { |
| 86 | t.Fatal("Empty embedding vector") |
| 87 | } |
| 88 | |
| 89 | t.Logf("Embedding dimensions: %d", len(embedding.Embedding)) |
| 90 | }) |
| 91 | } |
| 92 | |
| 93 | // TestConfigurationLoading tests the configuration loading functionality |
| 94 | func TestConfigurationLoading(t *testing.T) { |
| 95 | // Create a temporary config file |
| 96 | configContent := ` |
| 97 | openai: |
| 98 | api_key: "test-key" |
| 99 | model: "gpt-4" |
| 100 | |
| 101 | github: |
| 102 | token: "test-token" |
| 103 | owner: "test-owner" |
| 104 | repo: "test-repo" |
| 105 | |
| 106 | agents: |
| 107 | - name: "ceo" |
| 108 | role: "CEO" |
| 109 | system_prompt_file: "operations/agents/ceo/system.md" |
| 110 | |
| 111 | tasks: |
| 112 | storage_path: "tasks/" |
| 113 | ` |
| 114 | |
| 115 | // Write temp config file |
| 116 | tmpFile, err := os.CreateTemp("", "staff-config-*.yaml") |
| 117 | if err != nil { |
| 118 | t.Fatalf("Failed to create temp file: %v", err) |
| 119 | } |
| 120 | defer os.Remove(tmpFile.Name()) |
| 121 | |
| 122 | if _, err := tmpFile.WriteString(configContent); err != nil { |
| 123 | t.Fatalf("Failed to write config: %v", err) |
| 124 | } |
| 125 | tmpFile.Close() |
| 126 | |
| 127 | // Test loading config |
| 128 | config, err := LoadConfig(tmpFile.Name()) |
| 129 | if err != nil { |
| 130 | t.Fatalf("Failed to load config: %v", err) |
| 131 | } |
| 132 | |
| 133 | // Validate loaded config |
| 134 | if config.OpenAI.APIKey != "test-key" { |
| 135 | t.Errorf("Expected API key 'test-key', got '%s'", config.OpenAI.APIKey) |
| 136 | } |
| 137 | |
| 138 | if config.OpenAI.Model != "gpt-4" { |
| 139 | t.Errorf("Expected model 'gpt-4', got '%s'", config.OpenAI.Model) |
| 140 | } |
| 141 | |
| 142 | if len(config.Agents) != 1 { |
| 143 | t.Errorf("Expected 1 agent, got %d", len(config.Agents)) |
| 144 | } |
| 145 | |
| 146 | if config.Agents[0].Name != "ceo" { |
| 147 | t.Errorf("Expected agent name 'ceo', got '%s'", config.Agents[0].Name) |
| 148 | } |
| 149 | } |
| 150 | |
| 151 | // TestEnvironmentOverrides tests environment variable overrides |
| 152 | func TestEnvironmentOverrides(t *testing.T) { |
| 153 | // Set environment variables |
| 154 | os.Setenv("OPENAI_API_KEY", "env-openai-key") |
| 155 | os.Setenv("GITHUB_TOKEN", "env-github-token") |
| 156 | defer func() { |
| 157 | os.Unsetenv("OPENAI_API_KEY") |
| 158 | os.Unsetenv("GITHUB_TOKEN") |
| 159 | }() |
| 160 | |
| 161 | // Create a temporary config file |
| 162 | configContent := ` |
| 163 | openai: |
| 164 | api_key: "config-key" |
| 165 | |
| 166 | github: |
| 167 | token: "config-token" |
| 168 | owner: "test-owner" |
| 169 | repo: "test-repo" |
| 170 | |
| 171 | agents: |
| 172 | - name: "ceo" |
| 173 | role: "CEO" |
| 174 | system_prompt_file: "operations/agents/ceo/system.md" |
| 175 | ` |
| 176 | |
| 177 | tmpFile, err := os.CreateTemp("", "staff-config-*.yaml") |
| 178 | if err != nil { |
| 179 | t.Fatalf("Failed to create temp file: %v", err) |
| 180 | } |
| 181 | defer os.Remove(tmpFile.Name()) |
| 182 | |
| 183 | if _, err := tmpFile.WriteString(configContent); err != nil { |
| 184 | t.Fatalf("Failed to write config: %v", err) |
| 185 | } |
| 186 | tmpFile.Close() |
| 187 | |
| 188 | // Test loading config with env overrides |
| 189 | config, err := LoadConfigWithEnvOverrides(tmpFile.Name()) |
| 190 | if err != nil { |
| 191 | t.Fatalf("Failed to load config: %v", err) |
| 192 | } |
| 193 | |
| 194 | // Verify environment overrides |
| 195 | if config.OpenAI.APIKey != "env-openai-key" { |
| 196 | t.Errorf("Expected env API key 'env-openai-key', got '%s'", config.OpenAI.APIKey) |
| 197 | } |
| 198 | |
| 199 | if config.GitHub.Token != "env-github-token" { |
| 200 | t.Errorf("Expected env GitHub token 'env-github-token', got '%s'", config.GitHub.Token) |
| 201 | } |
| iomodo | 50598c6 | 2025-07-27 22:06:32 +0400 | [diff] [blame] | 202 | } |