package main import ( "encoding/json" "flag" "fmt" "log" "math/rand" "os" "time" bb "github.com/chorus-services/backbeat/internal/backbeat" "github.com/nats-io/nats.go" "gopkg.in/yaml.v3" ) type scoreFile struct { Score bb.Score `yaml:"score"` } func main() { cluster := flag.String("cluster", "chorus-aus-01", "cluster id") agentID := flag.String("id", "bzzz-1", "agent id") scorePath := flag.String("score", "./configs/sample-score.yaml", "score yaml path") natsURL := flag.String("nats", nats.DefaultURL, "nats url") flag.Parse() buf, err := os.ReadFile(*scorePath) if err != nil { log.Fatal(err) } var s scoreFile if err := yaml.Unmarshal(buf, &s); err != nil { log.Fatal(err) } score := s.Score nc, err := nats.Connect(*natsURL) if err != nil { log.Fatal(err) } defer nc.Drain() hlc := bb.NewHLC(*agentID) state := "planning" waiting := 0 beatsLeft := 0 nc.Subscribe(fmt.Sprintf("backbeat.%s.beat", *cluster), func(m *nats.Msg) { var bf bb.BeatFrame if err := json.Unmarshal(m.Data, &bf); err != nil { return } phase, _ := bb.PhaseFor(score.Phases, int(bf.BeatIndex)) switch phase { case "plan": state = "planning" beatsLeft = 0 case "work": if waiting == 0 && rand.Float64() < 0.3 { waiting = 1 } if waiting > 0 { state = "waiting" beatsLeft = score.WaitBudget.Help - waiting waiting++ if waiting > score.WaitBudget.Help { state = "executing" waiting = 0 } } else { state = "executing" beatsLeft = 0 } case "review": state = "review" waiting = 0 beatsLeft = 0 } sc := bb.StatusClaim{ AgentID: *agentID, TaskID: "ucxl://demo/task", BeatIndex: bf.BeatIndex, State: state, WaitFor: nil, BeatsLeft: beatsLeft, Progress: rand.Float64(), Notes: "proto", HLC: hlc.Next(), } payload, _ := json.Marshal(sc) nc.Publish("backbeat.status."+*agentID, payload) }) log.Printf("AgentSim %s started (cluster=%s)\n", *agentID, *cluster) for { time.Sleep(10 * time.Second) } }