Files
BACKBEAT/cmd/agent-sim/main.go
2025-10-17 08:56:25 +11:00

101 lines
2.0 KiB
Go

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)
}
}