Prompt Input
The composer for an agent chat: bounded text, attachments, a model picker and a send button that turns into stop.
Installation
Once per app, set up Aedis UI. The CLI verifies the signed release before writing anything and pins every dependency:
npx @aedis/cli@0.1.0 initImport the theme once in your global CSS, after Tailwind:
app/globals.css
@import "tailwindcss";@import "./styles/aedis-theme.css";Then add the component:
npx @aedis/cli@0.1.0 add prompt-input# pnpm dlx @aedis/cli@0.1.0 add prompt-input · yarn dlx @aedis/cli@0.1.0 add prompt-input · bunx @aedis/cli@0.1.0 add prompt-inputProps
| Prop | Type | Default | Description |
|---|---|---|---|
| onSend | (message, { signal }) => Promise<void> | — | Resolve when the answer is complete; Stop aborts signal. Throw to keep the draft. |
| maxLength | number | 8000 | Match your server limit. |
| attachments | { accept; maxBytes; uploadPath; maxFiles? } | — | Turns attachments on: MIME or extension allow-list, size limit, same-origin upload path (default 10 files). |
| models / model / onModelChange | { value; label }[] / string / (value) => void | — | Optional agent or model picker. |
| labels | Partial<PromptInputLabels> | — | Every string, in the dictionary. |
| checkAttachment / safeFileName / uploadAttachment | lib | — | The same rules for your own upload UI. |
Security
- Text is bounded and has hidden characters removed before it is sent.
- Attachments: type allow-list (an image/* wildcard never admits SVG), size and count limits, uploaded same-origin with X-Requested-With, redirects refused.
- File names are shown without bidi controls or control characters (RLO spoofing, T1036.002); files are never previewed, so an SVG is never inlined.
- Stop aborts the request through AbortController; cancel the work on the server through that same signal.
- The browser guesses a file's type from its name: the server must check the content again.