ci / test (push) Successful in 1m14s
Replace Anthropic client with OpenAI-compatible client targeting https://api.riotpiao.com. Configure models: reasoning (Planner/Judge), ornith:35b (Implementer). Add health check on startup. Add Pi provider support for skill preparation (--pi-provider=local-llm). Files changed: - action/llm/client.go: OpenAI-compatible HTTP client + HealthCheck() - action/llm/client_test.go: Unit tests for model validation & health - cmd/starter/main.go: Health check before workflow, local model defaults - statemachine/types.go: PiProvider field for OrchestratorInput Models: - Planner: reasoning (smart decisions) - Judge: reasoning (quality review) - Implementer: ornith:35b (cheap execution) Skills: pi clone-or-fetch --provider=local-llm with 504 timeout learning. Verification: go build ./cmd/starter ./cmd/worker ./action/llm ✓ Tests: go test -v ./action/llm ✓ (all passing)
101 lines
2.4 KiB
Go
101 lines
2.4 KiB
Go
package llm
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/rockliang/poimen/workflows/statemachine"
|
|
)
|
|
|
|
func TestNewClient(t *testing.T) {
|
|
client, err := NewClient()
|
|
if err != nil {
|
|
t.Fatalf("failed to create client: %v", err)
|
|
}
|
|
if client == nil {
|
|
t.Fatal("client is nil")
|
|
}
|
|
}
|
|
|
|
func TestHealthCheck(t *testing.T) {
|
|
client, err := NewClient()
|
|
if err != nil {
|
|
t.Fatalf("failed to create client: %v", err)
|
|
}
|
|
|
|
// Skip if local LLM API not available
|
|
err = client.HealthCheck(context.Background())
|
|
if err != nil {
|
|
t.Logf("local LLM API not available (expected in test env): %v", err)
|
|
t.Skip("local LLM API health check failed - skipping integration test")
|
|
}
|
|
}
|
|
|
|
func TestSupportedModels(t *testing.T) {
|
|
tests := []struct {
|
|
model string
|
|
expected bool
|
|
}{
|
|
{"reasoning", true},
|
|
{"ornith:35b", true},
|
|
{"ornith:13b", true},
|
|
{"qwen2.5:3b", true},
|
|
{"unsupported-model", false},
|
|
{"", false},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.model, func(t *testing.T) {
|
|
if SupportedModels[tt.model] != tt.expected {
|
|
t.Errorf("model %q: expected %v, got %v", tt.model, tt.expected, SupportedModels[tt.model])
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCreateMessageValidation(t *testing.T) {
|
|
client, _ := NewClient()
|
|
|
|
tests := []struct {
|
|
name string
|
|
modelID string
|
|
wantErr bool
|
|
}{
|
|
{"valid reasoning", "reasoning", true}, // Will fail to connect, but validates model
|
|
{"valid ornith", "ornith:35b", true}, // Will fail to connect, but validates model
|
|
{"invalid model", "invalid-model", false}, // Should fail validation
|
|
{"empty model", "", false}, // Should fail validation
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
in := MessageInput{
|
|
Model: statemachine.ModelSpec{
|
|
ModelID: tt.modelID,
|
|
},
|
|
SystemPrompt: "test",
|
|
Messages: []MessageParam{
|
|
{Role: "user", Content: "test"},
|
|
},
|
|
}
|
|
|
|
_, err := client.CreateMessage(context.Background(), in)
|
|
|
|
hasErr := err != nil
|
|
if hasErr != tt.wantErr {
|
|
if tt.wantErr {
|
|
t.Logf("expected error for model %q (likely API not reachable): %v", tt.modelID, err)
|
|
} else if !hasErr {
|
|
t.Errorf("expected error for invalid model %q, but got none", tt.modelID)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestLocalLLMBaseURL(t *testing.T) {
|
|
if LocalLLMBaseURL != "https://api.riotpiao.com" {
|
|
t.Errorf("expected base URL https://api.riotpiao.com, got %s", LocalLLMBaseURL)
|
|
}
|
|
}
|