mirror of
https://github.com/sipeed/picoclaw.git
synced 2026-07-28 01:27:58 +00:00
fix(gateway): guard startup info assertions
This commit is contained in:
+52
-11
@@ -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,
|
||||
|
||||
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user