gpui-ai

Guide

Differences from gpui-component

This library is built on gpui-component. Here is what is new, what extends it, and what is upstream's own work inside something new.

gpui-ai is built on gpui-component, and is not a replacement for it. If you need a button, an input, a dialog or a dock, that is the library to reach for — this one does not wrap them and does not re-export them. What it adds is the layer above: the surfaces an application grows when a model is doing the work, where the data arrives while it is being drawn and a person has to be able to follow, check and stop it.

The line between the two moves, and this page moves with it: gpui-component has since grown chat parts of its own — a message scroller, an attachment surface, bubbles and markers — and where they meet something here, the row below says so rather than leaving you to find out.

Every component below says which of three things it is. The words are the library’s own, exported from the same place its API documentation comes from.

  • 21New. Built from primitives. Upstream has no component for the thing at all, or has one whose look cannot be brought into line with this library’s.
  • 3Extends. Upstream’s component does the work; this adds what an agent surface needs and hands the rest back.
  • 13Composes. An upstream component is mounted inside a surface upstream has no equivalent for — you could not reach it by configuring anything it ships.

There is no fourth kind. Nothing in the catalogue is an upstream component under a new name: the library re-exports none of them, so every page you can open is one of the three above. Button, icon, spinner and text rendering count as primitives here — nearly everything uses them, and counting them would put every component in one bucket and tell you nothing.

Every component

