render

package
v0.29.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 30, 2026 License: CC0-1.0 Imports: 12 Imported by: 0

Documentation

Overview

Package render turns canonical session content into the HTML the sidepanel template ships. Assistant bodies are markdown on the wire — goldmark renders them safely; user and tool bodies stay escaped plain text with newlines preserved.

Index

Constants

View Source
const DividerThreshold = 30 * time.Second

DividerThreshold is the minimum gap between two surrounding non-grouped turns before GroupTurns inserts a "Worked for …" divider. 30 s skips the rapid-fire back-and-forth common to a real session and only surfaces the genuine pauses (long agent processing, human stepping away).

Variables

This section is empty.

Functions

func HumanDuration

func HumanDuration(d time.Duration) string

HumanDuration formats d into a short, human-readable label suitable for the sidepanel stats cluster ("18 min", "1h 30m", "4d") and the "Worked for …" divider between turn groups. Returns "—" when d <= 0 so callers can pass StartedAt/LastActivityAt deltas without guarding.

func Markdown

func Markdown(s string) template.HTML

Markdown renders s as a Markdown document and returns the HTML fragment. On any renderer error the input is escaped and returned verbatim so the panel still shows something legible.

func PlainText

func PlainText(s string) template.HTML

PlainText returns s HTML-escaped with newlines preserved as <br> so user prompts (which aren't markdown) keep their line breaks without enabling the rest of the markdown surface.

Types

type Turn

type Turn struct {
	Role       string
	Kind       string
	ToolName   string
	Ts         time.Time
	Body       template.HTML
	UserExtras *UserExtras
}

Turn is the render-ready shape for one canonical turn. Mirrors the fields the sidepanel template needs without dragging in the proto types. Body is pre-rendered HTML.

User turns also carry a structured UserExtras pointer when the content was wrapped in boilerplate (`<command-name>`, `<system-reminder>`, etc.). The template renders these as discrete chips / disclosure details so the bubble body stays focused on the human-authored prompt. Nil for non-user turns or for bare prompts with no wrappers.

type TurnGroup

type TurnGroup struct {
	Kind    string
	Turn    Turn
	Tools   []Turn
	Summary string
}

TurnGroup is one renderable block in the transcript. Either:

  • Kind == "single" → Turn is set, single bubble.
  • Kind == "tool-group" → Tools and Summary set, collapsible run of consecutive tool_result turns.
  • Kind == "thinking-group" → Tools and Summary set, collapsible run of consecutive thinking turns.
  • Kind == "divider" → Summary holds a "Worked for …" label inserted between turns separated by a meaningful time gap (see DividerThreshold).

func GroupTurns

func GroupTurns(in []Turn) []TurnGroup

GroupTurns walks in in order, coalescing maximal runs of Role=="tool" into one TurnGroup{Kind:"tool-group"} and maximal runs of Kind=="thinking" into TurnGroup{Kind:"thinking-group"}; everything else stays as TurnGroup{Kind:"single"}. The original order is preserved.

When the gap between two consecutive turns exceeds DividerThreshold (30s), an additional TurnGroup{Kind:"divider", Summary:"Worked for 2m 14s"} is inserted between them. Both turns must have a non-zero Ts for the divider to fire — zero-timestamp fixtures (and test inputs) stay divider-free.

type UserExtras

type UserExtras struct {
	Command                 string
	CommandArgs             string
	CommandMessage          string
	Reminders               []string
	EnvContext              string
	Instructions            string
	CollaborationMode       string
	PermissionsInstructions string
	LocalCommandCaveat      string
	LocalCommandStdout      string
	LocalCommandStderr      string
	// GoalBudget and GoalScaffold are the Codex goal wrapper parts kept
	// out of the bubble body (which shows the human objective). The
	// template surfaces each as a collapsible disclosure.
	GoalBudget   string
	GoalScaffold string
}

UserExtras mirrors the renderable parts of sessiontext.UserMessage without exposing that type through the template.

func (*UserExtras) HasDetails

func (e *UserExtras) HasDetails() bool

HasDetails reports whether any disclosure block (reminders, stdout, env_context, …) needs to be rendered below the bubble body.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL