input-804d0d — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited input-804d0d (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Composer area: rich-text input (Tiptap), send / stop / file-attach actions, and @mention / /command suggestion popups.
import {
ChatInput,
RichTextInput,
MentionList,
type ChatInputRef,
type RichTextInputRef,
type SuggestionConfig,
type SuggestionItem,
type MentionItem,
type SlashCommandItem
} from 'reachat';Main composer used inside <Chat>. Wraps RichTextInput and adds: file attachment (FileInput), send button, stop button (during streaming). Reads isLoading, disabled, sendMessage, stopMessage, fileUpload, activeSessionId from ChatContext.
| Prop | Type | Default | Description |
|---|---|---|---|
placeholder | string | 'Type a message...' | Editor placeholder |
defaultValue | string | — | Initial editor value |
allowedFiles | string[] | — | File extensions/MIME types — when set, the attach button is shown |
allowMultipleFiles | boolean | false | Allow selecting multiple files |
attachIcon | ReactElement | paperclip | Icon for the file button |
sendIcon | ReactElement | send | Icon for the send button |
stopIcon | ReactElement | stop | Icon for the stop button |
mentions | SuggestionConfig<MentionItem> | — | Configures @-trigger suggestions |
commands | SuggestionConfig<SlashCommandItem> | — | Configures /-trigger suggestions |
minHeight | number | 24 | Editor min height in px |
maxHeight | number | 200 | Editor max height in px (auto-expand) |
autoFocus | boolean | true | Auto-focus on mount and when activeSessionId changes |
onMessageChange | (value: string) => void | — | Fires on every keystroke with the current value |
className | string | — | Container class |
The send/stop buttons swap based on isLoading. Attach button only renders when allowedFiles?.length > 0.
const inputRef = useRef<ChatInputRef>(null);
<ChatInput
ref={inputRef}
placeholder="Ask anything..."
allowedFiles={['image/*', '.pdf']}
allowMultipleFiles
mentions={{
items: [
{ id: '1', label: 'John Doe', description: 'Engineer', icon: <Avatar /> }
]
}}
commands={{
items: [
{ id: 'help', label: 'Help', shortcut: 'Ctrl+H' },
{ id: 'search', label: 'Search', type: 'insert', value: 'search:' }
]
}}
onMessageChange={handleDraftChange}
/>interface ChatInputRef {
focus: () => void;
getValue: () => string;
setValue: (value: string) => void;
insertText: (text: string) => void;
}Standalone Tiptap-based editor used internally by ChatInput. Useful when building a custom composer.
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | — | Editor content |
placeholder | string | — | Placeholder text |
disabled | boolean | — | Disable editing |
autoFocus | boolean | true | Focus on mount |
minHeight | number | 24 | Min editor height |
maxHeight | number | 200 | Max editor height |
mentions | SuggestionConfig | — | @ trigger config |
commands | SuggestionConfig | — | / trigger config |
className | string | — | Editor class |
onChange | (value: string) => void | — | Value changed |
onSubmit | (value: string) => void | — | Enter pressed (Shift+Enter inserts a newline) |
RichTextInputRef exposes the same methods as ChatInputRef.
Built on Tiptap v3 with Document, Paragraph, Text, HardBreak, Placeholder, and Mention extensions; suggestion popups positioned via Floating UI's flip/shift middleware.
interface SuggestionItem {
id: string;
label: string;
description?: string;
icon?: ReactElement;
metadata?: Record<string, unknown>;
}
interface MentionItem extends SuggestionItem {
/** Custom value to insert; defaults to label. */
value?: string;
}
interface SlashCommandItem extends SuggestionItem {
shortcut?: string;
type?: 'insert' | 'action';
value?: string;
}
interface SuggestionConfig<T extends SuggestionItem = SuggestionItem> {
/** Trigger character (default: '@' for mentions, '/' for commands) */
trigger?: string;
/** Static items */
items?: T[];
/** Async search — return filtered items for the current query */
onSearch?: (query: string) => Promise<T[]> | T[];
/** Custom selection handler — receives the chosen item and an insertText callback */
onSelect?: (item: T, insertText: (text: string) => void) => void;
/** Cap on visible items (default: 10) */
maxResults?: number;
/** Custom row renderer */
renderItem?: (item: T, isHighlighted: boolean) => ReactNode;
/** Custom empty-state renderer */
renderEmpty?: (query: string) => ReactNode;
}mentions={{
items: [
{ id: '1', label: 'Alice', description: 'PM' },
{ id: '2', label: 'Bob', description: 'Eng' }
]
}}commands={{
onSearch: async query => {
const results = await api.searchCommands(query);
return results.map(r => ({ id: r.id, label: r.name, shortcut: r.hotkey }));
},
maxResults: 8
}}mentions={{
items: people,
renderItem: (item, isHighlighted) => (
<div className={isHighlighted ? 'bg-blue-100' : ''}>
<strong>@{item.label}</strong>
<small>{item.description}</small>
</div>
),
onSelect: (item, insertText) => insertText(`@[${item.label}](user:${item.id})`)
}}The popup component the editor renders for suggestions. Exposed for advanced users — most code only needs SuggestionConfig.
interface MentionListRef {
onKeyDown: (props: { event: KeyboardEvent }) => boolean;
}
interface MentionListProps {
items: SuggestionItem[];
command: (item: { id: string; label: string }) => void;
triggerChar: string;
config: SuggestionConfig;
query?: string;
}Keyboard: ↑/↓ moves selection, Enter/Tab inserts, Escape dismisses.
theme.input.{base, upload, input}
theme.input.actions.{base, send, stop}
theme.input.popup.{base, content, item, itemHighlighted, itemIcon, itemContent, itemLabel, itemDescription, itemShortcut, empty, loading}
theme.input.tag.{base, mention, command} // Inline pill styling for inserted mentions/commands
theme.input.editor.{base, container, placeholder}The following type aliases exist for backwards compatibility and will be removed in a future major:
MentionPluginConfig → use SuggestionConfig<MentionItem>SlashCommandPluginConfig → use SuggestionConfig<SlashCommandItem>InputPluginItem → use SuggestionItemInputTrigger<T> → use SuggestionConfig<T>~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.