okami.mom/albedo

git clone https://git.nkp.pet/okami.mom/albedo

Aly Raffaufperf(cli): read history without the shuffle6cd888d

main
2.1 KiB81 linesraw
1package app
2
3import (
4	"context"
5	"slices"
6
7	"albedo/cli/internal/daemon"
8)
9
10// historyPageRows is how many transcript rows Read asks for at a time.
11const historyPageRows = 200
12
13// SessionTurns is the newest turns of a session's committed transcript.
14type SessionTurns struct {
15	Session string               `json:"session"`
16	Events  []daemon.StreamEvent `json:"events"`
17	Running bool                 `json:"running"`
18}
19
20// Read answers the newest turns of a session, reading older transcript pages
21// until it has that many. A turn that is still running is not committed yet,
22// so Running says whether more is on its way.
23func (s *Service) Read(ctx context.Context, id string, turns int) (SessionTurns, error) {
24	conn, err := s.Connect(ctx)
25	if err != nil {
26		return SessionTurns{}, err
27	}
28	id, err = resolveSession(ctx, conn, id)
29	if err != nil {
30		return SessionTurns{}, err
31	}
32	client := daemon.NewChatClient(conn, id)
33	status, err := client.GetStatus(ctx)
34	if err != nil {
35		return SessionTurns{}, err
36	}
37	var pages [][]daemon.StreamEvent
38	eventCount, turnCount := 0, 0
39	var before int64
40	for {
41		page, err := client.History(ctx, before, historyPageRows)
42		if err != nil {
43			return SessionTurns{}, err
44		}
45		pages = append(pages, page.Events)
46		eventCount += len(page.Events)
47		turnCount += turnStarts(page.Events)
48		if !page.More || turnCount >= turns {
49			break
50		}
51		before = page.Before
52	}
53	events := make([]daemon.StreamEvent, 0, eventCount)
54	for _, page := range slices.Backward(pages) {
55		events = append(events, page...)
56	}
57	return SessionTurns{Session: id, Running: status.Running, Events: lastTurns(events, turns)}, nil
58}
59
60func turnStarts(events []daemon.StreamEvent) int {
61	count := 0
62	for _, event := range events {
63		if event.Type == daemon.EventUser {
64			count++
65		}
66	}
67	return count
68}
69
70// lastTurns keeps the events from the start of the turns-th newest turn on.
71func lastTurns(events []daemon.StreamEvent, turns int) []daemon.StreamEvent {
72	for i, event := range slices.Backward(events) {
73		if event.Type != daemon.EventUser {
74			continue
75		}
76		if turns--; turns == 0 {
77			return events[i:]
78		}
79	}
80	return events
81}