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 init

Import 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-input

Props

PropTypeDefaultDescription
onSend(message, { signal }) => Promise<void>—Resolve when the answer is complete; Stop aborts signal. Throw to keep the draft.
maxLengthnumber8000Match 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.
labelsPartial<PromptInputLabels>—Every string, in the dictionary.
checkAttachment / safeFileName / uploadAttachmentlib—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.