Features

AI imports & sync

Beyond chat, the assistant can import collection rows from attachments or remote JSON, export data, extract PDF text, schedule sync sources, and roll back the last AI mutation turn. Async work is tracked as import jobs; an external webhook can enqueue the same pipeline with AI_WEBHOOK_TOKEN.

Related

Chat UI & attachments: AI chat. Tool registration gates: AI assistant model. Env keys: AI configuration. Routes: AI API & webhooks.

Tools

Registered on App\Ai\Agents\AppAssistant when the user holds the matching permission (then re-checked inside the tool).

Tool classGateRole
ImportCollectionCsvcan-create-collectionsCSV/TXT/XLSX attachment → collection; max 500 rows sync; async if async or rows > 200
ImportRemoteJsoncan-create-collectionsRemote JSON URL via SafeRemoteUrlValidator; limit default 200, max 500; same async threshold
ExportCollectioncan-show-collectionsExport up to 500 rows as csv or json
ExtractPdfTextcan-create-collectionsPDF attachment text, max 20 000 characters
RollbackLastAiTurncan-delete-collectionsSoft-delete creations from the last AI turn (ai_prompt → following ai_mutation)
GetImportJobStatuscan-create-collectionsPoll job status (mirror of HTTP status)
ManageAiSyncSourcescreate vs edit collection permsList/create/update/enable/disable/delete sync sources

Paths: app/Ai/Tools/{ToolName}.php.

dry_run and upsert_key

Both ImportCollectionCsv and ImportRemoteJson accept:

OptionMeaning
dry_runPreview inferred schema / sample; no writes
upsert_keyField name used to choose update vs create

Also accepted on the collection-import webhook and stored on AiSyncSource for scheduled runs. ImportCollectionJob carries upsertKey and dryRun in its constructor.

Import job status

ItemDetail
JobApp\Jobs\ImportCollectionJob
HTTPGET /ai/import-jobs/{jobId}ImportJobStatusController
Nameai.import-jobs.show
Extra middlewarepermission:can-create-collections (in addition to can-use-ai on the group)
Status sourceImportCollectionJob::status($jobId) — cache key ai:import-job:{uuid}, TTL 24h

Status payload includes job_id, status (queued | running | done | failed), processed, total, message, and result (user id stripped for the response).

Webhook

ItemDetail
RoutePOST /ai/webhooks/collection-import
ControllerApp\Http\Controllers\Ai\CollectionImportWebhookController
Nameai.webhooks.collection-import
MiddlewareOnly throttle:30,1 (no session auth)
Token configconfig('ai.webhook_token')AI_WEBHOOK_TOKEN

Auth: Bearer token or header X-AI-Webhook-Token, compared with hash_equals. Empty configured token → 403.

Body (CollectionImportWebhookRequest):

FieldRules
collection_idRequired
recordsArray, 1–500
upsert_keyOptional

Uses ImportsCollectionRecords; webhook path does not write AI mutation logs (logAiMutation no-op).

Scheduled sync (AiSyncSource)

ItemDetail
ModelApp\Models\AiSyncSource
Fillableuser_id, collection_id, url, upsert_key, interval_minutes, auth_bearer (encrypted), last_run_at, last_status, enabled
Commandai:run-sync-sourcesApp\Console\Commands\RunAiSyncSourcesCommand
ScheduleSchedule::command('ai:run-sync-sources')->everyMinute() in routes/console.php

Eligible sources enqueue ImportCollectionJob with sourceType: 'remote_json' and syncSourceId.

Remote URL safety

ItemDetail
ValidatorApp\Ai\Support\SafeRemoteUrlValidator
Used byImportRemoteJson, ManageAiSyncSources
Ruleshttp/https only; no URL credentials; block localhost / metadata / private IPs; DNS resolve check
Allowlistconfig('ai.remote_import_hosts')AI_REMOTE_IMPORT_HOSTS (comma-separated)

If the allowlist is non-empty, the host must be listed. If empty, any non-blocked host is allowed.

EnvConfig key
AI_REMOTE_IMPORT_HOSTSai.remote_import_hosts
AI_WEBHOOK_TOKENai.webhook_token
AI_DAILY_PROMPT_LIMITai.daily_prompt_limit

(Plus provider keys documented under AI configuration.)

Source map

ConcernLocation
Toolsapp/Ai/Tools/ImportCollectionCsv.php, ImportRemoteJson.php, ExportCollection.php, ExtractPdfText.php, RollbackLastAiTurn.php, …
Jobapp/Jobs/ImportCollectionJob.php
Webhookapp/Http/Controllers/Ai/CollectionImportWebhookController.php
Job statusapp/Http/Controllers/Ai/ImportJobStatusController.php
Sync commandapp/Console/Commands/RunAiSyncSourcesCommand.php
Validatorapp/Ai/Support/SafeRemoteUrlValidator.php
Routes / scheduleroutes/ai.php, routes/console.php
Previous
AI chat