Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions internal/agents/chat.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,10 @@ Use assertions to verify specific fields in the response body:
{"field":"token","op":"contains","value":"Bearer"} — substring
Operators: eq, neq, exists, not_exists, contains, gt, gte, lt, lte

## ExportTests
Export API tests to formats strictly when the user requests it (e.g. "save to postman", "export tests to sh file").
Can export combinations of "postman", "pytest" or "sh".

## wait
Wait N seconds before proceeding. Use when:
- You receive a 429 status code
Expand Down
7 changes: 4 additions & 3 deletions internal/cli/tui.go
Original file line number Diff line number Diff line change
Expand Up @@ -324,9 +324,10 @@ func NewTestUIModel(baseURL string, specPath string, analysis *analyzer.Analysis
if cfg.LatestVersion != "" && updater.IsNewer(cfg.LatestVersion, version) {
model.latestVersion = cfg.LatestVersion
}
if cfg.Model != "" {
model.modelName = cfg.Model
}
}
_, _, _, activeModel := config.GetActiveLLMConfig()
if activeModel != "" {
model.modelName = activeModel
}

// Add header (logo + info)
Expand Down
7 changes: 0 additions & 7 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,13 +137,6 @@ func GetActiveLLMConfig() (provider, apiKey, baseURL, modelName string) {
if provider == "" {
provider = "claude"
}
if apiKey == "" {
if provider == "openai" || provider == "openrouter" {
apiKey = os.Getenv("OPENAI_API_KEY")
} else {
apiKey = os.Getenv("ANTHROPIC_API_KEY")
}
}

return provider, apiKey, baseURL, modelName
}
Expand Down
22 changes: 5 additions & 17 deletions internal/llm/claude/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"encoding/json"
"fmt"
"os"

"github.com/Octrafic/octrafic-cli/internal/infra/logger"

Expand Down Expand Up @@ -59,25 +58,14 @@ type Tool struct {
InputSchema map[string]interface{}
}

// NewClient creates a new Claude client (uses env vars)
func NewClient() (*Client, error) {
return NewClientWithConfig("", "")
}

// NewClientWithConfig creates a new Claude client with explicit API key and model
func NewClientWithConfig(apiKey, model string) (*Client, error) {
// NewClientWithConfig creates a new Claude client with explicit API key, model and base URL
func NewClientWithConfig(apiKey, model, baseURL string) (*Client, error) {
if apiKey == "" {
apiKey = os.Getenv("ANTHROPIC_API_KEY")
if apiKey == "" {
return nil, fmt.Errorf("ANTHROPIC_API_KEY not set")
}
return nil, fmt.Errorf("anthropic API key is required")
}

if model == "" {
model = os.Getenv("ANTHROPIC_MODEL")
if model == "" {
model = string(anthropic.ModelClaudeSonnet4_20250514)
}
model = string(anthropic.ModelClaudeSonnet4_20250514)
}

ctx := context.Background()
Expand All @@ -88,7 +76,7 @@ func NewClientWithConfig(apiKey, model string) (*Client, error) {
}

// Add custom base URL if provided (for proxies)
if baseURL := os.Getenv("ANTHROPIC_BASE_URL"); baseURL != "" {
if baseURL != "" {
opts = append(opts, option.WithBaseURL(baseURL))
}

Expand Down
2 changes: 1 addition & 1 deletion internal/llm/claude/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ type ClaudeProvider struct {

// NewClaudeProvider creates a new Claude provider
func NewClaudeProvider(config common.ProviderConfig) (*ClaudeProvider, error) {
client, err := NewClientWithConfig(config.APIKey, config.Model)
client, err := NewClientWithConfig(config.APIKey, config.Model, config.BaseURL)
if err != nil {
return nil, fmt.Errorf("failed to create Claude client: %w", err)
}
Expand Down
11 changes: 2 additions & 9 deletions internal/llm/gemini/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"encoding/base64"
"encoding/json"
"fmt"
"os"

"github.com/Octrafic/octrafic-cli/internal/infra/logger"

Expand Down Expand Up @@ -75,17 +74,11 @@ type Tool struct {
// NewClientWithConfig creates a new Gemini client with explicit API key and model.
func NewClientWithConfig(apiKey, model string) (*Client, error) {
if apiKey == "" {
apiKey = os.Getenv("GOOGLE_API_KEY")
if apiKey == "" {
return nil, fmt.Errorf("GOOGLE_API_KEY not set")
}
return nil, fmt.Errorf("gemini API key is required")
}

if model == "" {
model = os.Getenv("GEMINI_MODEL")
if model == "" {
model = "gemini-2.5-flash"
}
model = "gemini-2.5-flash"
}

ctx := context.Background()
Expand Down
23 changes: 3 additions & 20 deletions internal/llm/openai/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"fmt"
"io"
"net/http"
"os"
"strings"

"regexp"
Expand Down Expand Up @@ -191,28 +190,12 @@ type Client struct {
ctx context.Context
}

// NewClient creates a new client from environment variables
func NewClient() (*Client, error) {
apiKey := os.Getenv("OPENAI_API_KEY")
// NewClientWithConfig creates a new client with explicit configuration
func NewClientWithConfig(apiKey, model, baseURL string) (*Client, error) {
if apiKey == "" {
return nil, fmt.Errorf("OPENAI_API_KEY not set")
return nil, fmt.Errorf("openai API key is required")
}

model := os.Getenv("SEARCH_SPEC_MODEL")
if model == "" {
model = "gpt-4o-mini"
}

baseURL := os.Getenv("OPENAI_BASE_URL")
if baseURL == "" {
baseURL = "https://api.openai.com/v1"
}

return NewClientWithConfig(apiKey, model, baseURL)
}

// NewClientWithConfig creates a new client with explicit configuration
func NewClientWithConfig(apiKey, model, baseURL string) (*Client, error) {
if model == "" {
return nil, fmt.Errorf("model is required")
}
Expand Down