Log inGet started
Package

dotbot.plugin

README.md

transcript

The DotBot panel's transcript: a conversation's rows as the scroll area one tab draws.

local Transcript = require(".transcript")
local transcript = Transcript.new({
    source = Source,          -- traceOf / toolsRunIn, to read a tool answer; toolImage, to draw its pictures
    icons = { down = ..., right = ..., alert = ..., bot = ... },
    expanded = expandedRows,  -- which rows are open, by row key
    onToggle = function() expandEpoch += 1 end,
})
local node = transcript.render(tabId, messages, { conversation = convId })
MemberWhat it does
PAGE40: the rows a transcript draws before the "Show earlier messages" row, and how many more each press of it draws.
new(deps)A transcript over deps.source, deps.icons, deps.expanded and deps.onToggle; deps.pageSize overrides PAGE.
render(tabId, messages, opts?)The virtual scroll area holding the newest rows of messages, with a "Show earlier messages" row above them when there are more. opts.conversation names the conversation (a tab on a new one starts again at one page); opts.now is the clock a thinking row's seconds are read against. A run of a turn's work rows (thinking and tool calls) is drawn as one rounded card, each row a slice of it, so the rows stay the scroll area's own children. A usage line names its payer only on the first turn and where it differs from the turn before.
showEarlier(tabId)Draws one page more of the earlier rows on the next render.
stats(tabId)What the last render did: { rows, drawn, built, kept, hidden }.

Pictures

A tool row whose call returned pictures carries them as images: each { address, image, index, thumbWidth, thumbHeight, viewWidth, viewHeight, thumbKept, viewKept, thumbPath? }, where address is the conversation (<agent>/<id>) and image the picture's number in it. The row draws a thumbnail of each under its card, at most 160 by 90, read through source.toolImage(address, image, "thumb") unless thumbPath already names where it is. Clicking a thumbnail opens the larger copy ("view") under the card, at most 360 high; clicking it again closes it. A run of calls draws the pictures of all its calls.

The agents a turn started

newAgents(deps) builds the cards a tab draws above its composer for the agents its conversation's turns started. It takes a transcript's deps, with icons.term and icons.stop, plus onOpen(run, key) and onStop(run, key).

MemberWhat it does
render(key, runs, opts?)A grip to drag the section's height by, a heading naming how many agents are in each state, a failure in the failure hue (a press folds or opens the cards), with opts.usage (what the agents used together) at its right, then one line per agent, newest first: a dot and its state, its name, the tool it is in (or what it waits for, its answer, or why it failed; left off when it only repeats the state), its time worked (a queued agent shows none, and its line says how long it has waited), its Stop while it works and the arrow to its transcript. A press on what it is doing opens the line to its task, the whole of what it is doing, what it used, and the thumbnails of its newest AGENT_PICTURES pictures. The name and the arrow open its transcript. The section is as tall as its lines up to AGENTS_SHARE points, or to the height a person dragged it to (between AGENTS_MIN and AGENTS_MAX, kept per key), and scrolls past it; the earlier cards wait behind a "Show earlier agents" row at its end. Nil for no agents. opts.nowMs is the clock times are read against, and opts.conversation the conversation a fold is kept for.
folded(key, runs, conversation?) / setFolded(key, runs, conversation, folded)Whether the section is folded to its heading: as the person set it for that conversation since its agents last started or all ended, else open while an agent works and folded once every agent has ended; and setting it, as a press on the heading does.
showEarlier(key) / stats(key)One page more of the earlier cards, and what the last render did: { runs, drawn, built, kept, hidden, folded }.
AGENT_PAGE6: the cards drawn before the "Show earlier agents" row.
AGENTS_SHARE118: the height in points the section takes before its lines scroll, until a person drags it: its heading and about three agents.
AGENTS_MIN / AGENTS_MAX52 / 640: the least and the most the section can be dragged to.
agentHue(P, state)The hue a state is drawn in.

A card is kept, like a row, while what it shows is unchanged, so a status of one agent builds that card and no other.

What a redraw costs

Each row is drawn from what it shows: its text, its tool call and answer, whether it is open, a thinking row's seconds. A row that shows the same as it did last time keeps the subtree it already has, and its callbacks are carried into the new build (edui.app collectHandlers / adoptHandlers), so a delta streaming into the last answer builds that answer and nothing above it. A row holding a callback with no key is built fresh every time, because an unkeyed callback is numbered by the order a build reaches it.

Only the newest rows are drawn, so what a redraw costs is set by what is on screen rather than by how long the conversation is. The earlier rows are one press away and nothing is dropped.

Tested by src/lua/lib/tests/suites/dotbot_panel.testSuite.