diff --git a/hesabixCore/src/Controller/wizardController.php b/hesabixCore/src/Controller/wizardController.php
index 7673611d..c0f8b3cc 100644
--- a/hesabixCore/src/Controller/wizardController.php
+++ b/hesabixCore/src/Controller/wizardController.php
@@ -176,7 +176,8 @@ class wizardController extends AbstractController
'response' => $responseContent,
'conversationId' => $conversation->getId(),
'model' => $result['model'] ?? null,
- 'usage' => $result['usage'] ?? null
+ 'usage' => $result['usage'] ?? null,
+ 'debug_info' => $result['debug_info'] ?? null
];
// محاسبه هزینه در صورت وجود اطلاعات usage
@@ -212,14 +213,21 @@ class wizardController extends AbstractController
return $this->json([
'success' => false,
- 'error' => $result['error'] ?? 'خطای نامشخص در سرویس هوش مصنوعی'
+ 'error' => $result['error'] ?? 'خطای نامشخص در سرویس هوش مصنوعی',
+ 'debug_info' => $result['debug_info'] ?? null
]);
}
} catch (\Exception $e) {
return $this->json([
'success' => false,
- 'error' => 'خطا در پردازش درخواست: ' . $e->getMessage()
+ 'error' => 'خطا در پردازش درخواست: ' . $e->getMessage(),
+ 'debug_info' => [
+ 'ai_response' => null,
+ 'tool_commands' => [],
+ 'has_commands' => false,
+ 'error_details' => $e->getMessage()
+ ]
]);
}
}
@@ -557,4 +565,377 @@ class wizardController extends AbstractController
]);
}
}
+
+ #[Route('/api/wizard/execute-command', name: 'wizard_execute_command', methods: ['POST'])]
+ public function wizard_execute_command(
+ Request $request,
+ Access $access,
+ EntityManagerInterface $entityManager,
+ Log $log
+ ): JsonResponse
+ {
+ try {
+ $acc = $access->hasRole('join');
+ if (!$acc) {
+ throw $this->createAccessDeniedException();
+ }
+
+ // بررسی دسترسی هوش مصنوعی
+ if (!$acc['ai']) {
+ return $this->json([
+ 'success' => false,
+ 'error' => 'شما دسترسی استفاده از هوش مصنوعی را ندارید'
+ ]);
+ }
+
+ $params = json_decode($request->getContent(), true) ?? [];
+
+ if (!isset($params['tool']) || !isset($params['params'])) {
+ return $this->json([
+ 'success' => false,
+ 'error' => 'ابزار و پارامترها الزامی هستند'
+ ]);
+ }
+
+ $tool = $params['tool'];
+ $commandParams = $params['params'];
+ $business = $acc['bid'];
+
+ // اجرای دستور
+ $result = null;
+ switch ($tool) {
+ case 'add_person':
+ $result = $this->aiService->getPersonManagementService()->addPerson($commandParams, $business, $acc['user']);
+ break;
+ case 'edit_person':
+ $result = $this->aiService->getPersonManagementService()->editPerson($commandParams, $business, $acc['user']);
+ break;
+ case 'delete_person':
+ $result = $this->aiService->getPersonManagementService()->deletePerson($commandParams, $business, $acc['user']);
+ break;
+ case 'show_person':
+ $result = $this->aiService->getPersonManagementService()->showPerson($commandParams, $business, $acc['user']);
+ break;
+ case 'search_persons':
+ $result = $this->aiService->getPersonManagementService()->searchPersons($commandParams, $business);
+ break;
+ default:
+ return $this->json([
+ 'success' => false,
+ 'error' => "ابزار '{$tool}' شناخته نشد"
+ ]);
+ }
+
+ if ($result && $result['success']) {
+ return $this->json([
+ 'success' => true,
+ 'response' => $result['message'] ?? 'عملیات با موفقیت انجام شد',
+ 'debug_info' => [
+ 'ai_response' => 'دستور اجرا شد',
+ 'tool_commands' => [
+ [
+ 'tool' => $tool,
+ 'params' => $commandParams
+ ]
+ ],
+ 'has_commands' => true,
+ 'execution_result' => $result
+ ]
+ ]);
+ } else {
+ return $this->json([
+ 'success' => false,
+ 'error' => $result['error'] ?? 'خطا در اجرای دستور',
+ 'debug_info' => [
+ 'ai_response' => 'خطا در اجرای دستور',
+ 'tool_commands' => [
+ [
+ 'tool' => $tool,
+ 'params' => $commandParams
+ ]
+ ],
+ 'has_commands' => true,
+ 'execution_result' => $result
+ ]
+ ]);
+ }
+
+ } catch (\Exception $e) {
+ return $this->json([
+ 'success' => false,
+ 'error' => 'خطا در اجرای دستور: ' . $e->getMessage(),
+ 'debug_info' => [
+ 'ai_response' => null,
+ 'tool_commands' => [],
+ 'has_commands' => false,
+ 'error_details' => $e->getMessage()
+ ]
+ ]);
+ }
+ }
+
+ #[Route('/api/wizard/test-debug-info', name: 'wizard_test_debug_info', methods: ['POST'])]
+ public function wizard_test_debug_info(Access $access): JsonResponse
+ {
+ try {
+ $acc = $access->hasRole('join');
+ if (!$acc) {
+ throw $this->createAccessDeniedException();
+ }
+
+ // بررسی دسترسی هوش مصنوعی
+ if (!$acc['ai']) {
+ return $this->json([
+ 'success' => false,
+ 'error' => 'شما دسترسی استفاده از هوش مصنوعی را ندارید',
+ 'debug_info' => [
+ 'ai_response' => 'خطای دسترسی',
+ 'tool_commands' => [],
+ 'has_commands' => false,
+ 'error_details' => 'No AI access'
+ ]
+ ]);
+ }
+
+ return $this->json([
+ 'success' => true,
+ 'response' => 'تست Debug Info با موفقیت انجام شد',
+ 'debug_info' => [
+ 'ai_response' => 'این یک تست برای Debug Info است',
+ 'tool_commands' => [
+ [
+ 'tool' => 'test_tool',
+ 'params' => ['test_param' => 'test_value']
+ ]
+ ],
+ 'has_commands' => true,
+ 'test_data' => 'این داده تست است'
+ ]
+ ]);
+
+ } catch (\Exception $e) {
+ return $this->json([
+ 'success' => false,
+ 'error' => 'خطا در تست Debug Info: ' . $e->getMessage(),
+ 'debug_info' => [
+ 'ai_response' => null,
+ 'tool_commands' => [],
+ 'has_commands' => false,
+ 'error_details' => $e->getMessage()
+ ]
+ ]);
+ }
+ }
+
+ #[Route('/api/wizard/test-interactive', name: 'wizard_test_interactive', methods: ['POST'])]
+ public function wizard_test_interactive(Access $access): JsonResponse
+ {
+ try {
+ $acc = $access->hasRole('join');
+ if (!$acc) {
+ throw $this->createAccessDeniedException();
+ }
+
+ // بررسی دسترسی هوش مصنوعی
+ if (!$acc['ai']) {
+ return $this->json([
+ 'success' => false,
+ 'error' => 'شما دسترسی استفاده از هوش مصنوعی را ندارید',
+ 'debug_info' => [
+ 'ai_response' => 'خطای دسترسی',
+ 'action_type' => 'error',
+ 'has_commands' => false,
+ 'error_details' => 'No AI access'
+ ]
+ ]);
+ }
+
+ // تست سیستم تعاملی
+ $testMessage = "تلفن 09123456789 را برای محسن اضافه کن";
+ $business = $acc['bid'];
+
+ $result = $this->aiService->sendRequest($testMessage, $business, $acc['user']);
+
+ return $this->json([
+ 'success' => true,
+ 'response' => $result['response'] ?? 'تست سیستم تعاملی',
+ 'debug_info' => $result['debug_info'] ?? [
+ 'ai_response' => 'تست سیستم تعاملی',
+ 'action_type' => 'test',
+ 'has_commands' => false
+ ]
+ ]);
+
+ } catch (\Exception $e) {
+ return $this->json([
+ 'success' => false,
+ 'error' => 'خطا در تست سیستم تعاملی: ' . $e->getMessage(),
+ 'debug_info' => [
+ 'ai_response' => null,
+ 'action_type' => 'error',
+ 'has_commands' => false,
+ 'error_details' => $e->getMessage()
+ ]
+ ]);
+ }
+ }
+
+ #[Route('/api/wizard/test-interactive-system', name: 'wizard_test_interactive_system', methods: ['POST'])]
+ public function wizard_test_interactive_system(Access $access): JsonResponse
+ {
+ try {
+ $acc = $access->hasRole('join');
+ if (!$acc) {
+ throw $this->createAccessDeniedException();
+ }
+
+ // بررسی دسترسی هوش مصنوعی
+ if (!$acc['ai']) {
+ return $this->json([
+ 'success' => false,
+ 'error' => 'شما دسترسی استفاده از هوش مصنوعی را ندارید',
+ 'debug_info' => [
+ 'ai_response' => 'خطای دسترسی',
+ 'action_type' => 'error',
+ 'has_commands' => false,
+ 'error_details' => 'No AI access'
+ ]
+ ]);
+ }
+
+ // تست سیستم تعاملی
+ $testMessage = "تلفن 09123456789 را برای محسن اضافه کن";
+ $business = $acc['bid'];
+
+ $result = $this->aiService->sendRequest($testMessage, $business, $acc['user']);
+
+ return $this->json([
+ 'success' => true,
+ 'response' => $result['response'] ?? 'تست سیستم تعاملی',
+ 'debug_info' => $result['debug_info'] ?? [
+ 'ai_response' => 'تست سیستم تعاملی',
+ 'action_type' => 'test',
+ 'has_commands' => false
+ ]
+ ]);
+
+ } catch (\Exception $e) {
+ return $this->json([
+ 'success' => false,
+ 'error' => 'خطا در تست سیستم تعاملی: ' . $e->getMessage(),
+ 'debug_info' => [
+ 'ai_response' => null,
+ 'action_type' => 'error',
+ 'has_commands' => false,
+ 'error_details' => $e->getMessage()
+ ]
+ ]);
+ }
+ }
+
+ #[Route('/api/wizard/test-continuous-operation', name: 'wizard_test_continuous_operation', methods: ['POST'])]
+ public function wizard_test_continuous_operation(Access $access): JsonResponse
+ {
+ try {
+ $acc = $access->hasRole('join');
+ if (!$acc) {
+ throw $this->createAccessDeniedException();
+ }
+
+ // بررسی دسترسی هوش مصنوعی
+ if (!$acc['ai']) {
+ return $this->json([
+ 'success' => false,
+ 'error' => 'شما دسترسی استفاده از هوش مصنوعی را ندارید',
+ 'debug_info' => [
+ 'ai_response' => 'خطای دسترسی',
+ 'action_type' => 'error',
+ 'has_commands' => false,
+ 'error_details' => 'No AI access'
+ ]
+ ]);
+ }
+
+ // تست عملیات پیوسته
+ $testMessage = "برای احمد موبایل 09123456789 تنظیم کن";
+ $business = $acc['bid'];
+
+ $result = $this->aiService->sendRequest($testMessage, $business, $acc['user']);
+
+ return $this->json([
+ 'success' => true,
+ 'response' => $result['response'] ?? 'تست عملیات پیوسته',
+ 'debug_info' => $result['debug_info'] ?? [
+ 'ai_response' => 'تست عملیات پیوسته',
+ 'action_type' => 'test',
+ 'has_commands' => false
+ ]
+ ]);
+
+ } catch (\Exception $e) {
+ return $this->json([
+ 'success' => false,
+ 'error' => 'خطا در تست عملیات پیوسته: ' . $e->getMessage(),
+ 'debug_info' => [
+ 'ai_response' => null,
+ 'action_type' => 'error',
+ 'has_commands' => false,
+ 'error_details' => $e->getMessage()
+ ]
+ ]);
+ }
+ }
+
+ #[Route('/api/wizard/test-smart-operation', name: 'wizard_test_smart_operation', methods: ['POST'])]
+ public function wizard_test_smart_operation(Access $access): JsonResponse
+ {
+ try {
+ $acc = $access->hasRole('join');
+ if (!$acc) {
+ throw $this->createAccessDeniedException();
+ }
+
+ // بررسی دسترسی هوش مصنوعی
+ if (!$acc['ai']) {
+ return $this->json([
+ 'success' => false,
+ 'error' => 'شما دسترسی استفاده از هوش مصنوعی را ندارید',
+ 'debug_info' => [
+ 'ai_response' => 'خطای دسترسی',
+ 'action_type' => 'error',
+ 'has_commands' => false,
+ 'error_details' => 'No AI access'
+ ]
+ ]);
+ }
+
+ // تست عملیات هوشمند
+ $testMessage = "تلفن 09123456789 را برای محسن اضافه کن";
+ $business = $acc['bid'];
+
+ $result = $this->aiService->sendRequest($testMessage, $business, $acc['user']);
+
+ return $this->json([
+ 'success' => true,
+ 'response' => $result['response'] ?? 'تست عملیات هوشمند',
+ 'debug_info' => $result['debug_info'] ?? [
+ 'ai_response' => 'تست عملیات هوشمند',
+ 'action_type' => 'test',
+ 'has_commands' => false
+ ]
+ ]);
+
+ } catch (\Exception $e) {
+ return $this->json([
+ 'success' => false,
+ 'error' => 'خطا در تست عملیات هوشمند: ' . $e->getMessage(),
+ 'debug_info' => [
+ 'ai_response' => null,
+ 'action_type' => 'error',
+ 'has_commands' => false,
+ 'error_details' => $e->getMessage()
+ ]
+ ]);
+ }
+ }
}
diff --git a/hesabixCore/src/Service/AI/AIService.php b/hesabixCore/src/Service/AI/AIService.php
index 2de53f87..95a5f062 100644
--- a/hesabixCore/src/Service/AI/AIService.php
+++ b/hesabixCore/src/Service/AI/AIService.php
@@ -75,6 +75,10 @@ class AIService
// پردازش پاسخ هوش مصنوعی برای تشخیص دستورات ابزار
$processedResponse = $this->processAIResponse($aiResponse, $business, $user);
+ // اضافه کردن debug logging
+ error_log('AIService Debug - AI Response: ' . $aiResponse);
+ error_log('AIService Debug - Processed Response: ' . json_encode($processedResponse));
+
return [
'success' => true,
'response' => $processedResponse['response'],
@@ -82,7 +86,8 @@ class AIService
'service' => $service,
'model' => $this->getAIModel(),
'requires_action' => $processedResponse['requires_action'] ?? false,
- 'action_data' => $processedResponse['action_data'] ?? null
+ 'action_data' => $processedResponse['action_data'] ?? null,
+ 'debug_info' => $processedResponse['debug_info'] ?? null
];
} else {
// اگر کلید data وجود ندارد، احتمالاً پاسخ از ابزار است
@@ -143,62 +148,766 @@ class AIService
*/
private function getSystemPrompt(): string
{
- return "شما یک دستیار هوشمند برای سیستم حسابداری حسابیکس هستید. شما دسترسی به ابزارهای زیر دارید:
-
-🔧 ابزارهای موجود:
-
-1. **مدیریت اشخاص** (person_management):
- - افزودن شخص جدید: add_person{name:نام مستعار}
- - حذف شخص: delete_person{name:نام مستعار}
- - ویرایش شخص: edit_person{name:نام مستعار, phone:موبایل, address:آدرس, email:ایمیل}
- - نمایش مشخصات: show_person{name:نام مستعار}
- - جستجوی اشخاص: search_persons{search:متن جستجو, limit:تعداد نتایج}
-
-📋 قوانین استفاده:
-- اگر کاربر درخواست عملیات مدیریت اشخاص دارد، از دستورات بالا استفاده کنید
-- نام شخص = نام مستعار (nikename) که در دیتابیس فیلد الزامی است
-- نام مستعار معمولاً همان نامی است که کاربران استفاده میکنند
-- برای عملیات پیچیده، اطلاعات را جمعآوری کنید
-- همیشه پاسخ فارسی و واضح ارائه دهید
-- حتماً دستور ابزار را در پاسخ خود قرار دهید
-
-🔄 حفظ context:
-- همیشه تاریخچه گفتگو را در نظر بگیرید
-- اگر کاربر به سوال قبلی اشاره میکند، آن را در نظر بگیرید
-- اگر نام شخص در سوال قبلی ذکر شده، از آن استفاده کنید
-- برای سوالات کوتاه، به context قبلی مراجعه کنید
-
-💡 مثالهای استفاده:
-- 'علی رو حذف کن' → ابتدا بگویید: 'برای حذف شخص علی، از دستور delete_person{name:علی} استفاده میکنم.'
-- 'شخص جدید با نام احمد اضافه کن' → ابتدا بگویید: 'برای افزودن شخص جدید، از دستور add_person{name:احمد} استفاده میکنم.'
-- 'مشخصات محسن رو نشون بده' → ابتدا بگویید: 'برای نمایش مشخصات محسن، از دستور show_person{name:محسن} استفاده میکنم.'
-- 'اطلاعات رضا کمری رو بده' → ابتدا بگویید: 'برای نمایش مشخصات رضا کمری، از دستور show_person{name:رضا کمری} استفاده میکنم.'
-
-💬 مثال حفظ context:
-- کاربر: 'اطلاعات رضا رو بهم بده'
-- دستیار: 'کدام رضا؟ لطفاً نام کامل یا نام مستعار را مشخص کنید.'
-- کاربر: 'کمری'
-- دستیار: 'برای نمایش مشخصات رضا کمری، از دستور show_person{name:رضا کمری} استفاده میکنم.'
-
-⚠️ نکات مهم:
-- نام شخص = نام مستعار (nikename) در دیتابیس
-- حتماً دستور ابزار را در پاسخ خود قرار دهید
-- فقط از ابزارهایی که معرفی شدهاند استفاده کنید
-- اگر ابزار مناسب وجود ندارد، به کاربر بگویید
-- برای عملیات پیچیده، مرحله به مرحله پیش بروید
-- همیشه context گفتگو را حفظ کنید
-
-لطفاً درخواست کاربر را بررسی کرده و در صورت نیاز از ابزارهای مناسب استفاده کنید. حتماً دستور ابزار را در پاسخ خود قرار دهید و context گفتگو را حفظ کنید.";
+ return "شما یک دستیار هوشمند برای سیستم حسابداری حسابیکس هستید.\n\n🔧 ابزارهای موجود:\n\n1. **مدیریت اشخاص**:\n - افزودن شخص جدید: add_person{name:نام مستعار, full_name:نام کامل}\n - حذف شخص: delete_person{name:نام مستعار}\n - ویرایش شخص: edit_person{name:نام مستعار, mobile:موبایل, address:آدرس, email:ایمیل}\n - نمایش مشخصات: show_person{name:نام مستعار}\n - جستجوی اشخاص: search_persons{search:متن جستجو, limit:تعداد نتایج}\n\n📋 قوانین مهم:\n- حتماً از دستورات بالا استفاده کنید\n- نام شخص = نام مستعار (nikename) - فیلد الزامی\n- نام کامل (full_name) = نام و نام خانوادگی - فیلد اختیاری\n\n🔄 سیستم تعاملی چندمرحلهای:\nبرای عملیات پیچیده که نیاز به چند مرحله دارند، از ساختار JSON استفاده کنید:\n\n```json\n{
+ \"action\": \"tool_command\",
+ \"tool\": \"نام_ابزار\",
+ \"params\": {
+ \"param1\": \"value1\",
+ \"param2\": \"value2\"
+ },
+ \"user_message\": \"پیام نمایشی برای کاربر\",
+ \"debug_info\": \"اطلاعات دیباگ\",
+ \"requires_followup\": true,
+ \"next_step\": \"توضیح مرحله بعدی\"
+}
+```\n\n🔄 سیستم عملیات پیوسته تا حصول نتیجه:\nبرای عملیاتهایی که ممکن است نیاز به چندین تلاش داشته باشند، از متغیر `operation_complete` استفاده کنید:\n\n```json\n{
+ \"action\": \"continuous_operation\",
+ \"operation_type\": \"نوع_عملیات\",
+ \"current_step\": \"مرحله_فعلی\",
+ \"steps\": [
+ {
+ \"tool\": \"search_persons\",
+ \"params\": {\"search\": \"محسن\"},
+ \"purpose\": \"جستجوی شخص محسن\"
+ }
+ ],
+ \"user_message\": \"در حال جستجوی شخص محسن...\",
+ \"debug_info\": \"عملیات پیوسته برای یافتن و ویرایش محسن\",
+ \"operation_complete\": false,
+ \"next_action\": \"اگر محسن پیدا نشد، شخص جدید بساز\",
+ \"max_attempts\": 3
+}
+```\n\n🔄 سیستم عملیات هوشمند چندمرحلهای (جدید):\nبرای عملیاتهایی که نیاز به تصمیمگیری هوشمند دارند، از ساختار زیر استفاده کنید:\n\n```json\n{
+ \"action\": \"smart_operation\",
+ \"operation_type\": \"add_phone_to_person\",
+ \"target_person\": \"محسن\",
+ \"target_phone\": \"09123456789\",
+ \"steps\": [
+ {
+ \"tool\": \"search_persons\",
+ \"params\": {\"search\": \"محسن\"},
+ \"purpose\": \"جستجوی شخص محسن\",
+ \"on_success\": \"edit_person\",
+ \"on_failure\": \"add_person\"
+ }
+ ],
+ \"user_message\": \"در حال جستجوی شخص محسن...\",
+ \"debug_info\": \"عملیات هوشمند برای افزودن تلفن\",
+ \"operation_complete\": false,
+ \"next_action\": \"بر اساس نتیجه جستجو، شخص را ویرایش یا اضافه کن\"
+}
+```\n\n📝 انواع پاسخها:\n\n1. **پاسخ مستقیم** (برای عملیات ساده):\n```json\n{
+ \"action\": \"direct_response\",
+ \"user_message\": \"پیام نمایشی برای کاربر\",
+ \"debug_info\": \"اطلاعات دیباگ\"
+}
+```\n\n2. **دستور ابزار** (برای عملیات تک مرحلهای):\n```json\n{
+ \"action\": \"tool_command\",
+ \"tool\": \"edit_person\",
+ \"params\": {
+ \"name\": \"محسن\",
+ \"mobile\": \"09123456789\"
+ },
+ \"user_message\": \"در حال ویرایش موبایل محسن...\",
+ \"debug_info\": \"اجرای دستور edit_person\"
+}
+```\n\n3. **عملیات چندمرحلهای** (برای عملیات پیچیده):\n```json\n{
+ \"action\": \"multi_step\",
+ \"steps\": [
+ {
+ \"tool\": \"search_persons\",
+ \"params\": {\"search\": \"محسن\"},
+ \"purpose\": \"جستجوی شخص محسن\"
+ },
+ {
+ \"tool\": \"edit_person\",
+ \"params\": {\"name\": \"محسن\", \"mobile\": \"09123456789\"},
+ \"purpose\": \"ویرایش موبایل\"
+ }
+ ],
+ \"user_message\": \"در حال جستجو و ویرایش اطلاعات محسن...\",
+ \"debug_info\": \"عملیات چندمرحلهای\",
+ \"requires_followup\": true
+}
+```\n\n4. **عملیات هوشمند چندمرحلهای** (جدید):\n```json\n{
+ \"action\": \"smart_operation\",
+ \"operation_type\": \"add_phone_to_person\",
+ \"target_person\": \"محسن\",
+ \"target_phone\": \"09123456789\",
+ \"steps\": [
+ {
+ \"tool\": \"search_persons\",
+ \"params\": {\"search\": \"محسن\"},
+ \"purpose\": \"جستجوی شخص محسن\",
+ \"on_success\": \"edit_person\",
+ \"on_failure\": \"add_person\"
+ }
+ ],
+ \"user_message\": \"در حال جستجوی شخص محسن...\",
+ \"debug_info\": \"عملیات هوشمند برای افزودن تلفن\",
+ \"operation_complete\": false,
+ \"next_action\": \"بر اساس نتیجه جستجو، شخص را ویرایش یا اضافه کن\"
+}
+```\n\n5. **نتیجه نهایی** (وقتی عملیات کامل شد):\n```json\n{
+ \"action\": \"operation_complete\",
+ \"operation_type\": \"add_phone_to_person\",
+ \"final_result\": \"عملیات با موفقیت انجام شد\",
+ \"user_message\": \"موبایل 09123456789 برای محسن محمودی با موفقیت اضافه شد\",
+ \"debug_info\": \"عملیات پیوسته کامل شد\",
+ \"operation_complete\": true,
+ \"total_steps\": 2,
+ \"final_data\": {
+ \"person_id\": 139,
+ \"person_name\": \"محسن محمودی\",
+ \"new_mobile\": \"09123456789\"
+ }
+}
+```\n\n💡 مثالهای استفاده:\n\n**مثال 1 - عملیات ساده:**\n- 'علی رو حذف کن' → دستور مستقیم delete_person\n\n**مثال 2 - عملیات با جستجو:**\n- 'تلفن 09123456789 را برای محسن اضافه کن' → ابتدا جستجو، سپس ویرایش\n\n**مثال 3 - عملیات هوشمند:**\n- 'شخصی با نام محسن پیدا کن و موبایلش رو 09123456789 کن' → جستجو + اگر پیدا شد ویرایش + اگر پیدا نشد بساز\n\n**مثال 4 - عملیات پیچیده:**\n- 'برای احمد موبایل 09123456789 تنظیم کن' → جستجو + اگر پیدا نشد بساز + ویرایش موبایل\n\n**مثال 5 - نمایش نتایج جستجو:**\n- '5 نفر اخیر را نشان بده' → جستجو + نمایش مستقیم نتایج بدون followup\n\n⚠️ نکات مهم:\n- حتماً از ساختار JSON استفاده کنید\n- برای عملیات پیچیده، ابتدا جستجو کنید\n- اگر شخصی پیدا نشد، شخص جدید بسازید\n- پیامهای کاربر را واضح و مفید بنویسید\n- اطلاعات دیباگ را کامل ارائه دهید\n- برای عملیاتهایی که فقط نیاز به نمایش نتایج دارند، requires_followup را false کنید\n- برای عملیات پیوسته، operation_complete را false نگه دارید تا به نتیجه برسید\n- وقتی عملیات کامل شد، operation_complete را true کنید و نتیجه نهایی را ارائه دهید\n- برای عملیات هوشمند، از on_success و on_failure استفاده کنید تا مرحله بعدی مشخص شود\n- برای جستجو و نمایش نتایج، مستقیماً نتایج را در user_message قرار دهید و requires_followup را false کنید\n\n🔄 منطق عملیات هوشمند:\n1. ابتدا جستجو کنید\n2. اگر پیدا شد، عملیات مورد نظر را انجام دهید\n3. اگر پیدا نشد، شخص جدید بسازید\n4. سپس عملیات مورد نظر را انجام دهید\n5. در نهایت operation_complete را true کنید\n\n🔄 منطق عملیات پیوسته:\n1. ابتدا جستجو کنید\n2. اگر پیدا شد، عملیات مورد نظر را انجام دهید\n3. اگر پیدا نشد، شخص جدید بسازید\n4. سپس عملیات مورد نظر را انجام دهید\n5. در نهایت operation_complete را true کنید\n\n🔄 منطق نمایش نتایج:\n1. جستجو را انجام دهید\n2. نتایج را مستقیماً در user_message قرار دهید\n3. requires_followup را false کنید\n4. اطلاعات کامل را در debug_info قرار دهید\n\n🔄 منطق پاسخدهی عمومی:\n1. سوال را بررسی کنید\n2. اگر سوال عمومی است، پاسخ آموزشی ارائه دهید\n3. از direct_response استفاده کنید\n4. اطلاعات مفید و کامل ارائه دهید\n\nلطفاً درخواست کاربر را بررسی کرده و پاسخ مناسب را با ساختار JSON ارائه دهید.";
}
/**
* پردازش پاسخ هوش مصنوعی و تشخیص دستورات ابزار
*/
private function processAIResponse(string $aiResponse, ?Business $business, $user): array
+ {
+ // ابتدا سعی کن JSON را از پاسخ استخراج کن
+ $jsonResponse = $this->extractJSONFromResponse($aiResponse);
+
+ if ($jsonResponse) {
+ return $this->processJSONResponse($jsonResponse, $aiResponse, $business, $user);
+ }
+
+ // اگر JSON یافت نشد، از روش قدیمی استفاده کن
+ return $this->processLegacyResponse($aiResponse, $business, $user);
+ }
+
+ /**
+ * استخراج JSON از پاسخ AI
+ */
+ private function extractJSONFromResponse(string $aiResponse): ?array
+ {
+ // جستجوی JSON در پاسخ
+ if (preg_match('/```json\s*(\{.*?\})\s*```/s', $aiResponse, $matches)) {
+ $jsonString = $matches[1];
+ } elseif (preg_match('/(\{.*\})/s', $aiResponse, $matches)) {
+ $jsonString = $matches[1];
+ } else {
+ return null;
+ }
+
+ $decoded = json_decode($jsonString, true);
+ return $decoded ?: null;
+ }
+
+ /**
+ * پردازش پاسخ JSON
+ */
+ private function processJSONResponse(array $jsonResponse, string $originalResponse, ?Business $business, $user): array
+ {
+ $action = $jsonResponse['action'] ?? 'direct_response';
+
+ switch ($action) {
+ case 'direct_response':
+ return [
+ 'response' => $jsonResponse['user_message'] ?? $originalResponse,
+ 'requires_action' => false,
+ 'action_data' => null,
+ 'debug_info' => [
+ 'ai_response' => $originalResponse,
+ 'json_response' => $jsonResponse,
+ 'action_type' => 'direct_response',
+ 'has_commands' => false
+ ]
+ ];
+
+ case 'tool_command':
+ return $this->executeSingleToolCommand($jsonResponse, $originalResponse, $business, $user);
+
+ case 'multi_step':
+ return $this->executeMultiStepCommand($jsonResponse, $originalResponse, $business, $user);
+
+ case 'continuous_operation':
+ return $this->executeContinuousOperation($jsonResponse, $originalResponse, $business, $user);
+
+ case 'smart_operation':
+ return $this->executeSmartOperation($jsonResponse, $originalResponse, $business, $user);
+
+ case 'operation_complete':
+ return [
+ 'response' => $jsonResponse['user_message'] ?? 'عملیات با موفقیت کامل شد',
+ 'requires_action' => false,
+ 'action_data' => null,
+ 'debug_info' => [
+ 'ai_response' => $originalResponse,
+ 'json_response' => $jsonResponse,
+ 'action_type' => 'operation_complete',
+ 'has_commands' => false,
+ 'final_result' => $jsonResponse['final_result'] ?? null,
+ 'final_data' => $jsonResponse['final_data'] ?? null
+ ]
+ ];
+
+ default:
+ return [
+ 'response' => $jsonResponse['user_message'] ?? $originalResponse,
+ 'requires_action' => false,
+ 'action_data' => null,
+ 'debug_info' => [
+ 'ai_response' => $originalResponse,
+ 'json_response' => $jsonResponse,
+ 'action_type' => 'unknown',
+ 'has_commands' => false,
+ 'error' => 'نوع عملیات نامعتبر'
+ ]
+ ];
+ }
+ }
+
+ /**
+ * اجرای دستور ابزار تک مرحلهای
+ */
+ private function executeSingleToolCommand(array $jsonResponse, string $originalResponse, ?Business $business, $user): array
+ {
+ $tool = $jsonResponse['tool'] ?? '';
+ $params = $jsonResponse['params'] ?? [];
+
+ if (empty($tool)) {
+ return [
+ 'response' => $jsonResponse['user_message'] ?? 'خطا: ابزار مشخص نشده است',
+ 'requires_action' => false,
+ 'action_data' => null,
+ 'debug_info' => [
+ 'ai_response' => $originalResponse,
+ 'json_response' => $jsonResponse,
+ 'action_type' => 'tool_command',
+ 'has_commands' => false,
+ 'error' => 'ابزار مشخص نشده است'
+ ]
+ ];
+ }
+
+ $result = $this->executeToolCommand(['tool' => $tool, 'params' => $params], $business, $user);
+
+ $finalResponse = $jsonResponse['user_message'] ?? 'عملیات انجام شد';
+
+ // برای جستجو، نتایج را مستقیماً نمایش بده
+ if ($tool === 'search_persons' && $result['success'] && isset($result['persons'])) {
+ $persons = $result['persons'];
+ $count = count($persons);
+
+ if ($count > 0) {
+ $finalResponse .= "\n\n";
+ if (isset($params['search']) && !empty($params['search'])) {
+ $finalResponse .= "نتایج جستجو برای \"{$params['search']}\":\n";
+ } else {
+ $finalResponse .= "لیست {$count} نفر اخیر:\n";
+ }
+
+ foreach ($persons as $index => $person) {
+ $finalResponse .= "\n" . ($index + 1) . ". ";
+ if (!empty($person['nikename'])) {
+ $finalResponse .= $person['nikename'];
+ } elseif (!empty($person['name'])) {
+ $finalResponse .= $person['name'];
+ } else {
+ $finalResponse .= "شخص " . $person['code'];
+ }
+
+ if (!empty($person['mobile'])) {
+ $finalResponse .= " - موبایل: " . $person['mobile'];
+ }
+
+ $finalResponse .= " (کد: " . $person['code'] . ")";
+ }
+ } else {
+ $finalResponse .= "\n\nهیچ شخصی یافت نشد.";
+ }
+
+ // برای جستجو، followup را غیرفعال کن
+ $requiresFollowup = false;
+ } elseif ($tool === 'show_person' && $result['success'] && isset($result['person'])) {
+ // برای نمایش اطلاعات شخص، نتایج را مستقیماً نمایش بده
+ $person = $result['person'];
+
+ $finalResponse .= "\n\n";
+ $finalResponse .= "📋 اطلاعات شخص:\n";
+ $finalResponse .= "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n";
+
+ // نمایش اطلاعات اصلی
+ if (isset($person['نام مستعار']) && !empty($person['نام مستعار'])) {
+ $finalResponse .= "👤 نام مستعار: " . $person['نام مستعار'] . "\n";
+ }
+ if (isset($person['نام کامل']) && !empty($person['نام کامل'])) {
+ $finalResponse .= "📝 نام کامل: " . $person['نام کامل'] . "\n";
+ }
+ if (isset($person['کد']) && !empty($person['کد'])) {
+ $finalResponse .= "🔢 کد: " . $person['کد'] . "\n";
+ }
+
+ // نمایش اطلاعات تماس
+ if (isset($person['موبایل']) && !empty($person['موبایل']) && $person['موبایل'] !== 'تعیین نشده') {
+ $finalResponse .= "📱 موبایل: " . $person['موبایل'] . "\n";
+ }
+ if (isset($person['تلفن']) && !empty($person['تلفن']) && $person['تلفن'] !== 'تعیین نشده') {
+ $finalResponse .= "☎️ تلفن: " . $person['تلفن'] . "\n";
+ }
+ if (isset($person['ایمیل']) && !empty($person['ایمیل']) && $person['ایمیل'] !== 'تعیین نشده') {
+ $finalResponse .= "📧 ایمیل: " . $person['ایمیل'] . "\n";
+ }
+
+ // نمایش اطلاعات آدرس
+ if (isset($person['آدرس']) && !empty($person['آدرس']) && $person['آدرس'] !== 'تعیین نشده') {
+ $finalResponse .= "📍 آدرس: " . $person['آدرس'] . "\n";
+ }
+
+ // نمایش اطلاعات شرکت
+ if (isset($person['شرکت']) && !empty($person['شرکت']) && $person['شرکت'] !== 'تعیین نشده') {
+ $finalResponse .= "🏢 شرکت: " . $person['شرکت'] . "\n";
+ }
+
+ // نمایش اطلاعات مالی
+ if (isset($person['تراز حساب']) && !empty($person['تراز حساب'])) {
+ $finalResponse .= "💰 تراز حساب: " . $person['تراز حساب'] . "\n";
+ }
+ if (isset($person['وضعیت حساب']) && !empty($person['وضعیت حساب'])) {
+ $finalResponse .= "📊 وضعیت حساب: " . $person['وضعیت حساب'] . "\n";
+ }
+
+ // نمایش اطلاعات شناسایی
+ if (isset($person['شناسه ملی']) && !empty($person['شناسه ملی']) && $person['شناسه ملی'] !== 'تعیین نشده') {
+ $finalResponse .= "🆔 شناسه ملی: " . $person['شناسه ملی'] . "\n";
+ }
+ if (isset($person['کد اقتصادی']) && !empty($person['کد اقتصادی']) && $person['کد اقتصادی'] !== 'تعیین نشده') {
+ $finalResponse .= "🏛️ کد اقتصادی: " . $person['کد اقتصادی'] . "\n";
+ }
+
+ // نمایش انواع
+ if (isset($person['انواع']) && !empty($person['انواع']) && $person['انواع'] !== 'تعیین نشده') {
+ $finalResponse .= "🏷️ انواع: " . $person['انواع'] . "\n";
+ }
+
+ $finalResponse .= "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━";
+
+ // برای نمایش اطلاعات شخص، followup را غیرفعال کن
+ $requiresFollowup = false;
+ } else {
+ // برای سایر عملیات، از تنظیمات AI استفاده کن
+ if ($result['success']) {
+ $finalResponse .= "\n\n" . ($result['message'] ?? 'عملیات با موفقیت انجام شد');
+ } else {
+ $finalResponse .= "\n\nخطا: " . ($result['error'] ?? 'خطای نامشخص');
+ }
+
+ $requiresFollowup = $jsonResponse['requires_followup'] ?? false;
+ }
+
+ return [
+ 'response' => $finalResponse,
+ 'requires_action' => $requiresFollowup,
+ 'action_data' => $jsonResponse['next_step'] ?? null,
+ 'debug_info' => [
+ 'ai_response' => $originalResponse,
+ 'json_response' => $jsonResponse,
+ 'action_type' => 'tool_command',
+ 'tool_commands' => [['tool' => $tool, 'params' => $params]],
+ 'has_commands' => true,
+ 'execution_result' => $result
+ ]
+ ];
+ }
+
+ /**
+ * اجرای دستور چندمرحلهای
+ */
+ private function executeMultiStepCommand(array $jsonResponse, string $originalResponse, ?Business $business, $user): array
+ {
+ $steps = $jsonResponse['steps'] ?? [];
+ $results = [];
+ $allCommands = [];
+
+ foreach ($steps as $step) {
+ $tool = $step['tool'] ?? '';
+ $params = $step['params'] ?? [];
+
+ if (!empty($tool)) {
+ $allCommands[] = ['tool' => $tool, 'params' => $params];
+ $result = $this->executeToolCommand(['tool' => $tool, 'params' => $params], $business, $user);
+ $results[] = $result;
+ }
+ }
+
+ $finalResponse = $jsonResponse['user_message'] ?? 'عملیات چندمرحلهای انجام شد';
+
+ // اضافه کردن نتایج به پاسخ
+ foreach ($results as $index => $result) {
+ if ($result['success']) {
+ $finalResponse .= "\n\nمرحله " . ($index + 1) . ": " . ($result['message'] ?? 'موفق');
+ } else {
+ $finalResponse .= "\n\nمرحله " . ($index + 1) . ": خطا - " . ($result['error'] ?? 'خطای نامشخص');
+ }
+ }
+
+ return [
+ 'response' => $finalResponse,
+ 'requires_action' => $jsonResponse['requires_followup'] ?? false,
+ 'action_data' => $jsonResponse['next_step'] ?? null,
+ 'debug_info' => [
+ 'ai_response' => $originalResponse,
+ 'json_response' => $jsonResponse,
+ 'action_type' => 'multi_step',
+ 'tool_commands' => $allCommands,
+ 'has_commands' => true,
+ 'execution_results' => $results
+ ]
+ ];
+ }
+
+ /**
+ * اجرای عملیات پیوسته تا حصول نتیجه
+ */
+ private function executeContinuousOperation(array $jsonResponse, string $originalResponse, ?Business $business, $user): array
+ {
+ $operationType = $jsonResponse['operation_type'] ?? '';
+ $currentStep = $jsonResponse['current_step'] ?? 1;
+ $steps = $jsonResponse['steps'] ?? [];
+ $maxAttempts = $jsonResponse['max_attempts'] ?? 3;
+ $attemptCount = $jsonResponse['attempt_count'] ?? 1;
+ $operationComplete = $jsonResponse['operation_complete'] ?? false;
+
+ // اگر عملیات کامل شده، نتیجه نهایی را برگردان
+ if ($operationComplete) {
+ return [
+ 'response' => $jsonResponse['user_message'] ?? 'عملیات با موفقیت کامل شد',
+ 'requires_action' => false,
+ 'action_data' => null,
+ 'debug_info' => [
+ 'ai_response' => $originalResponse,
+ 'json_response' => $jsonResponse,
+ 'action_type' => 'operation_complete',
+ 'has_commands' => false,
+ 'final_result' => $jsonResponse['final_result'] ?? null,
+ 'final_data' => $jsonResponse['final_data'] ?? null
+ ]
+ ];
+ }
+
+ // اگر تعداد تلاشها از حد مجاز بیشتر شد
+ if ($attemptCount > $maxAttempts) {
+ return [
+ 'response' => 'تعداد تلاشها از حد مجاز بیشتر شد. لطفاً درخواست خود را واضحتر بیان کنید.',
+ 'requires_action' => false,
+ 'action_data' => null,
+ 'debug_info' => [
+ 'ai_response' => $originalResponse,
+ 'json_response' => $jsonResponse,
+ 'action_type' => 'continuous_operation',
+ 'has_commands' => false,
+ 'error' => 'تعداد تلاشها از حد مجاز بیشتر شد',
+ 'attempt_count' => $attemptCount,
+ 'max_attempts' => $maxAttempts
+ ]
+ ];
+ }
+
+ // اجرای مراحل فعلی
+ $results = [];
+ $allCommands = [];
+
+ foreach ($steps as $step) {
+ $tool = $step['tool'] ?? '';
+ $params = $step['params'] ?? [];
+
+ if (!empty($tool)) {
+ $allCommands[] = ['tool' => $tool, 'params' => $params];
+ $result = $this->executeToolCommand(['tool' => $tool, 'params' => $params], $business, $user);
+ $results[] = $result;
+ }
+ }
+
+ // بررسی نتایج و تصمیمگیری برای مرحله بعدی
+ $nextAction = $this->determineNextAction($operationType, $results, $jsonResponse);
+
+ $finalResponse = $jsonResponse['user_message'] ?? 'عملیات پیوسته در حال اجرا...';
+
+ // اضافه کردن نتایج به پاسخ
+ foreach ($results as $index => $result) {
+ if ($result['success']) {
+ $finalResponse .= "\n\nمرحله " . ($index + 1) . ": " . ($result['message'] ?? 'موفق');
+ } else {
+ $finalResponse .= "\n\nمرحله " . ($index + 1) . ": خطا - " . ($result['error'] ?? 'خطای نامشخص');
+ }
+ }
+
+ return [
+ 'response' => $finalResponse,
+ 'requires_action' => true,
+ 'action_data' => [
+ 'operation_type' => $operationType,
+ 'current_step' => $currentStep,
+ 'next_action' => $nextAction,
+ 'attempt_count' => $attemptCount,
+ 'max_attempts' => $maxAttempts,
+ 'results' => $results
+ ],
+ 'debug_info' => [
+ 'ai_response' => $originalResponse,
+ 'json_response' => $jsonResponse,
+ 'action_type' => 'continuous_operation',
+ 'tool_commands' => $allCommands,
+ 'has_commands' => true,
+ 'execution_results' => $results,
+ 'operation_type' => $operationType,
+ 'current_step' => $currentStep,
+ 'attempt_count' => $attemptCount,
+ 'max_attempts' => $maxAttempts,
+ 'next_action' => $nextAction
+ ]
+ ];
+ }
+
+ /**
+ * اجرای عملیات هوشمند چندمرحلهای
+ */
+ private function executeSmartOperation(array $jsonResponse, string $originalResponse, ?Business $business, $user): array
+ {
+ $operationType = $jsonResponse['operation_type'] ?? '';
+ $targetPerson = $jsonResponse['target_person'] ?? '';
+ $targetPhone = $jsonResponse['target_phone'] ?? '';
+ $steps = $jsonResponse['steps'] ?? [];
+
+ // اجرای مرحله اول (معمولاً جستجو)
+ $firstStep = $steps[0] ?? null;
+ if (!$firstStep) {
+ return [
+ 'response' => 'خطا: مرحله اول تعریف نشده است',
+ 'requires_action' => false,
+ 'action_data' => null,
+ 'debug_info' => [
+ 'ai_response' => $originalResponse,
+ 'json_response' => $jsonResponse,
+ 'action_type' => 'smart_operation',
+ 'has_commands' => false,
+ 'error' => 'مرحله اول تعریف نشده'
+ ]
+ ];
+ }
+
+ $tool = $firstStep['tool'] ?? '';
+ $params = $firstStep['params'] ?? [];
+ $onSuccess = $firstStep['on_success'] ?? '';
+ $onFailure = $firstStep['on_failure'] ?? '';
+
+ // اجرای مرحله اول
+ $result = $this->executeToolCommand(['tool' => $tool, 'params' => $params], $business, $user);
+
+ if ($result['success']) {
+ // بررسی نتیجه جستجو
+ if (isset($result['persons'])) {
+ if (!empty($result['persons'])) {
+ // شخص پیدا شد، عملیات on_success را انجام بده
+ return $this->executeNextStep($onSuccess, $targetPerson, $targetPhone, $result, $business, $user, $originalResponse, $jsonResponse);
+ } else {
+ // شخص پیدا نشد، عملیات on_failure را انجام بده
+ return $this->executeNextStep($onFailure, $targetPerson, $targetPhone, $result, $business, $user, $originalResponse, $jsonResponse);
+ }
+ }
+ }
+
+ // اگر نتیجه ناموفق بود
+ return [
+ 'response' => 'خطا در اجرای عملیات: ' . ($result['error'] ?? 'خطای نامشخص'),
+ 'requires_action' => false,
+ 'action_data' => null,
+ 'debug_info' => [
+ 'ai_response' => $originalResponse,
+ 'json_response' => $jsonResponse,
+ 'action_type' => 'smart_operation',
+ 'has_commands' => true,
+ 'execution_result' => $result,
+ 'error' => 'خطا در اجرای مرحله اول'
+ ]
+ ];
+ }
+
+ /**
+ * اجرای مرحله بعدی بر اساس نتیجه
+ */
+ private function executeNextStep(string $action, string $targetPerson, string $targetPhone, array $searchResult, ?Business $business, $user, string $originalResponse, array $jsonResponse): array
+ {
+ switch ($action) {
+ case 'edit_person':
+ // ویرایش شخص موجود
+ $person = $searchResult['persons'][0] ?? null;
+ if ($person) {
+ $editParams = [
+ 'name' => $person['nikename'],
+ 'mobile' => $targetPhone
+ ];
+
+ $editResult = $this->executeToolCommand(['tool' => 'edit_person', 'params' => $editParams], $business, $user);
+
+ if ($editResult['success']) {
+ return [
+ 'response' => "موبایل {$targetPhone} برای {$targetPerson} با موفقیت تنظیم شد",
+ 'requires_action' => false,
+ 'action_data' => null,
+ 'debug_info' => [
+ 'ai_response' => $originalResponse,
+ 'json_response' => $jsonResponse,
+ 'action_type' => 'smart_operation_complete',
+ 'has_commands' => true,
+ 'search_result' => $searchResult,
+ 'edit_result' => $editResult,
+ 'final_result' => 'عملیات ویرایش با موفقیت انجام شد'
+ ]
+ ];
+ } else {
+ return [
+ 'response' => 'خطا در ویرایش موبایل: ' . ($editResult['error'] ?? 'خطای نامشخص'),
+ 'requires_action' => false,
+ 'action_data' => null,
+ 'debug_info' => [
+ 'ai_response' => $originalResponse,
+ 'json_response' => $jsonResponse,
+ 'action_type' => 'smart_operation',
+ 'has_commands' => true,
+ 'search_result' => $searchResult,
+ 'edit_result' => $editResult,
+ 'error' => 'خطا در ویرایش'
+ ]
+ ];
+ }
+ }
+ break;
+
+ case 'add_person':
+ // افزودن شخص جدید
+ $addParams = [
+ 'name' => $targetPerson,
+ 'mobile' => $targetPhone
+ ];
+
+ $addResult = $this->executeToolCommand(['tool' => 'add_person', 'params' => $addParams], $business, $user);
+
+ if ($addResult['success']) {
+ return [
+ 'response' => "شخص جدید {$targetPerson} با موبایل {$targetPhone} با موفقیت ایجاد شد",
+ 'requires_action' => false,
+ 'action_data' => null,
+ 'debug_info' => [
+ 'ai_response' => $originalResponse,
+ 'json_response' => $jsonResponse,
+ 'action_type' => 'smart_operation_complete',
+ 'has_commands' => true,
+ 'search_result' => $searchResult,
+ 'add_result' => $addResult,
+ 'final_result' => 'عملیات افزودن با موفقیت انجام شد'
+ ]
+ ];
+ } else {
+ return [
+ 'response' => 'خطا در افزودن شخص: ' . ($addResult['error'] ?? 'خطای نامشخص'),
+ 'requires_action' => false,
+ 'action_data' => null,
+ 'debug_info' => [
+ 'ai_response' => $originalResponse,
+ 'json_response' => $jsonResponse,
+ 'action_type' => 'smart_operation',
+ 'has_commands' => true,
+ 'search_result' => $searchResult,
+ 'add_result' => $addResult,
+ 'error' => 'خطا در افزودن'
+ ]
+ ];
+ }
+ break;
+ }
+
+ return [
+ 'response' => 'عملیات نامشخص: ' . $action,
+ 'requires_action' => false,
+ 'action_data' => null,
+ 'debug_info' => [
+ 'ai_response' => $originalResponse,
+ 'json_response' => $jsonResponse,
+ 'action_type' => 'smart_operation',
+ 'has_commands' => false,
+ 'error' => 'عملیات نامشخص: ' . $action
+ ]
+ ];
+ }
+
+ /**
+ * تعیین مرحله بعدی بر اساس نتایج
+ */
+ private function determineNextAction(string $operationType, array $results, array $jsonResponse): string
+ {
+ switch ($operationType) {
+ case 'add_phone_to_person':
+ // بررسی نتایج جستجو
+ foreach ($results as $result) {
+ if (isset($result['persons']) && empty($result['persons'])) {
+ // شخص پیدا نشد، باید شخص جدید بسازیم
+ return "شخص پیدا نشد. در حال ساخت شخص جدید...";
+ } elseif (isset($result['persons']) && !empty($result['persons'])) {
+ // شخص پیدا شد، موبایل را ویرایش کن
+ return "شخص پیدا شد. در حال ویرایش موبایل...";
+ }
+ }
+ break;
+
+ case 'edit_person_info':
+ // بررسی نتایج جستجو
+ foreach ($results as $result) {
+ if (isset($result['persons']) && empty($result['persons'])) {
+ return "شخص پیدا نشد. لطفاً نام صحیح را وارد کنید.";
+ } elseif (isset($result['persons']) && !empty($result['persons'])) {
+ return "شخص پیدا شد. در حال ویرایش اطلاعات...";
+ }
+ }
+ break;
+
+ case 'delete_person':
+ // بررسی نتایج جستجو
+ foreach ($results as $result) {
+ if (isset($result['persons']) && empty($result['persons'])) {
+ return "شخص پیدا نشد. لطفاً نام صحیح را وارد کنید.";
+ } elseif (isset($result['persons']) && !empty($result['persons'])) {
+ return "شخص پیدا شد. در حال حذف...";
+ }
+ }
+ break;
+ }
+
+ return $jsonResponse['next_action'] ?? "مرحله بعدی تعیین نشده";
+ }
+
+ /**
+ * پردازش پاسخ قدیمی (برای سازگاری)
+ */
+ private function processLegacyResponse(string $aiResponse, ?Business $business, $user): array
{
// تشخیص دستورات ابزار در پاسخ
$toolCommands = $this->extractToolCommands($aiResponse);
+ // اضافه کردن debug info
+ $debugInfo = [
+ 'ai_response' => $aiResponse,
+ 'tool_commands' => $toolCommands,
+ 'has_commands' => !empty($toolCommands),
+ 'response_type' => 'legacy'
+ ];
+
+ // اگر دستور ابزاری یافت نشد، سعی کن دستورات را از متن استخراج کن
+ if (empty($toolCommands)) {
+ $extractedCommands = $this->extractCommandsFromText($aiResponse);
+ if (!empty($extractedCommands)) {
+ $toolCommands = $extractedCommands;
+ $debugInfo['extracted_commands'] = $extractedCommands;
+ $debugInfo['has_commands'] = true;
+ }
+ }
+
if (!empty($toolCommands)) {
// اجرای دستورات ابزار
$results = [];
@@ -213,7 +922,8 @@ class AIService
return [
'response' => $finalResponse,
'requires_action' => false,
- 'action_data' => null
+ 'action_data' => null,
+ 'debug_info' => $debugInfo
];
}
@@ -221,7 +931,8 @@ class AIService
return [
'response' => $aiResponse,
'requires_action' => false,
- 'action_data' => null
+ 'action_data' => null,
+ 'debug_info' => $debugInfo
];
}
@@ -232,13 +943,13 @@ class AIService
{
$commands = [];
- // الگوهای دستورات ابزار
+ // الگوهای دستورات ابزار - ساده شده
$patterns = [
- 'add_person' => '/add_person\{name:([^}]+)\}/u',
+ 'add_person' => '/add_person\{([^}]+)\}/u',
'delete_person' => '/delete_person\{name:([^}]+)\}/u',
- 'edit_person' => '/edit_person\{name:([^}]+)(?:,([^}]+))*\}/u',
+ 'edit_person' => '/edit_person\{([^}]+)\}/u',
'show_person' => '/show_person\{name:([^}]+)\}/u',
- 'search_persons' => '/search_persons\{search:([^}]+)(?:,limit:([^}]+))*\}/u'
+ 'search_persons' => '/search_persons\{search:([^}]+)\}/u'
];
foreach ($patterns as $tool => $pattern) {
@@ -256,6 +967,62 @@ class AIService
return $commands;
}
+ /**
+ * استخراج دستورات از متن پاسخ AI
+ */
+ private function extractCommandsFromText(string $text): array
+ {
+ $commands = [];
+ $text = mb_strtolower($text, 'UTF-8');
+
+ // الگوهای تشخیص دستورات برای فارسی
+ $patterns = [
+ 'add_person' => [
+ '/(?:افزودن|اضافه|ایجاد|ساخت)\s+(?:شخص|مشتری|کارمند)\s+(?:جدید\s+)?(?:با\s+نام\s+)?([^\s،]+)/u',
+ '/(?:شخص|مشتری|کارمند)\s+(?:جدید\s+)?(?:با\s+نام\s+)?([^\s،]+)\s+(?:اضافه|افزودن|ایجاد|ساخت)/u',
+ '/([^\s،]+)\s+(?:اضافه|افزودن|ایجاد|ساخت)/u',
+ '/(?:برای|به)\s+([^\s،]+)\s+(?:اضافه|افزودن|ایجاد|ساخت)/u'
+ ],
+ 'edit_person' => [
+ '/(?:ویرایش|تغییر|تنظیم)\s+(?:موبایل|شماره|تلفن)\s+(?:برای|به)\s+([^\s،]+)\s+(?:به\s+)?([0-9]+)/u',
+ '/([^\s،]+)\s+(?:موبایل|شماره|تلفن)\s+(?:به\s+)?([0-9]+)/u',
+ '/(?:موبایل|شماره|تلفن)\s+([0-9]+)\s+(?:را\s+)?(?:برای|به)\s+([^\s،]+)/u',
+ '/(?:برای|به)\s+([^\s،]+)\s+(?:موبایل|شماره|تلفن)\s+([0-9]+)/u'
+ ]
+ ];
+
+ foreach ($patterns as $tool => $toolPatterns) {
+ foreach ($toolPatterns as $pattern) {
+ if (preg_match($pattern, $text, $matches)) {
+ if ($tool === 'add_person') {
+ $commands[] = [
+ 'tool' => $tool,
+ 'params' => ['name' => $matches[1]]
+ ];
+ } elseif ($tool === 'edit_person') {
+ // تشخیص اینکه کدام پارامتر نام و کدام موبایل است
+ if (preg_match('/^[0-9]+$/', $matches[1])) {
+ // اگر اولین پارامتر عدد است، پس موبایل است
+ $commands[] = [
+ 'tool' => $tool,
+ 'params' => ['name' => $matches[2], 'mobile' => $matches[1]]
+ ];
+ } else {
+ // اگر اولین پارامتر عدد نیست، پس نام است
+ $commands[] = [
+ 'tool' => $tool,
+ 'params' => ['name' => $matches[1], 'mobile' => $matches[2]]
+ ];
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ return $commands;
+ }
+
/**
* تجزیه پارامترهای دستور ابزار
*/
@@ -263,7 +1030,11 @@ class AIService
{
$params = [];
- // استخراج پارامترها از فرمت {name:value,key:value}
+ // حذف نام ابزار از ابتدای دستور
+ $command = preg_replace('/^\w+\{/', '', $command);
+ $command = rtrim($command, '}');
+
+ // استخراج پارامترها از فرمت name:value,key:value
if (preg_match_all('/([^:,}]+):([^,}]+)/u', $command, $matches, PREG_SET_ORDER)) {
foreach ($matches as $match) {
$key = trim($match[1]);
@@ -272,6 +1043,18 @@ class AIService
// حذف کاراکترهای اضافی
$value = rtrim($value, ',}');
+ // حذف فاصلههای اضافی
+ $key = trim($key);
+ $value = trim($value);
+
+ // اصلاح کلیدهای نامعتبر
+ if (strpos($key, '{') !== false) {
+ $key = str_replace('{', '', $key);
+ }
+ if (strpos($key, 'edit_person') !== false) {
+ $key = 'name';
+ }
+
$params[$key] = $value;
}
}
diff --git a/hesabixCore/src/Service/AI/PersonManagementService.php b/hesabixCore/src/Service/AI/PersonManagementService.php
index b576e7ec..63dba871 100644
--- a/hesabixCore/src/Service/AI/PersonManagementService.php
+++ b/hesabixCore/src/Service/AI/PersonManagementService.php
@@ -31,6 +31,8 @@ class PersonTools
public function addPerson(array $params, Business $business, $user): array
{
$name = $params['name'] ?? '';
+ $fullName = $params['full_name'] ?? $name; // نام کامل (اختیاری)
+
if (empty($name)) {
return [
'success' => false,
@@ -38,7 +40,7 @@ class PersonTools
];
}
- // بررسی وجود شخص با همین نام
+ // بررسی وجود شخص با همین نام مستعار
$existingPerson = $this->entityManager->getRepository(Person::class)->findOneBy([
'nikename' => $name,
'bid' => $business
@@ -47,14 +49,14 @@ class PersonTools
if ($existingPerson) {
return [
'success' => false,
- 'error' => "شخصی با نام '{$name}' قبلاً وجود دارد."
+ 'error' => "شخصی با نام مستعار '{$name}' قبلاً وجود دارد."
];
}
// ایجاد شخص جدید
$person = new Person();
- $person->setName($name);
- $person->setNikename($name);
+ $person->setNikename($name); // نام مستعار (الزامی)
+ $person->setName($fullName); // نام کامل (اختیاری)
$person->setBid($business);
// تولید کد خودکار
@@ -138,6 +140,11 @@ class PersonTools
$changes[] = "موبایل: {$params['phone']}";
}
+ if (isset($params['mobile'])) {
+ $person->setMobile($params['mobile']);
+ $changes[] = "موبایل: {$params['mobile']}";
+ }
+
if (isset($params['address'])) {
$person->setAddress($params['address']);
$changes[] = "آدرس: {$params['address']}";
diff --git a/webUI/src/views/wizard/home.vue b/webUI/src/views/wizard/home.vue
index 065a527c..aba33206 100644
--- a/webUI/src/views/wizard/home.vue
+++ b/webUI/src/views/wizard/home.vue
@@ -76,23 +76,6 @@
مشاهده آرشیو گفتگوها
-
-
-
{{ message.debug_info.operation_type }}
+{{ message.debug_info.current_step }}
+{{ message.debug_info.attempt_count }} از {{ message.debug_info.max_attempts }}
+{{ message.debug_info.next_action }}
+{{ message.debug_info.final_result }}
+{{ JSON.stringify(message.debug_info.final_data, null, 2) }}+
{{ JSON.stringify(message.debug_info.json_response, null, 2) }}+
{{ JSON.stringify(command.params, null, 2) }}+
{{ JSON.stringify(message.debug_info.execution_result, null, 2) }}+
{{ JSON.stringify(result, null, 2) }}+
{{ message.debug_info.ai_response }}+
{{ message.debug_info.error }}
+