33namespace App \Services \Support \Agents ;
44
55use App \Models \Support \SupportCase ;
6+ use App \Services \Support \SupportProfileRequestParser ;
67use Illuminate \Support \Str ;
78
89class TriageAgentService
910{
11+ public function __construct (
12+ private readonly SupportProfileRequestParser $ profileParser ,
13+ ) {
14+ }
15+
1016 public function triage (SupportCase $ case ): array
1117 {
12- $ text = Str::lower ((string ) ($ case ->normalized_message ?? $ case ->raw_message ?? '' ));
18+ $ rawText = (string ) ($ case ->normalized_message ?? $ case ->raw_message ?? '' );
19+ $ text = Str::lower ($ rawText );
20+ $ profile = $ this ->profileParser ->parse ($ rawText );
1321
1422 // V1 heuristic placeholder (replace with LLM later, keep output schema stable).
1523 $ caseType = 'unknown ' ;
1624 $ runbook = 'unknown ' ;
1725 if (Str::contains ($ text , ['soft-deleted ' , 'deleted ' , 'restore account ' , 'account missing ' ])) {
1826 $ caseType = 'account_restore ' ;
1927 $ runbook = 'restore_deleted_account ' ;
28+ } elseif (Str::contains ($ text , [
29+ 'update profile ' ,
30+ 'profile name ' ,
31+ 'your details ' ,
32+ 'first name ' ,
33+ 'last name ' ,
34+ 'change name ' ,
35+ 'rename profile ' ,
36+ ]) || ($ profile ['firstname ' ] !== null || $ profile ['lastname ' ] !== null )) {
37+ $ caseType = 'profile_update ' ;
38+ $ runbook = 'update_user_profile ' ;
2039 } elseif (Str::contains ($ text , ['duplicate ' , 'two accounts ' , 'split across ' ])) {
2140 $ caseType = 'duplicate_account ' ;
2241 $ runbook = 'duplicate_account_investigation ' ;
@@ -31,22 +50,30 @@ public function triage(SupportCase $case): array
3150 $ runbook = 'role_problem ' ;
3251 }
3352
34- $ targetEmail = $ this ->extractFirstEmail ($ text );
53+ $ targetEmail = $ profile [ ' email ' ] ?? $ this ->extractFirstEmail ($ text );
3554 $ secondary = $ this ->extractAllEmails ($ text );
3655 $ secondary = array_values (array_filter ($ secondary , fn ($ e ) => $ targetEmail ? $ e !== $ targetEmail : true ));
3756
3857 $ risk = Str::contains ($ text , ['password reset ' , 'merge ' , 'ownership ' , 'privileged ' ]) ? 'high ' : 'low ' ;
58+ if ($ caseType === 'profile_update ' ) {
59+ $ risk = 'low ' ;
60+ }
61+
62+ $ needsHuman = $ targetEmail === null
63+ || ($ caseType === 'profile_update ' && $ profile ['firstname ' ] === null && $ profile ['lastname ' ] === null );
3964
4065 return [
4166 'case_type ' => $ caseType ,
4267 'confidence ' => 0.50 ,
4368 'target_email ' => $ targetEmail ,
4469 'secondary_emails ' => $ secondary ,
4570 'target_user_id ' => null ,
46- 'requested_action ' => null ,
71+ 'requested_action ' => $ caseType === 'profile_update ' ? 'user_profile_update ' : null ,
72+ 'profile_firstname ' => $ profile ['firstname ' ],
73+ 'profile_lastname ' => $ profile ['lastname ' ],
4774 'risk_level ' => $ risk ,
4875 'recommended_runbook ' => $ runbook ,
49- 'needs_human_review ' => $ targetEmail === null ,
76+ 'needs_human_review ' => $ needsHuman ,
5077 'reasoning_summary ' => 'V1 heuristic triage (LLM integration pending). ' ,
5178 ];
5279 }
0 commit comments