Features
AI chat
AI chat is the product surface for AppAssistant: a dedicated /ai page, a global FAB drawer, streaming replies, conversation pin/truncate/bulk delete, and short-lived file attachments. The whole /ai/* authenticated group requires can-use-ai.
Related
Agent & tool model: AI assistant model. Imports, sync, webhook: AI imports & sync. Env/provider keys: AI configuration. HTTP: AI API & webhooks.
Access
| Item | Detail |
|---|---|
| Permission | can-use-ai (PermissionEnum::CanUseAi) |
| Routes | routes/ai.php — middleware auth, verified, permission:can-use-ai |
| Page controller | App\Http\Controllers\Ai\AiPageController |
| Frontend page | resources/js/pages/ai/index.tsx |
| FAB | resources/js/components/ai/ai-fab.tsx in app-sidebar-layout |
AI page
| Route | Name | Behavior |
|---|---|---|
GET /ai | ai.index | Conversation list (25, pinned first) + optional selection |
GET /ai/{conversation} | ai.show | Same page with selected conversation (UUID) |
GET /ai/status | ai.status | AiStatusController — cached local provider /models probe |
Props include normalized messages (content, tools, attachments). Empty assistant tool turns get AiToolTurnSummary.
FAB
- Exported as
AiFab, mounted in the app sidebar layout. - Shown only when the user has
can-use-ai. - Hidden on
/airoutes. - Drawer: status, presets, attachments, SSE chat via
streamAiChat→POST /ai/chat.
Ask AI
List pages (users, groups, files, collections, items, activity logs) expose Ask AI via AskAiButton (resources/js/components/ai/ask-ai-button.tsx):
| Behavior | Detail |
|---|---|
| Permission | Shown only when can-use-ai |
| Modes | icon (row) or labeled (bulk toolbar) |
| Action | Opens the FAB composer with a seeded prompt (openAiWithPrompt in resources/js/lib/ai-open.ts) |
| Send | Never auto-sends — the user reviews/edits and submits |
Bulk selection can seed multi-entity prompts (see tests/Browser/AiContextBulkBrowserTest.php).
Conversations
Controller: App\Http\Controllers\Ai\AiConversationController.
Models use laravel/ai conversation tables (agent_conversations / agent_conversation_messages via config/ai.php).
| Action | Route | Behavior |
|---|---|---|
| Index | GET /ai/conversations | List owned conversations |
| Store | POST /ai/conversations | Create |
| Show | GET /ai/conversations/{conversation} | Detail |
| Destroy | DELETE /ai/conversations/{conversation} | Delete one |
| Pin | POST /ai/conversations/{conversation}/pin | Toggle pinned_at null ↔ now() |
| Truncate | POST /ai/conversations/{conversation}/truncate | Body from_message_id (UUID); deletes that message and all later |
| Bulk destroy | POST /ai/conversations/bulk-destroy | Body ids (1–100 UUIDs); must be owned; deletes messages + conversations |
Chat streaming
| Item | Detail |
|---|---|
| Controller | App\Http\Controllers\Ai\AiChatController (invokable) |
| Route | POST /ai/chat (ai.chat) |
| Throttle | throttle:30,1 (30 requests / minute) |
| Agent | App\Ai\Agents\AppAssistant |
| Response | SSE text/event-stream, ends with [DONE] |
Validated body:
| Field | Rules |
|---|---|
message | Required, max 20000 |
conversation_id | Optional UUID |
attachment_ids | Optional, max 5 UUIDs |
Optional daily cap: config('ai.daily_prompt_limit') ← AI_DAILY_PROMPT_LIMIT (0 = off), counted from Spatie activity log_name=ai, event=ai_prompt.
Events may include { type: 'conversation', conversation_id } and { type: 'error', … }. Logging goes through App\Ai\Support\AiActivityLogger.
Attachments
| Item | Detail |
|---|---|
| Controller | App\Http\Controllers\Ai\AiChatAttachmentController |
| Route | POST /ai/attachments (ai.attachments.store) |
| Throttle | throttle:30,1 |
| Model | App\Models\AiChatAttachment |
Allowed extensions: csv, txt, xlsx, pdf (MIME allowlist matches those families).
| Limit | Value |
|---|---|
| Max size | MAX_BYTES = 5 * 1024 * 1024 (5 MiB) |
| TTL | TTL_HOURS = 24 |
| Disk | local |
Cleanup: scheduled ai:cleanup-attachments daily (routes/console.php).
Presets
Presets are static frontend prompt templates, not backend entities.
| Item | Detail |
|---|---|
| Definition | resources/js/lib/ai-action-presets.ts |
| Types | AiActionPreset, categories comuni | dati | file | admin | avanzate |
| List | AI_ACTION_PRESETS (~25 templates: CSV/Excel/URL import, dry-run, upsert, export, PDF→schema, files, roles/users/groups, audit, async import, scheduled sync, rollback, …) |
| Filter | filterAiActionPresets() — show when anyOf is empty or the user has any listed permission |
| UI | resources/js/components/ai/ai-action-presets-drawer.tsx |
Related suggested-action chips (tool results): resources/js/lib/ai-suggested-actions.ts.
Client helpers
| Helper | Path |
|---|---|
| Stream / chat API | resources/js/lib/ai-chat.ts |
| Components | resources/js/components/ai/* |
Source map
| Concern | Location |
|---|---|
| Page | app/Http/Controllers/Ai/AiPageController.php |
| Chat | app/Http/Controllers/Ai/AiChatController.php |
| Conversations | app/Http/Controllers/Ai/AiConversationController.php |
| Attachments | app/Http/Controllers/Ai/AiChatAttachmentController.php |
| Routes | routes/ai.php |
| UI | resources/js/pages/ai/index.tsx, components/ai/ai-fab.tsx, ask-ai-button.tsx, lib/ai-open.ts |