PAIPAI

useComposer()

Draft text and staged attachments for the next send.

useComposer is the text box. It holds the draft for the next send so useChat() can stay subscribed only to the transcript.

The draft belongs to the ThreadProvider. Every composer hook under that provider reads the same draft.

function Composer() {
  const composer = Assistant.useComposer();

  return (
    <form
      onSubmit={(event) => {
        event.preventDefault();
        void composer.submit();
      }}
    >
      <textarea
        value={composer.text}
        onChange={(event) => composer.setText(event.target.value)}
      />
      <button type="submit" disabled={!composer.canSubmit}>
        Send
      </button>
    </form>
  );
}

Import

const composer = Assistant.useComposer();

Package-root import { useComposer } from "@pai/react" follows the nearest ThreadProvider and does not retain one agent's send-option types.

Signature

function useComposer(): ComposerController<TContract>;

Returns

ComposerController

Extends ComposerActions.

text: string

Current draft.

attachments: readonly ComposerAttachmentItem[]

Files staged for the next submit().

fileId: string

filename?: string

mediaType?: string

previewUrl?: string

Local object URL for image thumbnails. Revoked on remove or submit.

uploading: boolean

True while at least one attachFiles upload is in flight.

canSubmit: boolean

False while a send is in flight or an upload has not finished.

ComposerActions

setText: (text: string) => void

Replace the draft.

attachFiles: (files: Iterable<Blob>) => Promise<void>

Upload through client.files.upload and stage. Accepts a FileList. Files from one call are staged only when every upload succeeds.

removeAttachment: (fileId: string) => void

Drop a staged file. Revokes its previewUrl if any.

submit: (event?, options?: SendOptions) => Promise<void>

Send the draft. Clears it on success and restores it on failure. A busy thread throws ThreadBusyError.

clientData?: TContract['clientData']

Per-send overlay. Prefer ThreadProvider clientData for the open document. See Identity.

useComposerActions()

Write-only half of the same draft. Use for suggestion chips so typing does not re-render the chip.

function useComposerActions(): ComposerActions<TContract>;
function Suggestion({ text }: { text: string }) {
  const actions = Assistant.useComposerActions();
  return (
    <button type="button" onClick={() => actions.setText(text)}>
      {text}
    </button>
  );
}

Learn more

On this page