This repository has been archived on 2026-04-03. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
core/server/capabilities/capabilities_test.go
2026-02-23 01:57:28 +00:00

196 lines
5.3 KiB
Go

package capabilities
import (
"testing"
"git.gobha.me/xcaliber/chat-switchboard/models"
)
func TestLookupKnownModel_ExactMatch(t *testing.T) {
caps, ok := LookupKnownModel("gpt-4o")
if !ok {
t.Fatal("expected gpt-4o to be found")
}
if caps.MaxOutputTokens != 16384 {
t.Errorf("gpt-4o max output: got %d, want 16384", caps.MaxOutputTokens)
}
if !caps.ToolCalling {
t.Error("gpt-4o should support tool calling")
}
if !caps.Vision {
t.Error("gpt-4o should support vision")
}
}
func TestLookupKnownModel_PrefixMatch(t *testing.T) {
caps, ok := LookupKnownModel("claude-sonnet-4-20250514")
if !ok {
t.Fatal("expected claude-sonnet-4-20250514 to match prefix claude-sonnet-4")
}
if caps.MaxOutputTokens != 16000 {
t.Errorf("claude-sonnet-4 max output: got %d, want 16000", caps.MaxOutputTokens)
}
}
func TestLookupKnownModel_ProviderPrefix(t *testing.T) {
caps, ok := LookupKnownModel("anthropic/claude-sonnet-4-20250514")
if !ok {
t.Fatal("expected provider-prefixed model to match")
}
if caps.MaxOutputTokens != 16000 {
t.Errorf("got %d, want 16000", caps.MaxOutputTokens)
}
}
func TestLookupKnownModel_NotFound(t *testing.T) {
_, ok := LookupKnownModel("totally-unknown-model-xyz")
if ok {
t.Error("expected unknown model to not be found")
}
}
func TestInferCapabilities_ToolCalling(t *testing.T) {
tests := []struct {
model string
want bool
}{
{"llama-3.1-70b-instruct", true},
{"mistral-7b", true},
{"qwen-2.5-72b", true},
{"phi-3-mini", true},
{"random-smallmodel", false},
}
for _, tt := range tests {
caps := InferCapabilities(tt.model)
if caps.ToolCalling != tt.want {
t.Errorf("InferCapabilities(%q).ToolCalling = %v, want %v", tt.model, caps.ToolCalling, tt.want)
}
}
}
func TestInferCapabilities_Vision(t *testing.T) {
caps := InferCapabilities("llava-v1.6-34b")
if !caps.Vision {
t.Error("llava should infer vision capability")
}
}
func TestInferCapabilities_Reasoning(t *testing.T) {
caps := InferCapabilities("deepseek-r1-distill-llama-70b")
if !caps.Reasoning {
t.Error("deepseek-r1 should infer reasoning capability")
}
}
func TestResolveMaxOutput_FromCaps(t *testing.T) {
caps := models.ModelCapabilities{MaxOutputTokens: 32000}
got := ResolveMaxOutput("whatever-model", caps)
if got != 32000 {
t.Errorf("got %d, want 32000", got)
}
}
func TestResolveMaxOutput_FromKnownTable(t *testing.T) {
caps := models.ModelCapabilities{}
got := ResolveMaxOutput("claude-opus-4-20250514", caps)
if got != 32000 {
t.Errorf("got %d, want 32000", got)
}
}
func TestResolveMaxOutput_FromContext(t *testing.T) {
caps := models.ModelCapabilities{MaxContext: 32768}
got := ResolveMaxOutput("unknown-model-abc", caps)
if got != 4096 {
t.Errorf("got %d, want 4096 (derived from context/8)", got)
}
}
func TestResolveMaxOutput_ContextClamp(t *testing.T) {
caps := models.ModelCapabilities{MaxContext: 1048576}
got := ResolveMaxOutput("unknown-large-model", caps)
if got != 16384 {
t.Errorf("got %d, want 16384 (clamped)", got)
}
caps = models.ModelCapabilities{MaxContext: 4096}
got = ResolveMaxOutput("unknown-tiny-model", caps)
if got != 2048 {
t.Errorf("got %d, want 2048 (clamped)", got)
}
}
func TestResolveMaxOutput_LastResort(t *testing.T) {
caps := models.ModelCapabilities{}
got := ResolveMaxOutput("mystery-model", caps)
if got != 4096 {
t.Errorf("got %d, want 4096 (last resort)", got)
}
}
func TestResolveIntrinsic(t *testing.T) {
// Provider reports tool_calling and max_output — these should be authoritative.
// Known table for claude-sonnet-4 has vision, thinking, etc — should fill gaps.
providerCaps := models.ModelCapabilities{
ToolCalling: true,
MaxOutputTokens: 16384,
}
merged := ResolveIntrinsic("claude-sonnet-4-20250514", &providerCaps)
if !merged.ToolCalling {
t.Error("tool_calling should be preserved from provider")
}
if merged.MaxOutputTokens != 16384 {
t.Errorf("max_output should be 16384 from provider, got %d", merged.MaxOutputTokens)
}
if !merged.Vision {
t.Error("vision should be filled from known table")
}
if merged.MaxContext == 0 {
t.Error("max_context should be filled from known table")
}
}
func TestResolveIntrinsic_ProviderFalseWins(t *testing.T) {
providerCaps := models.ModelCapabilities{
ToolCalling: true,
Vision: false,
MaxOutputTokens: 8192,
MaxContext: 65536,
}
merged := ResolveIntrinsic("some-unknown-model", &providerCaps)
if merged.Vision {
t.Error("vision should remain false — provider is authoritative")
}
}
func TestResolveIntrinsic_NilProvider(t *testing.T) {
// Nil provider caps — should fall through entirely to known table
merged := ResolveIntrinsic("gpt-4o", nil)
if !merged.ToolCalling {
t.Error("should get tool_calling from known table when provider is nil")
}
if !merged.Vision {
t.Error("should get vision from known table when provider is nil")
}
}
func TestHasProviderData(t *testing.T) {
empty := models.ModelCapabilities{}
if empty.HasProviderData() {
t.Error("empty caps should not have provider data")
}
withTool := models.ModelCapabilities{ToolCalling: true}
if !withTool.HasProviderData() {
t.Error("caps with tool_calling should have provider data")
}
withContext := models.ModelCapabilities{MaxContext: 128000}
if !withContext.HasProviderData() {
t.Error("caps with max_context should have provider data")
}
}