ComponentKind, and what it stands onWhat it adds, and why it is here
Progress
LoadingStateNewnot built on oneAn animated pixel grid with elapsed time, for waits long enough that a spinner stops meaning anything.
StatusBadgeNewnot built on oneOne status vocabulary - pending, running, completed, failed - mapped onto the theme's semantic colours once and shared by chips, task rows, tool calls and plan steps. Upstream's badge is a pill with no lifecycle in it.
ThinkingNewnot built on oneA reasoning trace that opens itself while it runs, follows the newest steps, holds the reader's place when they scroll back, and collapses to a single line when it settles.
OrbsNewnot built on oneAmbient motion for the moments when a model is alive but has nothing to show yet: one dot lattice, several choreographed personalities.
ContextMeterComposesProgressCircle, HoverCardHow much of the model's context window a conversation has spent, as a ring, a bar or plain text, with the tone changing as it fills and the numbers exposed semantically so the level never depends on colour alone.
Agent work
ToolChipNewnot built on oneThe compact form of the same thing, for a transcript that should not become a list of cards.
ToolCallNewnot built on oneOne invocation: name, summary, status, and on expansion the input sent, the output returned or the reason it failed, with Allow and Deny where a person has to decide. Groups fold a burst of them.
TaskRowNewnot built on oneLive status for long-running agent work.
SearchResultsNewnot built on oneWeb-search tool output: the query, its results, and the sources behind them.
TodoListNewnot built on oneThe plan an agent is working through, with completion arriving item by item.
ImageGenerationNewnot built on oneA picture revealed as it is produced rather than swapped in when it is done.
Readable output
StreamingTextComposesTextView, HoverCard, LinkMarkdown that arrives a token at a time, with citations that resolve on hover and follow-up suggestions underneath. Upstream renders markdown it already has.
CodeBlockComposeshighlighter, ClipboardUpstream's highlighting with a streaming reveal, so a block can be syntax-coloured while the model is still writing it, and copied while it is.
CodeDiffComposeshighlighter, ClipboardThe same, as a reviewable patch: accept and reject per hunk, with the decision handed back to the application.
SelectionActionsComposesTextViewState, PositionerActions anchored to a selection inside rendered Markdown, which needs the text view's own selection state rather than a copy of it.
Composites
ChatComposesTextarea, listA virtualized, controlled transcript: unread reconciliation, jump to latest, and an anchor that survives messages arriving off screen. Upstream now has a MessageScroller that follows the tail and holds the anchor too; what it leaves to the application is the meaning of unread, and what this adds above it is the transcript itself - streaming answers, tool calls, and the prompt bar under them.
SuggestionsNewnot built on oneThe prompts an assistant offers before it has been asked anything.
AttachmentStripNewnot built on oneFiles on their way into a prompt, with upload progress and failure shown per item. Upstream ships an Attachment of its own now, and is explicit that it is a composition primitive: it lays out a preview, a title and actions, and leaves upload state, retry and selection to the application. This owns that lifecycle, which is the part an agent surface cannot avoid.
ArtifactPanelComposestab::TabBarA generated document beside the conversation, with preview and source, a version switcher, and streamed content so the panel renders while the agent is still writing.
FineTuneCardComposesColorPicker, Slider, InputUpstream's own controls arranged as one controlled inspector that reports every change rather than owning it.
PromptBarComposesTextarea, PositionerNative text editing with the apparatus around it that makes a prompt: attachments, a context meter, a slash-command popup and a queue.
VoiceControlsNewnot built on oneIdle, listening, transcribing, speaking: a lifecycle no upstream control models.
MessageQueueNewnot built on oneMessages typed while the model was busy, and the means to clear them.
Navigation
CommandSearchExtendscommand::CommandStateStable-ID items over the native palette, so a result keeps its identity as the ranking moves under it and the selection does not jump to whatever now sits at that index.
SidebarNavExtendssidebar::SidebarMenuItemFlattens the tree into one virtualized list, so a section holding ten thousand items costs what the viewport shows rather than what the section holds. Adds a retained filter input, roving focus with tree semantics, and a rail that glides between its widths.
ThreadListComposesInput, Popover, PopupMenuConversations grouped into sections, with search, an archive toggle and a per-row overflow menu. Every intent goes back to the application rather than being acted on here.
Data tables
RecordsTableExtendstable::DataTableAdds controlled snapshots with stable row IDs, so a row keeps its identity when the data is replaced; progressive states drawn inside the grid; columns that divide the table's width; and a footer. Upstream's grid draws data that has arrived, and an agent's grid has to draw while it is still arriving.
DiffTableComposesRecordsTableBefore and after values for one proposal, with accept and reject per row. Reviewing a change an agent wants to make is a different surface from browsing data, even though both are grids.
FilterTableComposesRecordsTableFilter chips over a grid whose rows animate to their new places rather than cutting, so a reader can see what the filter did to the set they were looking at.
ComparisonTableNewnot built on oneA matrix rather than a data grid: rows are features, columns are the things compared, and every column header carries its own control. Bounded and virtualized, with columns that divide the width and titles that wrap.
Decisions
ApprovalCardNewnot built on oneOne decision about something already proposed, with the consequence stated and the tone matched to how far it reaches.
PlanCardNewnot built on oneThe steps an agent intends, each carrying the shared status vocabulary as it runs.
RecommendationCardNewnot built on oneA suggested next step with its reasoning, which a reader accepts or dismisses.
Evidence
ContextCardNewnot built on oneThe document, file or record an answer drew on, shown beside the answer.
InsightCardComposeschart::LineChartMetrics and a time series in a paged card, so an analytical answer arrives as evidence rather than as a paragraph about numbers.
Human in the loop
ChoiceGroupNewnot built on oneOne choice from a set, and one switch between two states. Upstream's radio and checkbox are styled on their outer frame only - the box, its radius, its fill and its size are fixed inside render - so a wrapped one arrives with a look no styling can bring into line with the controls beside it.
QuestionFlowNewnot built on oneThe short sequence an agent asks before it acts: one question at a time, the place in the sequence stated, and a way past a question that does not apply.

One extension that is not a component

ButtonLabelExt is the one place the library extends an upstream primitive in public API. Upstream’s label squeezes its glyphs into a one-em box; this composes the button’s child slot instead, so descenders and accents keep the theme’s leading. Everything else about the button — sizes, colours, focus, activation, disabled states — stays upstream’s.

Which library you want

If you are building an application interface — settings, forms, panels, menus — gpui-component is the whole answer and this library has nothing to add to it. If your interface has a model in it, the difference is not decoration: a grid that has to draw while its rows are still arriving, a transcript that keeps its place as messages land off screen, a tool call a person can allow or deny, a reasoning trace that folds itself away when it settles. Those are the 37 surfaces here, and each one names above what it is standing on.