v1.2.1
- Generic AI integration (Admin > Integracje > "Integracja AI"), optional and off by default: an OpenAI-compatible /chat/completions client (Groq, OpenAI, or a self-hosted Ollama instance) configured by base URL, optional API key, model, and an SSL-verification toggle. Foundation for the two AI features below and anything else that wants an LLM call in the future. - BookStack automatic content tagging (AI): "Otaguj nową treść"/"Otaguj wszystko ponownie" buttons plus `php artisan bookstack:tag-content` (--dry-run/--force/--limit=N) tag every book/chapter/page with matching helpdesk subcategory names, idempotent by default. - BookStack search refinement: "Przeszukuj" is now three independent checkboxes (Książki/Strony/Rozdziały) instead of a single dropdown, plus a new "Szukaj po" setting (nazwa/tagi/oba) — tag matching uses the bare subcategory name, matching what auto-tagging writes. - AI-driven ticket triage + summary (Admin > Integracje > "Automatyzacja AI dla zgłoszeń", via new scheduled ai:run-ticket-automation): five toggles auto-assign/correct category+subcategory, rewrite an unclear subject, and set priority from content, once per ticket in the background; every change is logged in the ticket's history. Separately, an AI summary + suggested action for every ticket, shown to operators only, with an admin-editable prompt. - Operators can now reassign a ticket to any team, not just one they belong to. - The auto-refresh countdown badges (ticket view, operator queue) are now clickable — fetch immediately and reset the countdown. - All 7 "cyclical" intervals (3 browser refresh countdowns, the notification bell poll, and the 4 background scheduled commands) are now configurable from Admin > Konfiguracja instead of fixed in code. - Fixed: an operator viewing a ticket that's deleted or moved outside their team scope mid-session is now redirected to the operator queue instead of hitting an error. - Docs: README/ARCHITECTURE/CLAUDE/install/wiki updated for all of the above. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -161,6 +161,52 @@ class TicketService
|
||||
TicketQueueChanged::dispatch($ticket->id, 'team_changed', Auth::id());
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies one AI-triage pass's changes (see TicketAiTriageService) in a
|
||||
* single update, rather than composing setPriority()/updateDetails() —
|
||||
* a pass can touch category, subcategory, subject and priority
|
||||
* together, and those would each write their own generic history line
|
||||
* and fire notify()/TriggerEngine::handle() per field instead of once
|
||||
* per pass, fragmenting one semantic AI decision into several
|
||||
* unrelated-looking edits. $historyLines carries one mechanical
|
||||
* "X changed to: Y" line per changed field (built by the caller, since
|
||||
* it already knows the human-readable labels); this always appends one
|
||||
* more attribution line on top, mirroring how RunAutomationRules logs
|
||||
* "Automatyzacja: {label}" after its own field-change lines.
|
||||
*
|
||||
* @param array<string, mixed> $changes column => value, only the fields that actually changed
|
||||
* @param string[] $historyLines
|
||||
*/
|
||||
public function applyAiTriage(Ticket $ticket, array $changes, array $historyLines): void
|
||||
{
|
||||
if (! $changes) {
|
||||
return;
|
||||
}
|
||||
|
||||
$categoryChanged = array_key_exists('category_id', $changes) || array_key_exists('subcategory_id', $changes);
|
||||
$priorityChanged = array_key_exists('priority_key', $changes);
|
||||
|
||||
$ticket->update($changes);
|
||||
|
||||
foreach ($historyLines as $line) {
|
||||
$ticket->addHistory($line);
|
||||
}
|
||||
$ticket->addHistory('Automatyzacja: klasyfikacja AI');
|
||||
|
||||
if ($categoryChanged) {
|
||||
$this->notify($ticket, 'category_changed');
|
||||
app(TriggerEngine::class)->handle($ticket, 'category_changed');
|
||||
}
|
||||
|
||||
if ($priorityChanged) {
|
||||
$this->notify($ticket, 'priority_changed');
|
||||
app(TriggerEngine::class)->handle($ticket, 'priority_changed');
|
||||
}
|
||||
|
||||
app(TriggerEngine::class)->handle($ticket, 'ticket_updated');
|
||||
TicketQueueChanged::dispatch($ticket->id, 'ai_triage', Auth::id());
|
||||
}
|
||||
|
||||
public function setReporter(Ticket $ticket, User $customer): void
|
||||
{
|
||||
$ticket->update(['customer_id' => $customer->id, 'email' => $customer->email, 'name' => $customer->name]);
|
||||
|
||||
Reference in New Issue
Block a user