Files
kandev/apps/backend/internal/backendapp/helpers_session_models_test.go
T
2026-08-25 15:36:00 +00:00

112 lines
3.3 KiB
Go

package backendapp
import (
"encoding/json"
"fmt"
"testing"
"github.com/kandev/kandev/internal/agent/runtime/lifecycle"
"github.com/kandev/kandev/internal/agentctl/types/streams"
"github.com/kandev/kandev/internal/task/models"
)
func TestAppendSessionModelsMessageFallsBackToPersistedFlatModels(t *testing.T) {
persistedModels := make([]streams.SessionModelInfo, 15)
for i := range persistedModels {
modelID := fmt.Sprintf("claude-model-%d", i+1)
persistedModels[i] = streams.SessionModelInfo{ModelID: modelID, Name: modelID}
}
session := &models.TaskSession{
ID: "session-1",
TaskID: "task-1",
Metadata: map[string]interface{}{
models.SessionMetaKeyACPModelState: lifecycle.SessionModelsSnapshot{
CurrentModelID: "claude-model-1",
Models: persistedModels,
},
},
}
liveState := &lifecycle.CachedModelState{CurrentModelID: "live-model"}
messages := appendSessionModelsMessageFromState(session.ID, session, liveState, nil)
if len(messages) != 1 {
t.Fatalf("messages = %d, want 1", len(messages))
}
var payload lifecycle.SessionModelsEventPayload
if err := json.Unmarshal(messages[0].Payload, &payload); err != nil {
t.Fatalf("decode session models payload: %v", err)
}
if len(payload.Models) != len(persistedModels) {
t.Fatalf("models = %d, want %d", len(payload.Models), len(persistedModels))
}
if payload.CurrentModelID != "live-model" {
t.Fatalf("current model = %q, want %q", payload.CurrentModelID, "live-model")
}
}
func TestAppendSessionModelsMessageKeepsLiveStateAuthoritative(t *testing.T) {
session := &models.TaskSession{
ID: "session-1",
TaskID: "task-1",
Metadata: map[string]interface{}{
models.SessionMetaKeyACPModelState: lifecycle.SessionModelsSnapshot{
CurrentModelID: "persisted-flat-model",
Models: []streams.SessionModelInfo{{
ModelID: "persisted-flat-model",
Name: "Persisted flat model",
}},
},
},
}
liveOptions := []streams.ConfigOption{{
Type: "select",
ID: "model",
CurrentValue: "live-config-model",
}}
tests := []struct {
name string
liveState *lifecycle.CachedModelState
wantConfigCount int
}{
{
name: "live config options",
liveState: &lifecycle.CachedModelState{
CurrentModelID: "live-config-model",
ConfigOptions: liveOptions,
},
wantConfigCount: len(liveOptions),
},
{
name: "settled empty catalog",
liveState: &lifecycle.CachedModelState{
CurrentModelID: "live-config-model",
ConfigOptionsSettled: true,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
messages := appendSessionModelsMessageFromState(session.ID, session, tt.liveState, nil)
if len(messages) != 1 {
t.Fatalf("messages = %d, want 1", len(messages))
}
var payload lifecycle.SessionModelsEventPayload
if err := json.Unmarshal(messages[0].Payload, &payload); err != nil {
t.Fatalf("decode session models payload: %v", err)
}
if len(payload.Models) != 0 {
t.Fatalf("models = %d, want 0", len(payload.Models))
}
if payload.CurrentModelID != tt.liveState.CurrentModelID {
t.Fatalf("current model = %q, want %q", payload.CurrentModelID, tt.liveState.CurrentModelID)
}
if len(payload.ConfigOptions) != tt.wantConfigCount {
t.Fatalf("config options = %d, want %d", len(payload.ConfigOptions), tt.wantConfigCount)
}
})
}
}