Pulse/internal/ai/knowledge/store_test.go
rcourtman d2330cf405 refactor(ai): Remove over-engineered URL discovery service
Keep only the simple AI-powered approach:
- set_resource_url tool lets AI save discovered URLs
- Users ask AI directly: 'Find URLs for my containers'
- AI uses its intelligence to discover and set URLs

Removed:
- URLDiscoveryService (rigid port scanning)
- Bulk discovery API endpoints
- Frontend discovery button

The AI itself is smart enough to iterate through resources
and discover URLs when asked.
2025-12-10 08:35:24 +00:00

155 lines
3.8 KiB
Go

package knowledge
import (
"os"
"path/filepath"
"testing"
"time"
)
func TestFormatAllForContext_LimitsOutput(t *testing.T) {
// Create a temp directory for the test
tmpDir, err := os.MkdirTemp("", "knowledge-test")
if err != nil {
t.Fatalf("Failed to create temp dir: %v", err)
}
defer os.RemoveAll(tmpDir)
// Create store without encryption for simplicity
store, err := NewStore(tmpDir)
if err != nil {
t.Fatalf("Failed to create store: %v", err)
}
// Add more than maxGuests (10) guests with notes
for i := 0; i < 15; i++ {
guestID := filepath.Base(tmpDir) + "-guest-" + string(rune('A'+i))
err := store.SaveNote(guestID, "Guest-"+string(rune('A'+i)), "vm", "service", "Web Server", "http://example.com:8080")
if err != nil {
t.Fatalf("Failed to save note: %v", err)
}
// Small delay to ensure different UpdatedAt times
time.Sleep(10 * time.Millisecond)
}
// Get the formatted context
result := store.FormatAllForContext()
if result == "" {
t.Fatal("Expected non-empty result")
}
// Should mention it's truncated (15 guests but only 10 included)
if !contains(result, "/") {
t.Error("Expected truncation indicator (e.g., '10/15 notes') in output")
}
// Count how many guest sections we have (look for "### Guest-")
guestCount := countOccurrences(result, "### Guest-")
if guestCount > 10 {
t.Errorf("Expected at most 10 guests, got %d", guestCount)
}
// Should be under 8KB
if len(result) > 8500 {
t.Errorf("Result too large: %d bytes (expected < 8500)", len(result))
}
}
func TestFormatAllForContext_PrioritizesRecent(t *testing.T) {
tmpDir, err := os.MkdirTemp("", "knowledge-test")
if err != nil {
t.Fatalf("Failed to create temp dir: %v", err)
}
defer os.RemoveAll(tmpDir)
store, err := NewStore(tmpDir)
if err != nil {
t.Fatalf("Failed to create store: %v", err)
}
// Create an old guest first
err = store.SaveNote("old-guest", "OldGuest", "vm", "config", "Setting", "old value")
if err != nil {
t.Fatal(err)
}
time.Sleep(50 * time.Millisecond)
// Create a newer guest
err = store.SaveNote("new-guest", "NewGuest", "vm", "config", "Setting", "new value")
if err != nil {
t.Fatal(err)
}
result := store.FormatAllForContext()
// NewGuest should appear before OldGuest (more recently updated)
newIdx := indexOf(result, "NewGuest")
oldIdx := indexOf(result, "OldGuest")
if newIdx == -1 || oldIdx == -1 {
t.Fatalf("Both guests should be in result. newIdx=%d, oldIdx=%d", newIdx, oldIdx)
}
if newIdx > oldIdx {
t.Error("Expected NewGuest to appear before OldGuest (more recent)")
}
}
func TestFormatAllForContext_ByteLimit(t *testing.T) {
tmpDir, err := os.MkdirTemp("", "knowledge-test")
if err != nil {
t.Fatalf("Failed to create temp dir: %v", err)
}
defer os.RemoveAll(tmpDir)
store, err := NewStore(tmpDir)
if err != nil {
t.Fatalf("Failed to create store: %v", err)
}
// Create notes with very large content to trigger byte limit
largeContent := make([]byte, 2000)
for i := range largeContent {
largeContent[i] = 'x'
}
for i := 0; i < 10; i++ {
guestID := "large-guest-" + string(rune('A'+i))
err := store.SaveNote(guestID, "LargeGuest-"+string(rune('A'+i)), "vm", "learning", "Big Note", string(largeContent))
if err != nil {
t.Fatal(err)
}
}
result := store.FormatAllForContext()
// Should be capped at ~8KB (with some tolerance for headers)
if len(result) > 9000 {
t.Errorf("Result should be capped at ~8KB, got %d bytes", len(result))
}
}
// Helper functions
func contains(s, substr string) bool {
return indexOf(s, substr) != -1
}
func indexOf(s, substr string) int {
for i := 0; i <= len(s)-len(substr); i++ {
if s[i:i+len(substr)] == substr {
return i
}
}
return -1
}
func countOccurrences(s, substr string) int {
count := 0
for i := 0; i <= len(s)-len(substr); i++ {
if s[i:i+len(substr)] == substr {
count++
}
}
return count
}