package tui import ( "strings" "albedo/cli/internal/daemon" ) const shotReply = `the footer was showing counts you can already see, so it now says when the daemon last polled. ## what changed - ` + "`counts()`" + ` is gone; ` + "`polled()`" + ` takes the newest reading - under a minute it reads **polled just now** ` + "```go" + ` func (m QuotaModel) polled() string { return "polled " + quotaSpan(age) + " ago" } ` + "```" + ` the screen does not tick, so the age is as of the fetch.` func init() { registerShots("chat", shotState{name: "transcript", view: func(w, h int) string { return renderTranscriptShot(w, h, nil, shotConversation()...) }}, shotState{name: "transcript-glances", view: func(w, h int) string { return renderTranscriptShot(w, h, shotGlances(), shotConversation()...) }}, shotState{name: "transcript-notes", view: func(w, h int) string { return renderTranscriptShot(w, h, nil, HistoryEntry{Kind: EntryUser, Speaker: "You", Text: "fan the review out to three children", Timestamp: 1}, HistoryEntry{Kind: EntryCompacted, Strategy: "rolling", Evicted: 42, Timestamp: 2}, HistoryEntry{Kind: EntryUser, MailKind: "letter", Speaker: "scout", Text: "done: 4 findings in /tmp/review/scout.md", Timestamp: 3}, HistoryEntry{Kind: EntryNote, Text: "dawn changed work item 12 to done", Timestamp: 4}, HistoryEntry{Kind: EntryError, Text: "provider returned 529: overloaded", Timestamp: 5}, HistoryEntry{Kind: EntryTurnEnd, Mood: moodFailed, ElapsedMs: 8200, Tools: 2, Timestamp: 6}, HistoryEntry{Kind: EntryUser, Speaker: "You", Text: "stop", Timestamp: 7}, HistoryEntry{Kind: EntryTurnEnd, Mood: moodStopped, ElapsedMs: 900, Timestamp: 8}, ) }}, shotState{name: "empty", view: func(w, h int) string { return renderTranscriptShot(w, h, nil) }}, shotState{name: "running-transcript", view: func(w, h int) string { return renderChatShot(w, h, shotRunning) }}, shotState{name: "queued", view: func(w, h int) string { return renderChatShot(w, h, func(m *ChatModel) { shotRunning(m) m.pendingUsers = []PendingUserTurn{ {OperationID: "op-1", Text: "and check the narrow layout", At: 7, Queued: true}, {OperationID: "op-2", Text: "then commit it", At: 8, Queued: true}, } }) }}, shotState{name: "composer-multiline", view: func(w, h int) string { return renderChatShot(w, h, func(m *ChatModel) { m.TextArea.SetValue("make the footer say when it polled\n\n- keep the counts out\n- under a minute, say just now") }) }}, shotState{name: "image-attached", view: func(w, h int) string { return renderChatShot(w, h, func(m *ChatModel) { image := daemon.ImageAttachment{ImageMetadata: daemon.ImageMetadata{MimeType: "image/png", Width: 1280, Height: 720}} m.TextArea.SetValue("why does the footer wrap here " + m.Images.add(pastedImage{ImageAttachment: image})) }) }}, shotState{name: "notice", view: func(w, h int) string { return renderChatShot(w, h, func(m *ChatModel) { m.AddNotice("Recovered the created session 01a172c2") }) }}, ) } // shotRunning starts a second turn after the conversation, with a cell running. func shotRunning(m *ChatModel) { m.Status = daemon.AgentStatus{Phase: &phaseTool, Running: true} m.appendSettledEntry(HistoryEntry{Kind: EntryUser, Speaker: "You", Text: "now make it tick once a minute", Timestamp: 7}) m.handleStreamEvent(daemon.StreamEvent{Type: daemon.EventToolProgress, Progress: &daemon.ToolProgress{ CallID: "p1", Name: "python", Phase: "running", Title: "vet and test the tui package", Code: &daemon.ToolCodePreview{Text: "# vet and test the tui package\nprint(1)"}, }}) } // renderChatShot is the conversation with setup applied after it, laid out // again for whatever setup put in the chrome. func renderChatShot(width, height int, setup func(*ChatModel)) string { conn := daemon.NewConnection(daemon.ConnectionSnapshot{Port: 1}, nil) session := &daemon.Session{ID: "s", Workspace: "/Users/dawn/proj/albedo", Model: "claude-opus-5-5", Provider: "claude"} m := NewChatModel(session, daemon.NewChatClient(conn, session.ID)) m.Status.Idle = true m.SetSize(width, height) for _, entry := range shotConversation() { m.appendSettledEntry(entry) } setup(&m) m.SetSize(width, height) return m.View() } func shotConversation() []HistoryEntry { return []HistoryEntry{ {Kind: EntryUser, Speaker: "You", Text: "what should the quota footer say instead of the counts?", Timestamp: 1}, {Kind: EntryThinking, Text: "the counts repeat what the rows show; freshness is what you cannot see", ElapsedMs: 4200, Timestamp: 2}, {Kind: EntryTool, ToolName: "python", ToolTitle: "read the quota view's footer", ToolArgs: map[string]any{"code": "# read the quota view's footer\nprint(1)"}, ToolResult: `{"status":"ok","output":"done"}`, Timestamp: 3}, {Kind: EntryTool, ToolName: "python", ToolTitle: "vet and test the tui package", ToolArgs: map[string]any{"code": "# vet and test the tui package\nprint(1)"}, ToolResult: `{"status":"ok","output":"ok"}`, ToolTrace: &daemon.ToolTrace{Activities: []daemon.ToolActivity{{Kind: "artifact", Target: "quota footer mockup", Artifact: &daemon.ArtifactActivity{ID: "a1", Version: 1}}}}, Timestamp: 4}, {Kind: EntryAssistant, Speaker: "albedo", Text: shotReply, Timestamp: 5}, {Kind: EntryTurnEnd, Mood: moodDone, ElapsedMs: 48000, Tools: 2, TokensPerSecond: 61, Timestamp: 6}, } } func shotGlances() []PageGlance { return []PageGlance{ {Title: "active work", Rows: []PageRow{{ID: "91", Text: "blockout review of every tui screen", Tone: ToneActive}}}, {Title: "open work", Rows: []PageRow{{ID: "89", Text: "license-dead accounts read as no license"}, {ID: "74", Text: "hydrant per-checkout crates"}}}, {Title: "vents", Rows: []PageRow{{ID: "21", Text: strings.Repeat("ssh master dies with its job ", 2), Tone: ToneMuted}}}, } } func renderTranscriptShot(width, height int, glances []PageGlance, entries ...HistoryEntry) string { conn := daemon.NewConnection(daemon.ConnectionSnapshot{Port: 1}, nil) session := &daemon.Session{ID: "s", Workspace: "/Users/dawn/proj/albedo", Model: "claude-opus-5-5", Provider: "claude"} m := NewChatModel(session, daemon.NewChatClient(conn, session.ID)) m.Glances = glances m.Status.Idle = true m.SetSize(width, height) for _, entry := range entries { m.appendSettledEntry(entry) } m.refreshViewportContent() return m.View() }