task: task-1753636924-a1d4c708 - created
Change-Id: Ic78528c47ae38114b9b7504f1c4a76f95e93eb13
diff --git a/server/config/openai_test.go b/server/config/openai_test.go
new file mode 100644
index 0000000..bd53e9c
--- /dev/null
+++ b/server/config/openai_test.go
@@ -0,0 +1,202 @@
+package config
+
+import (
+ "context"
+ "os"
+ "testing"
+
+ "github.com/iomodo/staff/llm"
+ "github.com/iomodo/staff/llm/openai"
+)
+
+// TestOpenAIIntegration tests the OpenAI integration with real API calls
+// This test requires OPENAI_API_KEY environment variable to be set
+func TestOpenAIIntegration(t *testing.T) {
+ apiKey := os.Getenv("OPENAI_API_KEY")
+ if apiKey == "" {
+ t.Skip("OPENAI_API_KEY not set, skipping OpenAI integration test")
+ }
+
+ // Create OpenAI config
+ config := llm.Config{
+ Provider: llm.ProviderOpenAI,
+ APIKey: apiKey,
+ BaseURL: "https://api.openai.com/v1",
+ }
+
+ // Create OpenAI provider
+ factory := &openai.OpenAIFactory{}
+ provider, err := factory.CreateProvider(config)
+ if err != nil {
+ t.Fatalf("Failed to create OpenAI provider: %v", err)
+ }
+ defer provider.Close()
+
+ // Test chat completion
+ t.Run("ChatCompletion", func(t *testing.T) {
+ req := llm.ChatCompletionRequest{
+ Model: "gpt-3.5-turbo",
+ Messages: []llm.Message{
+ {
+ Role: llm.RoleSystem,
+ Content: "You are a helpful assistant.",
+ },
+ {
+ Role: llm.RoleUser,
+ Content: "Hello! Just say 'Hello from OpenAI' and nothing else.",
+ },
+ },
+ }
+
+ resp, err := provider.ChatCompletion(context.Background(), req)
+ if err != nil {
+ t.Fatalf("ChatCompletion failed: %v", err)
+ }
+
+ if len(resp.Choices) == 0 {
+ t.Fatal("No choices returned")
+ }
+
+ message := resp.Choices[0].Message
+ if message.Content == "" {
+ t.Fatal("Empty response content")
+ }
+
+ t.Logf("OpenAI Response: %s", message.Content)
+ })
+
+ // Test embeddings
+ t.Run("Embeddings", func(t *testing.T) {
+ req := llm.EmbeddingRequest{
+ Model: "text-embedding-ada-002",
+ Input: "Hello, world!",
+ }
+
+ resp, err := provider.CreateEmbeddings(context.Background(), req)
+ if err != nil {
+ t.Fatalf("CreateEmbeddings failed: %v", err)
+ }
+
+ if len(resp.Data) == 0 {
+ t.Fatal("No embeddings returned")
+ }
+
+ embedding := resp.Data[0]
+ if len(embedding.Embedding) == 0 {
+ t.Fatal("Empty embedding vector")
+ }
+
+ t.Logf("Embedding dimensions: %d", len(embedding.Embedding))
+ })
+}
+
+// TestConfigurationLoading tests the configuration loading functionality
+func TestConfigurationLoading(t *testing.T) {
+ // Create a temporary config file
+ configContent := `
+openai:
+ api_key: "test-key"
+ model: "gpt-4"
+
+github:
+ token: "test-token"
+ owner: "test-owner"
+ repo: "test-repo"
+
+agents:
+ - name: "ceo"
+ role: "CEO"
+ system_prompt_file: "operations/agents/ceo/system.md"
+
+tasks:
+ storage_path: "tasks/"
+`
+
+ // Write temp config file
+ tmpFile, err := os.CreateTemp("", "staff-config-*.yaml")
+ if err != nil {
+ t.Fatalf("Failed to create temp file: %v", err)
+ }
+ defer os.Remove(tmpFile.Name())
+
+ if _, err := tmpFile.WriteString(configContent); err != nil {
+ t.Fatalf("Failed to write config: %v", err)
+ }
+ tmpFile.Close()
+
+ // Test loading config
+ config, err := LoadConfig(tmpFile.Name())
+ if err != nil {
+ t.Fatalf("Failed to load config: %v", err)
+ }
+
+ // Validate loaded config
+ if config.OpenAI.APIKey != "test-key" {
+ t.Errorf("Expected API key 'test-key', got '%s'", config.OpenAI.APIKey)
+ }
+
+ if config.OpenAI.Model != "gpt-4" {
+ t.Errorf("Expected model 'gpt-4', got '%s'", config.OpenAI.Model)
+ }
+
+ if len(config.Agents) != 1 {
+ t.Errorf("Expected 1 agent, got %d", len(config.Agents))
+ }
+
+ if config.Agents[0].Name != "ceo" {
+ t.Errorf("Expected agent name 'ceo', got '%s'", config.Agents[0].Name)
+ }
+}
+
+// TestEnvironmentOverrides tests environment variable overrides
+func TestEnvironmentOverrides(t *testing.T) {
+ // Set environment variables
+ os.Setenv("OPENAI_API_KEY", "env-openai-key")
+ os.Setenv("GITHUB_TOKEN", "env-github-token")
+ defer func() {
+ os.Unsetenv("OPENAI_API_KEY")
+ os.Unsetenv("GITHUB_TOKEN")
+ }()
+
+ // Create a temporary config file
+ configContent := `
+openai:
+ api_key: "config-key"
+
+github:
+ token: "config-token"
+ owner: "test-owner"
+ repo: "test-repo"
+
+agents:
+ - name: "ceo"
+ role: "CEO"
+ system_prompt_file: "operations/agents/ceo/system.md"
+`
+
+ tmpFile, err := os.CreateTemp("", "staff-config-*.yaml")
+ if err != nil {
+ t.Fatalf("Failed to create temp file: %v", err)
+ }
+ defer os.Remove(tmpFile.Name())
+
+ if _, err := tmpFile.WriteString(configContent); err != nil {
+ t.Fatalf("Failed to write config: %v", err)
+ }
+ tmpFile.Close()
+
+ // Test loading config with env overrides
+ config, err := LoadConfigWithEnvOverrides(tmpFile.Name())
+ if err != nil {
+ t.Fatalf("Failed to load config: %v", err)
+ }
+
+ // Verify environment overrides
+ if config.OpenAI.APIKey != "env-openai-key" {
+ t.Errorf("Expected env API key 'env-openai-key', got '%s'", config.OpenAI.APIKey)
+ }
+
+ if config.GitHub.Token != "env-github-token" {
+ t.Errorf("Expected env GitHub token 'env-github-token', got '%s'", config.GitHub.Token)
+ }
+}
\ No newline at end of file