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>
);
}