1package loop
2
3import (
4 "context"
5 "os"
6 "testing"
7 "time"
8
9 "shelley.exe.dev/llm"
10 "shelley.exe.dev/llm/ant"
11)
12
13// TestLoopWithClaude tests the loop with actual Claude API if key is available
14func TestLoopWithClaude(t *testing.T) {
15 apiKey := os.Getenv("ANTHROPIC_API_KEY")
16 if apiKey == "" {
17 t.Skip("Skipping Claude integration test - ANTHROPIC_API_KEY not set")
18 }
19
20 // Create a simple conversation with Claude service
21 loop := NewLoop(Config{
22 LLM: &ant.Service{
23 APIKey: apiKey,
24 Model: ant.Claude45Haiku, // Use cheaper model for testing
25 },
26 History: []llm.Message{},
27 Tools: []*llm.Tool{},
28 RecordMessage: func(ctx context.Context, message llm.Message, usage llm.Usage) error {
29 // In a real app, this would save to database
30 t.Logf("Recorded %s message: %s", message.Role, message.Content[0].Text)
31 return nil
32 },
33 })
34
35 // Queue a simple user message
36 loop.QueueUserMessage(llm.UserStringMessage("Hello! Please respond with just 'Hi there!' and nothing else."))
37
38 // Run with a reasonable timeout
39 ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
40 defer cancel()
41
42 err := loop.Go(ctx)
43 if err != context.DeadlineExceeded {
44 t.Errorf("expected context deadline exceeded, got %v", err)
45 }
46
47 // Check that usage was tracked
48 usage := loop.GetUsage()
49 if usage.IsZero() {
50 t.Error("expected non-zero usage from Claude API")
51 }
52
53 t.Logf("Claude API usage: %s", usage.String())
54
55 // Check conversation history
56 history := loop.GetHistory()
57 if len(history) < 2 {
58 t.Errorf("expected at least 2 messages in history, got %d", len(history))
59 }
60
61 // First should be user message, second should be assistant
62 if history[0].Role != llm.MessageRoleUser {
63 t.Errorf("first message should be user, got %v", history[0].Role)
64 }
65
66 if len(history) > 1 && history[1].Role != llm.MessageRoleAssistant {
67 t.Errorf("second message should be assistant, got %v", history[1].Role)
68 }
69}