blob: 5f6b3faf8beacf15d5a73739e59dbbd743e59390 [file] [log] [blame]
user5a7d60d2025-07-27 21:22:04 +04001package config
2
3import (
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
14func 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
94func TestConfigurationLoading(t *testing.T) {
95 // Create a temporary config file
96 configContent := `
97openai:
98 api_key: "test-key"
99 model: "gpt-4"
100
101github:
102 token: "test-token"
103 owner: "test-owner"
104 repo: "test-repo"
105
106agents:
107 - name: "ceo"
108 role: "CEO"
109 system_prompt_file: "operations/agents/ceo/system.md"
110
111tasks:
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
152func 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 := `
163openai:
164 api_key: "config-key"
165
166github:
167 token: "config-token"
168 owner: "test-owner"
169 repo: "test-repo"
170
171agents:
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 }
iomodo50598c62025-07-27 22:06:32 +0400202}