package app import ( "context" "slices" "albedo/cli/internal/daemon" ) // historyPageRows is how many transcript rows Read asks for at a time. const historyPageRows = 200 // SessionTurns is the newest turns of a session's committed transcript. type SessionTurns struct { Session string `json:"session"` Events []daemon.StreamEvent `json:"events"` Running bool `json:"running"` } // Read answers the newest turns of a session, reading older transcript pages // until it has that many. A turn that is still running is not committed yet, // so Running says whether more is on its way. func (s *Service) Read(ctx context.Context, id string, turns int) (SessionTurns, error) { conn, err := s.Connect(ctx) if err != nil { return SessionTurns{}, err } id, err = resolveSession(ctx, conn, id) if err != nil { return SessionTurns{}, err } client := daemon.NewChatClient(conn, id) status, err := client.GetStatus(ctx) if err != nil { return SessionTurns{}, err } var pages [][]daemon.StreamEvent eventCount, turnCount := 0, 0 var before int64 for { page, err := client.History(ctx, before, historyPageRows) if err != nil { return SessionTurns{}, err } pages = append(pages, page.Events) eventCount += len(page.Events) turnCount += turnStarts(page.Events) if !page.More || turnCount >= turns { break } before = page.Before } events := make([]daemon.StreamEvent, 0, eventCount) for _, page := range slices.Backward(pages) { events = append(events, page...) } return SessionTurns{Session: id, Running: status.Running, Events: lastTurns(events, turns)}, nil } func turnStarts(events []daemon.StreamEvent) int { count := 0 for _, event := range events { if event.Type == daemon.EventUser { count++ } } return count } // lastTurns keeps the events from the start of the turns-th newest turn on. func lastTurns(events []daemon.StreamEvent, turns int) []daemon.StreamEvent { for i, event := range slices.Backward(events) { if event.Type != daemon.EventUser { continue } if turns--; turns == 0 { return events[i:] } } return events }