diff --git a/pkg/gateway/gateway.go b/pkg/gateway/gateway.go index c95f586d..ec519e45 100644 --- a/pkg/gateway/gateway.go +++ b/pkg/gateway/gateway.go @@ -205,18 +205,11 @@ func Run(debug bool, homePath, configPath string, allowEmptyStartup bool) (runEr publishGatewayEvent(agentLoop, runtimeevents.KindGatewayStart, startedAt, nil) fmt.Println("\n📦 Agent Status:") - startupInfo := agentLoop.GetStartupInfo() - toolsInfo := startupInfo["tools"].(map[string]any) - skillsInfo := startupInfo["skills"].(map[string]any) - fmt.Printf(" • Tools: %d loaded\n", toolsInfo["count"]) - fmt.Printf(" • Skills: %d/%d available\n", skillsInfo["available"], skillsInfo["total"]) + startupStatus := collectGatewayStartupStatus(agentLoop.GetStartupInfo()) + fmt.Printf(" • Tools: %d loaded\n", startupStatus.toolsCount) + fmt.Printf(" • Skills: %d/%d available\n", startupStatus.skillsAvailable, startupStatus.skillsTotal) - logger.InfoCF("agent", "Agent initialized", - map[string]any{ - "tools_count": toolsInfo["count"], - "skills_total": skillsInfo["total"], - "skills_available": skillsInfo["available"], - }) + logger.InfoCF("agent", "Agent initialized", startupStatus.logFields) runningServices, err := setupAndStartServices(cfg, agentLoop, msgBus, pidData.Token, listenResult) if err != nil { @@ -315,6 +308,54 @@ func preCheckConfig(cfg *config.Config) error { return nil } +type gatewayStartupStatus struct { + toolsCount int + skillsAvailable int + skillsTotal int + logFields map[string]any +} + +func collectGatewayStartupStatus(startupInfo map[string]any) gatewayStartupStatus { + status := gatewayStartupStatus{logFields: map[string]any{}} + + if toolsInfo, ok := startupInfo["tools"].(map[string]any); ok { + if count, ok := startupInfoInt(toolsInfo["count"]); ok { + status.toolsCount = count + status.logFields["tools_count"] = count + } + } + + if skillsInfo, ok := startupInfo["skills"].(map[string]any); ok { + if total, ok := startupInfoInt(skillsInfo["total"]); ok { + status.skillsTotal = total + status.logFields["skills_total"] = total + } + if available, ok := startupInfoInt(skillsInfo["available"]); ok { + status.skillsAvailable = available + status.logFields["skills_available"] = available + } + } + + return status +} + +func startupInfoInt(value any) (int, bool) { + switch v := value.(type) { + case int: + return v, true + case int32: + return int(v), true + case int64: + return int(v), true + case float32: + return int(v), true + case float64: + return int(v), true + default: + return 0, false + } +} + func executeReload( ctx context.Context, agentLoop *agent.AgentLoop, diff --git a/pkg/gateway/gateway_test.go b/pkg/gateway/gateway_test.go index ab3833ba..2eb8a25d 100644 --- a/pkg/gateway/gateway_test.go +++ b/pkg/gateway/gateway_test.go @@ -7,6 +7,7 @@ import ( "os" "os/exec" "path/filepath" + "reflect" "strings" "testing" "time" @@ -113,6 +114,93 @@ func TestGatewayRunStartupFailureHelper(t *testing.T) { os.Exit(0) } +func TestCollectGatewayStartupStatusHandlesMalformedInfo(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + startupInfo map[string]any + wantToolsCount int + wantSkillsAvailable int + wantSkillsTotal int + wantLogFields map[string]any + }{ + { + name: "missing info", + startupInfo: map[string]any{}, + wantLogFields: map[string]any{}, + }, + { + name: "wrong map shapes", + startupInfo: map[string]any{ + "tools": "unexpected", + "skills": []any{"unexpected"}, + }, + wantLogFields: map[string]any{}, + }, + { + name: "valid startup info", + startupInfo: map[string]any{ + "tools": map[string]any{ + "count": 3, + }, + "skills": map[string]any{ + "available": 2, + "total": 5, + }, + }, + wantToolsCount: 3, + wantSkillsAvailable: 2, + wantSkillsTotal: 5, + wantLogFields: map[string]any{ + "tools_count": 3, + "skills_available": 2, + "skills_total": 5, + }, + }, + { + name: "json number startup info", + startupInfo: map[string]any{ + "tools": map[string]any{ + "count": float64(4), + }, + "skills": map[string]any{ + "available": float64(1), + "total": float64(6), + }, + }, + wantToolsCount: 4, + wantSkillsAvailable: 1, + wantSkillsTotal: 6, + wantLogFields: map[string]any{ + "tools_count": 4, + "skills_available": 1, + "skills_total": 6, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + got := collectGatewayStartupStatus(tt.startupInfo) + if got.toolsCount != tt.wantToolsCount { + t.Fatalf("toolsCount = %d, want %d", got.toolsCount, tt.wantToolsCount) + } + if got.skillsAvailable != tt.wantSkillsAvailable { + t.Fatalf("skillsAvailable = %d, want %d", got.skillsAvailable, tt.wantSkillsAvailable) + } + if got.skillsTotal != tt.wantSkillsTotal { + t.Fatalf("skillsTotal = %d, want %d", got.skillsTotal, tt.wantSkillsTotal) + } + if !reflect.DeepEqual(got.logFields, tt.wantLogFields) { + t.Fatalf("logFields = %#v, want %#v", got.logFields, tt.wantLogFields) + } + }) + } +} + func TestPublishGatewayEvent(t *testing.T) { eventBus := runtimeevents.NewBus() t.Cleanup(func() {