Skip to content

Rich composer

The desktop app's Tiptap composer as a React component, with completions, typed badges, ghost text, prompt modes, history, attachments and a draft shared across windows, over a composer host.

zidane-ui/chat/rich-composer holds the desktop app's composer: RichComposer. It completes @ files, / commands and skills, # chats and extension triggers, shows links and commands as badges while you type, offers ghost text and the next prompt, has a shell mode (!) and a transcript search mode (?), recalls earlier prompts with ↑ / ↓, stages attachments, and shares its draft with every window on the same session. It reads a ComposerHost. Sending stays yours: onSend gets the text, the attachments and the skills it activates.

It is its own entry point, so an app that uses only Composer never loads it. The previews below run on the fixture host. Type / or @ to open a popover, or git sta to see ghost text.

New chat: type / or @ for the popovers
A session's shared draft, from the host
A run in flight: Send turns into Stop
No folder picked yet

Mount it#

Wrap the composer in a ComposerHostProvider and a PromptHistoryProvider (both from zidane-ui/chat/composer). Pass the session, the folder, and what sending does.

TSX
import 'zidane-ui/styles.css'
import { ComposerHostProvider, PromptHistoryProvider } from 'zidane-ui/chat/composer'
import { RichComposer } from 'zidane-ui/chat/rich-composer'

export function Prompt({ host, sessionId, folder, send }) {
  return (
    <ComposerHostProvider host={host}>
      <PromptHistoryProvider>
        <RichComposer
          disabled={false}
          folderPath={folder}
          activeSessionId={sessionId}
          hostId={null}
          onSend={(text, attachments, skills) => send({ text, attachments, skills })}
          inlineAutocomplete
        />
      </PromptHistoryProvider>
    </ComposerHostProvider>
  )
}

AppHostProvider (zidane-ui/app) puts host.composer in a ComposerHostProvider for you. Reject from onSend to put the prompt back in an empty composer.

Slots and options:

  • leadingActions and trailingActions sit beside the + button and before Send (the desktop app puts its pickers and status pills there). badges is the band above the card. footer sits in the tray under it.
  • attachmentsEnabled, inlineAutocomplete and promptSuggestions turn the attachment folding, the ghost text and the next-prompt ghost on or off.
  • scopeKey names the composer on the composer bus (pushComposerPrompt, pushComposerAttachment, pushComposerMention from zidane-ui/chat/composer), so a panel can push content into it.
  • commandArgs shares the commands' argument values with the rest of your app, siteIcons draws favicons in link badges, and attachmentLabel and textPreview set how attachment tiles and text previews look.
  • The search mode reports its query with onSearchQueryChange and takes the match counter back as searchStatus.

Pick a host#

HostFromTalks to
createServerComposerHost({ client })zidane-ui/adapterszidane-server. Pass the client of your chat host (createServerHost(…).client).
createFixtureComposerHost(options)zidane-ui/chat/testingMemory, for demos and tests.
Your ownzidane-ui/chat/headlessAnything that implements ComposerHost.

zidane-server runs the extensions' completions (completions.providers, completions.suggest, completions.submit), so the server host offers the extension members. @ lists a folder's files on the server (files.list, read again after a tool result), # its sessions (sessions.listMeta, read again on sessions:changed), and completions.locationOf is the folder's checkout and project there (files.location). It has no call to resolve ghost text for a new chat: the server host answers none before the chat has a session.

What a host offers#

Every member is optional. A member you leave out turns off what needs it.

MemberWhat it doesLeft out
draftsThe draft per session, its staged files, and the edits other windows makeEach window keeps its own draft
completions.filesThe files @ lists@ lists nothing
completions.commands, commandArgsThe / commands and their argument values/ lists skills only
completions.chatsThe sessions # can reference# lists nothing
completions.watchSkillsThe enabled skills, as they change/ lists commands only
completions.watchExtensionProviders, extensionItems, submitExtension completion triggers, their items, and their submit hooksNo extension popovers
completions.locationOfA folder's checkout and project roots# cannot scope to the project
autocompleteGhost text, and ghost text another window resolvedNo ghost text
suggestionsThe next prompt once a run ends, and when it goes staleNo next-prompt ghost

The contract every implementation runs is describeComposerHostContract in zidane-ui/chat/testing/contract.