first commit
This commit is contained in:
@@ -0,0 +1,230 @@
|
||||
//go:build integration
|
||||
// +build integration
|
||||
|
||||
package integration
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"ai-agent/internal/agent"
|
||||
"ai-agent/internal/command"
|
||||
"ai-agent/internal/config"
|
||||
"ai-agent/internal/llm"
|
||||
"ai-agent/internal/mcp"
|
||||
"ai-agent/internal/tui"
|
||||
|
||||
tea "charm.land/bubbletea/v2"
|
||||
)
|
||||
|
||||
func skipIfNoOllama(t *testing.T) {
|
||||
if os.Getenv("OLLAMA_HOST") == "" {
|
||||
os.Setenv("OLLAMA_HOST", "http://localhost:11434")
|
||||
}
|
||||
client := llm.NewClient(llm.Config{
|
||||
BaseURL: os.Getenv("OLLAMA_HOST"),
|
||||
Model: "qwen3.5:2b",
|
||||
NumCtx: 262144,
|
||||
})
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
||||
defer cancel()
|
||||
if err := client.Ping(ctx); err != nil {
|
||||
t.Skip("Ollama not available: skipping integration test")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTUI_Initialization(t *testing.T) {
|
||||
skipIfNoOllama(t)
|
||||
reg := command.NewRegistry()
|
||||
command.RegisterBuiltins(reg)
|
||||
cfg := config.DefaultModelConfig()
|
||||
router := config.NewRouter(&cfg)
|
||||
modelManager := llm.NewModelManager("http://localhost:11434", 262144)
|
||||
modelManager.SetCurrentModel("qwen3.5:2b")
|
||||
ag := agent.New(modelManager, mcp.NewRegistry(), cfg.Ollama.NumCtx)
|
||||
ag.SetRouter(router)
|
||||
completer := tui.NewCompleter(reg, []string{"qwen3.5:2b"}, nil, nil, nil)
|
||||
m := tui.New(ag, reg, nil, completer, modelManager, router, nil)
|
||||
updated, _ := m.Update(tea.WindowSizeMsg{Width: 120, Height: 40})
|
||||
m = updated.(*tui.Model)
|
||||
if !m.Ready() {
|
||||
t.Error("TUI should be ready after WindowSizeMsg")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTUI_ScrollAnchorDuringStreaming(t *testing.T) {
|
||||
skipIfNoOllama(t)
|
||||
reg := command.NewRegistry()
|
||||
command.RegisterBuiltins(reg)
|
||||
cfg := config.DefaultModelConfig()
|
||||
router := config.NewRouter(&cfg)
|
||||
modelManager := llm.NewModelManager("http://localhost:11434", 262144)
|
||||
ag := agent.New(modelManager, mcp.NewRegistry(), 262144)
|
||||
ag.SetRouter(router)
|
||||
completer := tui.NewCompleter(reg, []string{"qwen3.5:2b"}, nil, nil, nil)
|
||||
m := tui.New(ag, reg, nil, completer, modelManager, router, nil)
|
||||
updated, _ := m.Update(tea.WindowSizeMsg{Width: 120, Height: 40})
|
||||
m = updated.(*tui.Model)
|
||||
if !m.AnchorActive() {
|
||||
t.Error("anchorActive should be true after initialization")
|
||||
}
|
||||
updated, _ = m.Update(tui.StreamTextMsg{Text: "Hello"})
|
||||
m = updated.(*tui.Model)
|
||||
if !m.AnchorActive() {
|
||||
t.Error("anchorActive should remain true during streaming")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTUI_OverlayRendering(t *testing.T) {
|
||||
reg := command.NewRegistry()
|
||||
command.RegisterBuiltins(reg)
|
||||
cfg := config.DefaultModelConfig()
|
||||
router := config.NewRouter(&cfg)
|
||||
modelManager := llm.NewModelManager("http://localhost:11434", 262144)
|
||||
ag := agent.New(modelManager, mcp.NewRegistry(), 262144)
|
||||
ag.SetRouter(router)
|
||||
completer := tui.NewCompleter(reg, []string{"qwen3.5:2b"}, nil, nil, nil)
|
||||
m := tui.New(ag, reg, nil, completer, modelManager, router, nil)
|
||||
updated, _ := m.Update(tea.WindowSizeMsg{Width: 120, Height: 40})
|
||||
m = updated.(*tui.Model)
|
||||
updated, _ = m.Update(tui.KeyPressMsg{Code: '?'})
|
||||
m = updated.(*tui.Model)
|
||||
view := m.View()
|
||||
if view == nil {
|
||||
t.Error("View should not be nil")
|
||||
}
|
||||
updated, _ = m.Update(tui.KeyPressMsg{Code: tea.KeyEscape})
|
||||
m = updated.(*tui.Model)
|
||||
}
|
||||
|
||||
func TestTUI_ToolCardRendering(t *testing.T) {
|
||||
reg := command.NewRegistry()
|
||||
command.RegisterBuiltins(reg)
|
||||
cfg := config.DefaultModelConfig()
|
||||
router := config.NewRouter(&cfg)
|
||||
modelManager := llm.NewModelManager("http://localhost:11434", 262144)
|
||||
ag := agent.New(modelManager, mcp.NewRegistry(), 262144)
|
||||
ag.SetRouter(router)
|
||||
completer := tui.NewCompleter(reg, []string{"qwen3.5:2b"}, nil, nil, nil)
|
||||
m := tui.New(ag, reg, nil, completer, modelManager, router, nil)
|
||||
updated, _ := m.Update(tea.WindowSizeMsg{Width: 120, Height: 40})
|
||||
m = updated.(*tui.Model)
|
||||
startTime := time.Now()
|
||||
updated, _ = m.Update(tui.ToolCallStartMsg{
|
||||
Name: "read_file",
|
||||
Args: map[string]any{"path": "test.go"},
|
||||
StartTime: startTime,
|
||||
})
|
||||
m = updated.(*tui.Model)
|
||||
updated, _ = m.Update(tui.ToolCallResultMsg{
|
||||
Name: "read_file",
|
||||
Result: "file content",
|
||||
IsError: false,
|
||||
Duration: 100 * time.Millisecond,
|
||||
})
|
||||
m = updated.(*tui.Model)
|
||||
view := m.View()
|
||||
if view == nil {
|
||||
t.Error("View should not be nil after tool execution")
|
||||
}
|
||||
}
|
||||
|
||||
func TestQwenRouter_Integration(t *testing.T) {
|
||||
cfg := config.DefaultModelConfig()
|
||||
router := config.NewQwenModelRouter(&cfg)
|
||||
tests := []struct {
|
||||
query string
|
||||
mode config.ModeContext
|
||||
expectSmaller string
|
||||
expectLarger string
|
||||
}{
|
||||
{"what is go?", config.ModeAskContext, "qwen3.5:2b", ""},
|
||||
{"design architecture", config.ModeBuildContext, "", "qwen3.5:4b"},
|
||||
{"plan the system", config.ModePlanContext, "", "qwen3.5:4b"},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.query, func(t *testing.T) {
|
||||
model := router.SelectModelForMode(tt.query, tt.mode)
|
||||
if tt.expectSmaller != "" {
|
||||
if modelRank(model) > modelRank(tt.expectSmaller) {
|
||||
t.Errorf("model %s is larger than expected %s", model, tt.expectSmaller)
|
||||
}
|
||||
}
|
||||
if tt.expectLarger != "" {
|
||||
if modelRank(model) < modelRank(tt.expectLarger) {
|
||||
t.Errorf("model %s is smaller than expected %s", model, tt.expectLarger)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func modelRank(model string) int {
|
||||
switch {
|
||||
case strings.Contains(model, "0.8b"):
|
||||
return 1
|
||||
case strings.Contains(model, "2b"):
|
||||
return 2
|
||||
case strings.Contains(model, "4b"):
|
||||
return 3
|
||||
case strings.Contains(model, "9b"):
|
||||
return 4
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileOperations_Integration(t *testing.T) {
|
||||
skipIfNoOllama(t)
|
||||
tmpDir := t.TempDir()
|
||||
testFile := filepath.Join(tmpDir, "test.txt")
|
||||
if err := os.WriteFile(testFile, []byte("hello world"), 0644); err != nil {
|
||||
t.Fatalf("failed to create test file: %v", err)
|
||||
}
|
||||
content, err := os.ReadFile(testFile)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to read test file: %v", err)
|
||||
}
|
||||
if string(content) != "hello world" {
|
||||
t.Errorf("unexpected file content: %q", string(content))
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkTUI_Render(b *testing.B) {
|
||||
reg := command.NewRegistry()
|
||||
command.RegisterBuiltins(reg)
|
||||
cfg := config.DefaultModelConfig()
|
||||
router := config.NewRouter(&cfg)
|
||||
modelManager := llm.NewModelManager("http://localhost:11434", 262144)
|
||||
ag := agent.New(modelManager, mcp.NewRegistry(), 262144)
|
||||
ag.SetRouter(router)
|
||||
completer := tui.NewCompleter(reg, []string{"qwen3.5:2b"}, nil, nil, nil)
|
||||
m := tui.New(ag, reg, nil, completer, modelManager, router, nil)
|
||||
updated, _ := m.Update(tea.WindowSizeMsg{Width: 120, Height: 40})
|
||||
m = updated.(*tui.Model)
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = m.View()
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkQwenRouter_Classification(b *testing.B) {
|
||||
cfg := config.DefaultModelConfig()
|
||||
router := config.NewQwenModelRouter(&cfg)
|
||||
queries := []string{
|
||||
"what is go",
|
||||
"how do i create a file",
|
||||
"debug this nil pointer error",
|
||||
"design microservice architecture",
|
||||
}
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
for _, q := range queries {
|
||||
_ = router.SelectModelForMode(q, config.ModeAskContext)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user