Something went wrong. Try again.
small gleam coding and persistent agent daemon with a detachable cli and a canvas ui forked from okami.mom/albedo
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193// Command tuifixture captures one live session's transcript into the file the// chat benchmarks replay. It issues only the reads a TUI client makes when it// opens a session: the snapshot and the history pages. It never writes to the// daemon and never sends a prompt.//// ALBEDO_HOME=~/.albedo go run ./cmd/tuifixture -session <id> -out /tmp/fx.jsonpackage main
import ( "context" "encoding/json" "flag" "fmt" "os" "path/filepath" "time"
"albedo/cli/internal/config" "albedo/cli/internal/daemon" "albedo/cli/internal/localdaemon")
// capture is one session as the benchmarks replay it. The reset event a real// stream opens with is rebuilt from Session, because its snapshot carries// fields (glances, location) the wire type does not marshal.type capture struct { CapturedAt time.Time `json:"captured_at"` Session capturedSession `json:"session"` Tail []daemon.StreamEvent `json:"tail"` Full []daemon.StreamEvent `json:"full"`}
type capturedSession struct { ID string `json:"id"` Title string `json:"title"` Workspace string `json:"workspace"` Model string `json:"model"` Effort string `json:"effort"` Provider string `json:"provider"` TranscriptCount int `json:"transcript_count"` Status daemon.AgentStatus `json:"status"` Glances []daemon.PageGlance `json:"glances"` // Before is the first row the reset carried, and More whether rows precede it. Before int64 `json:"before"` More bool `json:"more"`}
func main() { if err := run(); err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) }}
func run() error { session := flag.String("session", "", "session id to capture") out := flag.String("out", "", "path to write the fixture to") pageRows := flag.Int("page", 200, "history rows per page read") tail := flag.Int("tail", 120, "history rows the opening stream carries") full := flag.Int("full", 4000, "history rows the full transcript keeps, 0 for all") flag.Parse() if *session == "" || *out == "" { flag.Usage() return fmt.Errorf("-session and -out are required") }
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) defer cancel()
home := config.HomeDir() found, err := localdaemon.Discover(ctx, home) if err != nil { return err } if found.Kind != localdaemon.Running { return fmt.Errorf("no running daemon under %s", home) } conn, err := daemon.Attach(ctx, found.Snapshot, nil) if err != nil { return err } defer conn.HTTPClient().CloseIdleConnections()
client := daemon.NewChatClient(conn, *session) snapshot, err := client.GetSession(ctx) if err != nil { return fmt.Errorf("read session: %w", err) }
// Newest page first, then backwards, so each page is prepended. var pages [][]daemon.StreamEvent before := int64(0) more := false rows := 0 for { historyPage, err := client.History(ctx, before, *pageRows) if err != nil { return fmt.Errorf("read history: %w", err) } pages = append(pages, historyPage.Events) rows += len(historyPage.Events) more = historyPage.More if !historyPage.More || historyPage.Before == 0 { break } before = historyPage.Before if *full > 0 && rows >= *full { break } }
var fullEvents []daemon.StreamEvent for i := len(pages) - 1; i >= 0; i-- { fullEvents = append(fullEvents, pages[i]...) } if *full > 0 && len(fullEvents) > *full { fullEvents = fullEvents[len(fullEvents)-*full:] } tailEvents := lastRows(fullEvents, *tail) tailStart := int64(0) for _, event := range tailEvents { if isRow(event) { tailStart = event.Position break } }
carried := capture{ CapturedAt: time.Now(), Session: capturedSession{ ID: snapshot.ID, Title: snapshot.Title, Workspace: snapshot.Workspace, Model: snapshot.Model, Effort: snapshot.Effort, Provider: snapshot.Provider, TranscriptCount: snapshot.TranscriptCount, Status: snapshot.Status, Glances: snapshot.Glances, Before: tailStart, More: more || len(tailEvents) < len(fullEvents), }, Tail: withoutReset(tailEvents), Full: withoutReset(fullEvents), } data, err := json.Marshal(carried) if err != nil { return err } if err := os.MkdirAll(filepath.Dir(*out), 0o755); err != nil { return err } if err := os.WriteFile(*out, data, 0o644); err != nil { return err } fmt.Fprintf(os.Stderr, "%s: %d rows, tail %d rows, %d bytes\n", snapshot.ID, len(carried.Full), len(carried.Tail), len(data)) return nil}
// lastRows keeps the newest rows of a transcript, with the committed stamps// that follow them, since a stream's tail counts transcript rows.func lastRows(events []daemon.StreamEvent, rows int) []daemon.StreamEvent { if rows <= 0 { return events } for at := len(events) - 1; at >= 0; at-- { if !isRow(events[at]) { continue } rows-- if rows == 0 { return events[at:] } } return events}
// isRow reports whether an event carries a transcript row rather than a stamp.func isRow(event daemon.StreamEvent) bool { switch event.Type { case daemon.EventUser, daemon.EventMessage, daemon.EventThinking, daemon.EventTool, daemon.EventNote, daemon.EventCompacted, daemon.EventError, daemon.EventTurnCompleted: return true } return false}
// withoutReset drops reset events: the benchmark rebuilds the opening reset// from the captured session so it carries the glances and status.func withoutReset(events []daemon.StreamEvent) []daemon.StreamEvent { kept := make([]daemon.StreamEvent, 0, len(events)) for _, evt := range events { if evt.Type == daemon.EventReset { continue } kept = append(kept, evt) } return kept}