1
0
Эх сурвалжийг харах

Ticket #4711 - Automations: Assistants.

AntonLV 2 жил өмнө
parent
commit
168486cd60
26 өөрчлөгдсөн 1439 нэмэгдсэн , 116 устгасан
  1. 45 1
      inc/classes/BxDolAI.php
  2. 43 5
      inc/classes/BxDolAIModelGpt40.php
  3. 214 49
      inc/classes/BxDolAIQuery.php
  4. 0 0
      install/sql/system.sql
  5. 33 0
      modules/boonex/english/data/langs/system/en.xml
  6. 34 3
      modules/boonex/russian/data/langs/system/ru.xml
  7. 1 0
      studio/classes/BxDolStudioAgents.php
  8. 28 0
      studio/classes/BxDolStudioAgentsAssistants.php
  9. 61 0
      studio/classes/BxDolStudioAgentsAsstChats.php
  10. 219 0
      studio/classes/BxDolStudioAgentsAsstChatsCmts.php
  11. 0 14
      studio/classes/BxDolStudioAgentsAutomators.php
  12. 0 14
      studio/classes/BxDolStudioAgentsHelpers.php
  13. 19 0
      studio/template/agents_assistant_info.html
  14. 14 0
      studio/template/images/icons/mi-agt-assistants.svg
  15. 9 6
      studio/template/images/icons/mi-agt-automators.svg
  16. 13 5
      studio/template/images/icons/mi-agt-helpers.svg
  17. 0 2
      studio/template/images/icons/mi-agt-providers.svg
  18. 0 1
      studio/template/images/icons/mi-cog.svg
  19. 64 7
      studio/template/scripts/BxBaseStudioAgents.php
  20. 338 0
      studio/template/scripts/BxBaseStudioAgentsAssistants.php
  21. 239 0
      studio/template/scripts/BxBaseStudioAgentsAsstChats.php
  22. 12 6
      studio/template/scripts/BxBaseStudioAgentsAutomators.php
  23. 10 1
      studio/template/scripts/BxBaseStudioAgentsHelpers.php
  24. 5 2
      studio/template/scripts/BxBaseStudioAgentsProviders.php
  25. 19 0
      studio/template/scripts_templ/BxTemplStudioAgentsAssistants.php
  26. 19 0
      studio/template/scripts_templ/BxTemplStudioAgentsAsstChats.php

+ 45 - 1
inc/classes/BxDolAI.php

@@ -21,7 +21,10 @@ class BxDolAI extends BxDolFactory implements iBxDolSingleton
     protected $_iProfileId;
     
     protected $_aExcludeAlertUnits;
-    
+
+    protected $_sCmtsAutomators;
+    protected $_sCmtsAssistantsChats;
+
     protected $_bWriteLog;
 
     protected function __construct()
@@ -39,6 +42,9 @@ class BxDolAI extends BxDolFactory implements iBxDolSingleton
             'system', 'module_template_method_call'
         ];
 
+        $this->_sCmtsAutomators = 'sys_agents_automators';
+        $this->_sCmtsAssistantsChats = 'sys_agents_assistants_chats';
+
         $this->_bWriteLog = true;
     }
 
@@ -115,6 +121,30 @@ class BxDolAI extends BxDolFactory implements iBxDolSingleton
         return BxDolAIProvider::getObjectInstance($iId);
     }   
 
+    public function getAssistantById($iId)
+    {
+        return $this->_oDb->getAssistantsBy(['sample' => 'id', 'id' => $iId]);
+    }
+
+    public function getAssistantByName($sName)
+    {
+        return $this->_oDb->getAssistantsBy(['sample' => 'name', 'name' => $sName]);
+    }
+    
+    public function getAssistantChatCmtsObject()
+    {
+        return $this->_sCmtsAssistantsChats;
+    }
+
+    public function getAssistantChatCmts($iId, $oTemplate = false)
+    {
+        $oCmts = BxDolCmts::getObjectInstance($this->_sCmtsAssistantsChats, (int)$iId, true, $oTemplate);
+        if(!$oCmts || !$oCmts->isEnabled())
+            return false;
+
+        return $oCmts;
+    }
+
     public function getHelperById($iId)
     {
         return $this->_oDb->getHelpersBy(['sample' => 'id', 'id' => $iId]);
@@ -169,6 +199,20 @@ class BxDolAI extends BxDolFactory implements iBxDolSingleton
         return $mixedResult;
     }
 
+    public function getAutomatorCmtsObject()
+    {
+        return $this->_sCmtsAutomators;
+    }
+
+    public function getAutomatorCmts($iId, $oTemplate = false)
+    {
+        $oCmts = BxDolCmts::getObjectInstance($this->_sCmtsAutomators, (int)$iId, true, $oTemplate);
+        if(!$oCmts || !$oCmts->isEnabled())
+            return false;
+
+        return $oCmts;
+    }
+
     public function getAutomatorsEvent($sUnit, $sAction)
     {
         if(in_array($sUnit, $this->_aExcludeAlertUnits))

+ 43 - 5
inc/classes/BxDolAIModelGpt40.php

@@ -15,6 +15,14 @@ class BxDolAIModelGpt40 extends BxDolAIModel
     protected $_sEndpointRuns;
     protected $_sEndpointRunsCheck;
     protected $_sEndpointMessages;
+
+    protected $_sEndpointFiles;
+            
+    protected $_sEndpointVectorStores;
+    protected $_sEndpointVectorStoresFiles;
+
+    protected $_sEndpointAssistants;
+
     protected $_sEndpointChat;
 
     public function __construct($aModel)
@@ -23,12 +31,19 @@ class BxDolAIModelGpt40 extends BxDolAIModel
 
         parent::__construct($aModel);
 
-        $this->_sEndpoint = "https://api.openai.com/v1/threads";
+        $this->_sEndpoint = 'https://api.openai.com/v1/threads';
         $this->_sEndpointRuns = $this->_sEndpoint . '/%s/runs';
         $this->_sEndpointRunsCheck = $this->_sEndpoint . '/%s/runs/%s';
         $this->_sEndpointMessages = $this->_sEndpoint . '/%s/messages';
-        
-        $this->_sEndpointChat = "https://api.openai.com/v1/chat/completions";
+
+        $this->_sEndpointFiles = 'https://api.openai.com/v1/files';
+            
+        $this->_sEndpointVectorStores = 'https://api.openai.com/v1/vector_stores';
+        $this->_sEndpointVectorStoresFiles = $this->_sEndpointVectorStores . '/%s/files';
+
+        $this->_sEndpointAssistants = 'https://api.openai.com/v1/assistants';
+
+        $this->_sEndpointChat = 'https://api.openai.com/v1/chat/completions';
     }
     
     public function getResponseText($sPrompt, $sMessage)
@@ -46,7 +61,7 @@ class BxDolAIModelGpt40 extends BxDolAIModel
     }
 
     public function getResponseInit($sType, $sMessage, $aParams = [])
-    {        
+    {
         $aResponse = $this->call(['messages' => [['role' => 'user', 'content' => $sMessage]]]);
         if(!isset($aResponse['id'], $aResponse['object']) || $aResponse['object'] != 'thread')
             return false;
@@ -112,6 +127,13 @@ class BxDolAIModelGpt40 extends BxDolAIModel
         return $this->getMessages($sThreadId);
     }
 
+    public function getAssistant($sMessage, $aParams = [])
+    {
+        $aResponse = $this->callVectorStores(['name' => $aParams['name']]);
+        if(!isset($aResponse['id'], $aResponse['object']) || $aResponse['object'] != 'vector_store')
+            return false;
+    }
+
     public function call($aParams = [])
     {
         $aData = [];
@@ -161,6 +183,21 @@ class BxDolAIModelGpt40 extends BxDolAIModel
         return $mixedResponse;
     }
     
+    public function callVectorStores($aParams = [])
+    {
+        $aData = [];
+        if(!empty($this->_aParams['call_vs']) && is_array($this->_aParams['call_vs']))
+            $aData = array_merge($aData, $this->_aParams['call_vs']);
+        if(!empty($aParams) && is_array($aParams))
+            $aData = array_merge($aData, $aParams);
+
+        $mixedResponse = $this->_call($this->_sEndpointVectorStores, $aData);
+        if($mixedResponse !== false)
+            $mixedResponse = $mixedResponse['content'][0]['text']['value'];
+
+        return $mixedResponse;
+    }
+    
     public function callChat($aMessages, $aParams = [])
     {
         $aData = [
@@ -210,7 +247,8 @@ class BxDolAIModelGpt40 extends BxDolAIModel
             'Content-Type: application/json', 
             'OpenAI-Beta: assistants=v2'
         ]);
-
+//TODO: Remove at the end
+//var_dump($sResponse); exit;
         $aResponse = json_decode($sResponse, true);
         if(isset($aResponse['error'])) {
             $this->_log($aResponse['error']);

+ 214 - 49
inc/classes/BxDolAIQuery.php

@@ -81,6 +81,22 @@ class BxDolAIQuery extends BxDolDb
                 $aMethod['name'] = 'getPairs';
                 $aMethod['params'][1] = 'id';
                 $aMethod['params'][2] = 'title';
+
+                if(isset($aParams['for_asst'])) {
+                    $aMethod['params'][3] = [
+                        'for_asst' => $aParams['for_asst']
+                    ];
+
+                    $sWhereClause = " AND `for_asst`=:for_asst";
+                }
+
+                if(isset($aParams['active'])) {
+                    $aMethod['params'][3] = [
+                        'active' => $aParams['active']
+                    ];
+
+                    $sWhereClause = " AND `active`=:active";
+                }
                 break;
         }
 
@@ -202,55 +218,6 @@ class BxDolAIQuery extends BxDolDb
 
         return call_user_func_array([$this, $aMethod['name']], $aMethod['params']);
     }
-    
-    public function getHelpersBy($aParams = [])
-    {
-        $aMethod = ['name' => 'getAll', 'params' => [0 => 'query']];
-        $sSelectClause = "`th`.*";
-    	$sJoinClause = $sWhereClause = "";
-
-        switch($aParams['sample']) {
-            case 'id':
-            	$aMethod['name'] = 'getRow';
-            	$aMethod['params'][1] = [
-                    'id' => $aParams['id']
-                ];
-
-                $sWhereClause .= " AND `th`.`id`=:id";
-                break;
-            case 'name':
-            	$aMethod['name'] = 'getRow';
-            	$aMethod['params'][1] = [
-                    'name' => $aParams['name']
-                ];
-
-                $sWhereClause .= " AND `th`.`name`=:name";
-                break;
-            case 'ids':
-                $sWhereClause = " AND `th`.`id` IN (" . $this->implode_escape($aParams['ids']) . ")";
-                break;
-
-            case 'all_pairs':
-                $aMethod['name'] = 'getPairs';
-                $aMethod['params'][1] = 'id';
-                $aMethod['params'][2] = 'name';
-
-                if(isset($aParams['active'])) {
-                    $aMethod['params'][3] = [
-                        'active' => $aParams['active']
-                    ];
-
-                    $sWhereClause = " AND `th`.`active`=:active";
-                }
-                break;
-        }
-
-        $aMethod['params'][0] = "SELECT " . $sSelectClause . "
-            FROM `sys_agents_helpers` AS `th` " . $sJoinClause . "
-            WHERE 1" . $sWhereClause;
-
-        return call_user_func_array([$this, $aMethod['name']], $aMethod['params']);
-    }
 
     public function updateAutomators($aSetClause, $aWhereClause)
     {
@@ -324,6 +291,38 @@ class BxDolAIQuery extends BxDolDb
         return (int)$this->query("DELETE FROM `sys_agents_automators_helpers` WHERE `id` IN (" . $this->implode_escape($mixedId) . ")") > 0;
     }
 
+    public function insertAutomatorAssistant($aParamsSet)
+    {
+        if(empty($aParamsSet))
+            return false;
+
+        return (int)$this->query("INSERT INTO `sys_agents_automators_assistants` SET " . $this->arrayToSQL($aParamsSet)) > 0 ? (int)$this->lastId() : false;
+    }
+
+    public function updateAutomatorAssistant($aParamsSet, $aParamsWhere)
+    {
+        if(empty($aParamsSet) || empty($aParamsWhere))
+            return false;
+
+        return $this->query("UPDATE `sys_agents_automators_assistants` SET " . $this->arrayToSQL($aParamsSet) . " WHERE " . $this->arrayToSQL($aParamsWhere, " AND "));
+    }
+
+    public function deleteAutomatorAssistants($aParamsWhere)
+    {
+        if(empty($aParamsWhere))
+            return false;
+
+        return (int)$this->query("DELETE FROM `sys_agents_automators_assistants` WHERE " . $this->arrayToSQL($aParamsWhere)) > 0;
+    }
+    
+    public function deleteAutomatorAssistantsById($mixedId)
+    {
+        if(!is_array($mixedId))
+            $mixedId = [$mixedId];
+
+        return (int)$this->query("DELETE FROM `sys_agents_automators_assistants` WHERE `id` IN (" . $this->implode_escape($mixedId) . ")") > 0;
+    }
+
     public function getProviderTypesBy($aParams = [])
     {
         $aMethod = ['name' => 'getAll', 'params' => [0 => 'query']];
@@ -488,6 +487,172 @@ class BxDolAIQuery extends BxDolDb
 
         return (int)$this->query("DELETE FROM `sys_agents_providers_values` WHERE " . $this->arrayToSQL($aParamsWhere, ' AND ')) > 0;
     }
+    
+    public function getHelpersBy($aParams = [])
+    {
+        $aMethod = ['name' => 'getAll', 'params' => [0 => 'query']];
+        $sSelectClause = "`th`.*";
+    	$sJoinClause = $sWhereClause = "";
+
+        switch($aParams['sample']) {
+            case 'id':
+            	$aMethod['name'] = 'getRow';
+            	$aMethod['params'][1] = [
+                    'id' => $aParams['id']
+                ];
+
+                $sWhereClause .= " AND `th`.`id`=:id";
+                break;
+            case 'name':
+            	$aMethod['name'] = 'getRow';
+            	$aMethod['params'][1] = [
+                    'name' => $aParams['name']
+                ];
+
+                $sWhereClause .= " AND `th`.`name`=:name";
+                break;
+            case 'ids':
+                $sWhereClause = " AND `th`.`id` IN (" . $this->implode_escape($aParams['ids']) . ")";
+                break;
+
+            case 'all_pairs':
+                $aMethod['name'] = 'getPairs';
+                $aMethod['params'][1] = 'id';
+                $aMethod['params'][2] = 'name';
+
+                if(isset($aParams['active'])) {
+                    $aMethod['params'][3] = [
+                        'active' => $aParams['active']
+                    ];
+
+                    $sWhereClause = " AND `th`.`active`=:active";
+                }
+                break;
+        }
+
+        $aMethod['params'][0] = "SELECT " . $sSelectClause . "
+            FROM `sys_agents_helpers` AS `th` " . $sJoinClause . "
+            WHERE 1" . $sWhereClause;
+
+        return call_user_func_array([$this, $aMethod['name']], $aMethod['params']);
+    }
+
+    public function getAssistantsBy($aParams = [])
+    {
+        $aMethod = ['name' => 'getAll', 'params' => [0 => 'query']];
+        $sSelectClause = "`ta`.*";
+    	$sJoinClause = $sWhereClause = "";
+
+        switch($aParams['sample']) {
+            case 'id':
+            	$aMethod['name'] = 'getRow';
+            	$aMethod['params'][1] = [
+                    'id' => $aParams['id']
+                ];
+
+                $sWhereClause .= " AND `ta`.`id`=:id";
+                break;
+
+            case 'name':
+            	$aMethod['name'] = 'getRow';
+            	$aMethod['params'][1] = [
+                    'name' => $aParams['name']
+                ];
+
+                $sWhereClause .= " AND `ta`.`name`=:name";
+                break;
+
+            case 'ids':
+                $sWhereClause = " AND `ta`.`id` IN (" . $this->implode_escape($aParams['ids']) . ")";
+                break;
+
+            case 'all_pairs':
+                $aMethod['name'] = 'getPairs';
+                $aMethod['params'][1] = 'id';
+                $aMethod['params'][2] = 'name';
+
+                if(isset($aParams['active'])) {
+                    $aMethod['params'][3] = [
+                        'active' => $aParams['active']
+                    ];
+
+                    $sWhereClause = " AND `ta`.`active`=:active";
+                }
+                break;
+        }
+
+        $aMethod['params'][0] = "SELECT " . $sSelectClause . "
+            FROM `sys_agents_assistants` AS `ta` " . $sJoinClause . "
+            WHERE 1" . $sWhereClause;
+
+        return call_user_func_array([$this, $aMethod['name']], $aMethod['params']);
+    }
+    
+    public function updateAssistants($aSetClause, $aWhereClause)
+    {
+        if(empty($aSetClause) || empty($aWhereClause))
+            return false;
+
+        return (int)$this->query("UPDATE `sys_agents_assistants` SET " . $this->arrayToSQL($aSetClause) . " WHERE " . $this->arrayToSQL($aWhereClause)) > 0;
+    }
+
+    public function getChatsBy($aParams = [])
+    {
+        $aMethod = ['name' => 'getAll', 'params' => [0 => 'query']];
+        $sSelectClause = "`tac`.*";
+    	$sJoinClause = $sWhereClause = "";
+
+        switch($aParams['sample']) {
+            case 'id':
+            	$aMethod['name'] = 'getRow';
+            	$aMethod['params'][1] = [
+                    'id' => $aParams['id']
+                ];
+
+                $sWhereClause .= " AND `tac`.`id`=:id";
+                break;
+
+            case 'name':
+            	$aMethod['name'] = 'getRow';
+            	$aMethod['params'][1] = [
+                    'name' => $aParams['name']
+                ];
+
+                $sWhereClause .= " AND `tac`.`name`=:name";
+                break;
+
+            case 'assistant_id':
+                $aMethod['params'][1] = [
+                    'assistant_id' => $aParams['assistant_id']
+                ];
+
+                $sWhereClause .= " AND `tac`.`assistant_id`=:assistant_id";
+                break;
+                
+        }
+
+        $aMethod['params'][0] = "SELECT " . $sSelectClause . "
+            FROM `sys_agents_assistants_chats` AS `tac` " . $sJoinClause . "
+            WHERE 1" . $sWhereClause;
+
+        return call_user_func_array([$this, $aMethod['name']], $aMethod['params']);
+    }
+    
+    public function updateChats($aSetClause, $aWhereClause)
+    {
+        if(empty($aSetClause) || empty($aWhereClause))
+            return false;
+
+        return (int)$this->query("UPDATE `sys_agents_assistants_chats` SET " . $this->arrayToSQL($aSetClause) . " WHERE " . $this->arrayToSQL($aWhereClause)) > 0;
+    }
+    
+    public function deleteChats($aParamsWhere)
+    {
+        if(empty($aParamsWhere))
+            return false;
+
+        return (int)$this->query("DELETE FROM `sys_agents_assistants_chats` WHERE " . $this->arrayToSQL($aParamsWhere, ' AND ')) > 0;
+    }
 }
 
 /** @} */

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
install/sql/system.sql


+ 33 - 0
modules/boonex/english/data/langs/system/en.xml

@@ -1105,6 +1105,7 @@
     <string name="_adm_lang_cnf_uninstall"><![CDATA[<h3>Uninstall "{0}" language?</h3><p>Uninstalling "{0}" language will also delete all of its data. Do you want to continue?</p>]]></string>
     <string name="_adm_lmi_cpt_actions"><![CDATA[Actions]]></string>
     <string name="_adm_lmi_cpt_api_config"><![CDATA[Configuration]]></string>
+    <string name="_adm_lmi_cpt_assistants"><![CDATA[Assistants]]></string>
     <string name="_adm_lmi_cpt_automators"><![CDATA[Automators]]></string>
     <string name="_adm_lmi_cpt_helpers"><![CDATA[Helpers]]></string>
     <string name="_adm_lmi_cpt_badges"><![CDATA[Badges]]></string>
@@ -2225,6 +2226,38 @@
     <string name="_sys_agents_helpers_field_result"><![CDATA[Result]]></string>
     <string name="_sys_agents_helpers_popup_add"><![CDATA[Add helper]]></string>
     <string name="_sys_agents_helpers_popup_edit"><![CDATA[Edit helper]]></string>
+    <string name="_sys_agents_assistants_txt_active"><![CDATA[Active]]></string>
+    <string name="_sys_agents_assistants_txt_name"><![CDATA[Name]]></string>
+    <string name="_sys_agents_assistants_txt_model_id"><![CDATA[Model]]></string>
+    <string name="_sys_agents_assistants_txt_profile_id"><![CDATA[Profile]]></string>
+    <string name="_sys_agents_assistants_txt_prompt"><![CDATA[Prompt]]></string>
+    <string name="_sys_agents_assistants_txt_added"><![CDATA[Added]]></string>
+    <string name="_sys_agents_assistants_txt_assistant"><![CDATA[Assistant]]></string>
+    <string name="_sys_agents_assistants_btn_add"><![CDATA[Add Assistant]]></string>
+    <string name="_sys_agents_assistants_btn_chats"><![CDATA[Chats]]></string>
+    <string name="_sys_agents_assistants_field_name"><![CDATA[Name]]></string>
+    <string name="_sys_agents_assistants_field_model_id"><![CDATA[Model]]></string>
+    <string name="_sys_agents_assistants_field_profile_id"><![CDATA[Profile]]></string>
+    <string name="_sys_agents_assistants_field_profile_id_inf"><![CDATA[Leave empty to use default.]]></string>
+    <string name="_sys_agents_assistants_field_description"><![CDATA[Description]]></string>
+    <string name="_sys_agents_assistants_field_prompt"><![CDATA[Prompt]]></string>
+    <string name="_sys_agents_assistants_field_prompt_err"><![CDATA[Prompt is essential. Please type something here.]]></string>
+    <string name="_sys_agents_assistants_field_result"><![CDATA[Result]]></string>
+    <string name="_sys_agents_assistants_popup_add"><![CDATA[Add assistant]]></string>
+    <string name="_sys_agents_assistants_popup_edit"><![CDATA[Edit assistant]]></string>
+    <string name="_sys_agents_assistants_chats_txt_name"><![CDATA[Name]]></string>
+    <string name="_sys_agents_assistants_chats_txt_description"><![CDATA[Description]]></string>
+    <string name="_sys_agents_assistants_chats_txt_messages"><![CDATA[Messages]]></string>
+    <string name="_sys_agents_assistants_chats_txt_added"><![CDATA[Added]]></string>
+    <string name="_sys_agents_assistants_chats_txt_stored"><![CDATA[Stored]]></string>
+    <string name="_sys_agents_assistants_chats_txt_chat"><![CDATA[Chat]]></string>
+    <string name="_sys_agents_assistants_chats_btn_add"><![CDATA[Add Chat]]></string>
+    <string name="_sys_agents_assistants_chats_btn_chat"><![CDATA[Chat]]></string>
+    <string name="_sys_agents_assistants_chats_btn_store"><![CDATA[Store]]></string>
+    <string name="_sys_agents_assistants_chats_field_name"><![CDATA[Name]]></string>
+    <string name="_sys_agents_assistants_chats_field_description"><![CDATA[Description]]></string>
+    <string name="_sys_agents_assistants_chats_popup_add"><![CDATA[Add chat]]></string>
+    <string name="_sys_agents_assistants_chats_popup_edit"><![CDATA[Edit chat]]></string>
 
   <string name="_sys_audit_content_info_popup_title"><![CDATA[Information]]></string>
   <string name="_sys_audit_action_edit_content"><![CDATA[Content edited]]></string>

+ 34 - 3
modules/boonex/russian/data/langs/system/ru.xml

@@ -1090,6 +1090,8 @@
     <string name="_adm_lmi_cpt_actions"><![CDATA[Действия]]></string>
     <string name="_adm_lmi_cpt_api_config"><![CDATA[Конфигурация]]></string>
     <string name="_adm_lmi_cpt_automators"><![CDATA[Автоматизаторы]]></string>
+    <string name="_adm_lmi_cpt_assistants"><![CDATA[Ассистент]]></string>
+    <string name="_adm_lmi_cpt_helpers"><![CDATA[Помощники]]></string>
     <string name="_adm_lmi_cpt_badges"><![CDATA[Бейджи]]></string>
     <string name="_adm_lmi_cpt_categories"><![CDATA[Категории]]></string>
     <string name="_adm_lmi_cpt_checkout"><![CDATA[Оплата {checkout_counter}]]></string>
@@ -2200,9 +2202,38 @@
         <string name="_sys_agents_helpers_field_result"><![CDATA[Результат]]></string>
         <string name="_sys_agents_helpers_popup_add"><![CDATA[Добавить помощника]]></string>
         <string name="_sys_agents_helpers_popup_edit"><![CDATA[Редактировать помощника]]></string>
-        <string name=""><![CDATA[]]></string>
-        <string name=""><![CDATA[]]></string>
-        <string name=""><![CDATA[]]></string>
+        <string name="_sys_agents_assistants_txt_active"><![CDATA[Активный]]></string>
+        <string name="_sys_agents_assistants_txt_name"><![CDATA[Название]]></string>
+        <string name="_sys_agents_assistants_txt_model_id"><![CDATA[Модель]]></string>
+        <string name="_sys_agents_assistants_txt_profile_id"><![CDATA[Профиль]]></string>
+        <string name="_sys_agents_assistants_txt_prompt"><![CDATA[Инструкции]]></string>
+        <string name="_sys_agents_assistants_txt_added"><![CDATA[Добавлено]]></string>
+        <string name="_sys_agents_assistants_txt_assistant"><![CDATA[Ассистент]]></string>
+        <string name="_sys_agents_assistants_btn_add"><![CDATA[Добавить ассистента]]></string>
+        <string name="_sys_agents_assistants_btn_tune"><![CDATA[Настройка]]></string>
+        <string name="_sys_agents_assistants_field_name"><![CDATA[Название]]></string>
+        <string name="_sys_agents_assistants_field_model_id"><![CDATA[Модель]]></string>
+        <string name="_sys_agents_assistants_field_profile_id"><![CDATA[Профиль]]></string>
+        <string name="_sys_agents_assistants_field_profile_id_inf"><![CDATA[Оставьте пустым, чтобы использовать значение по умолчанию.]]></string>
+        <string name="_sys_agents_assistants_field_description"><![CDATA[Описание]]></string>
+        <string name="_sys_agents_assistants_field_prompt"><![CDATA[Инструкции]]></string>
+        <string name="_sys_agents_assistants_field_prompt_err"><![CDATA[Инструкции имеют важное значение. Пожалуйста, напишите что-нибудь здесь.]]></string>
+        <string name="_sys_agents_assistants_field_result"><![CDATA[Результат]]></string>
+        <string name="_sys_agents_assistants_popup_add"><![CDATA[Добавить ассистента]]></string>
+        <string name="_sys_agents_assistants_popup_edit"><![CDATA[Редактировать ассистента]]></string>
+        <string name="_sys_agents_assistants_chats_txt_name"><![CDATA[Название]]></string>
+        <string name="_sys_agents_assistants_chats_txt_description"><![CDATA[Описание]]></string>
+        <string name="_sys_agents_assistants_chats_txt_messages"><![CDATA[Сообщений]]></string>
+        <string name="_sys_agents_assistants_chats_txt_added"><![CDATA[Добавлено]]></string>
+        <string name="_sys_agents_assistants_chats_txt_stored"><![CDATA[Сохранено]]></string>
+        <string name="_sys_agents_assistants_chats_txt_chat"><![CDATA[Чат]]></string>
+        <string name="_sys_agents_assistants_chats_btn_add"><![CDATA[Добавить чат]]></string>
+        <string name="_sys_agents_assistants_chats_btn_chat"><![CDATA[Беседовать]]></string>
+        <string name="_sys_agents_assistants_chats_btn_store"><![CDATA[Сохранить]]></string>
+        <string name="_sys_agents_assistants_chats_field_name"><![CDATA[Название]]></string>
+        <string name="_sys_agents_assistants_chats_field_description"><![CDATA[Описание]]></string>
+        <string name="_sys_agents_assistants_chats_popup_add"><![CDATA[Добавить чат]]></string>
+        <string name="_sys_agents_assistants_chats_popup_edit"><![CDATA[Редактировать чат]]></string>
 
   <string name="_sys_audit_content_info_popup_title"><![CDATA[Информация]]></string>
   <string name="_sys_audit_action_edit_content"><![CDATA[Контент изменен]]></string>

+ 1 - 0
studio/classes/BxDolStudioAgents.php

@@ -11,6 +11,7 @@ define('BX_DOL_STUDIO_AGENTS_TYPE_SETTINGS', 'settings');
 define('BX_DOL_STUDIO_AGENTS_TYPE_AUTOMATORS', 'automators');
 define('BX_DOL_STUDIO_AGENTS_TYPE_PROVIDERS', 'providers');
 define('BX_DOL_STUDIO_AGENTS_TYPE_HELPERS', 'helpers');
+define('BX_DOL_STUDIO_AGENTS_TYPE_ASSISTANTS', 'assistants');
 
 define('BX_DOL_STUDIO_AGENTS_TYPE_DEFAULT', BX_DOL_STUDIO_AGENTS_TYPE_SETTINGS);
 

+ 28 - 0
studio/classes/BxDolStudioAgentsAssistants.php

@@ -0,0 +1,28 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    UnaStudio UNA Studio
+ * @{
+ */
+
+class BxDolStudioAgentsAssistants extends BxTemplStudioGrid
+{
+    protected $_oDb;
+
+    protected $_iProfileIdAi;
+
+    public function __construct ($aOptions, $oTemplate = false)
+    {
+        parent::__construct ($aOptions, $oTemplate);
+
+        $this->_sDefaultSortingOrder = 'DESC';
+
+        $this->_oDb = new BxDolStudioAgentsQuery();
+
+        $this->_iProfileIdAi = BxDolAI::getInstance()->getProfileId();
+    }
+}
+
+/** @} */

+ 61 - 0
studio/classes/BxDolStudioAgentsAsstChats.php

@@ -0,0 +1,61 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    UnaStudio UNA Studio
+ * @{
+ */
+
+class BxDolStudioAgentsAsstChats extends BxTemplStudioGrid
+{
+    protected $_oDb;
+
+    protected $_sCmts;
+
+    protected $_iProfileIdAi;
+    protected $_iAssistantId;
+
+    public function __construct ($aOptions, $oTemplate = false)
+    {
+        parent::__construct ($aOptions, $oTemplate);
+
+        $this->_sDefaultSortingOrder = 'DESC';
+
+        $this->_oDb = new BxDolStudioAgentsQuery();
+
+        $this->_sCmts = 'sys_agents_assistants_chats';
+
+        $this->_iProfileIdAi = BxDolAI::getInstance()->getProfileId();
+
+        if(($iAssistantId = bx_get('aid')) !== false) 
+            $this->setAssistantId($iAssistantId);
+    }
+
+    public function setAssistantId($iAssistantId)
+    {
+        $this->_iAssistantId = bx_process_input($iAssistantId, BX_DATA_INT);
+        $this->_aQueryAppend['aid'] = $this->_iAssistantId;
+    }
+
+    protected function _delete ($mixedId)
+    {
+        $mixedResult = parent::_delete($mixedId);
+        if($mixedResult !== false && ($oCmts = BxDolCmts::getObjectInstance($this->_sCmts, $mixedId)) !== null) {
+            $oCmts->onObjectDelete($mixedId);
+        }
+
+        return $mixedResult;
+    }
+
+    protected function _getDataSql($sFilter, $sOrderField, $sOrderDir, $iStart, $iPerPage)
+    {
+        if(empty($this->_iAssistantId))
+            return [];
+
+        $this->_aOptions['source'] .= $this->_oDb->prepareAsString(" AND `assistant_id`=? ", $this->_iAssistantId);
+        return parent::_getDataSql($sFilter, $sOrderField, $sOrderDir, $iStart, $iPerPage);
+    }
+}
+
+/** @} */

+ 219 - 0
studio/classes/BxDolStudioAgentsAsstChatsCmts.php

@@ -0,0 +1,219 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    UnaStudio UNA Studio
+ * @{
+ */
+
+class BxDolStudioAgentsAsstChatsCmts extends BxTemplCmts
+{
+    protected $_oQueryAgents;
+    
+    protected $_oAI;
+    protected $_iProfileIdAi;
+    
+    protected $_iAssistantId;
+    protected $_sAssistantUrl;
+
+    protected $_bAuto;   
+
+    public function __construct($sSystem, $iId, $iInit = true, $oTemplate = false)
+    {
+        parent::__construct($sSystem, $iId, $iInit, $oTemplate);
+
+        if ($oTemplate)
+            $this->_oTemplate = $oTemplate;
+        else
+            $this->_oTemplate = BxDolStudioTemplate::getInstance();
+                
+        $this->_sTmplNameItemContent = 'agents_comment_content.html';
+        $this->_bLiveUpdates = false;
+
+        $this->_oQueryAgents = new BxDolStudioAgentsQuery();
+
+        $this->_oAI = BxDolAI::getInstance();
+        $this->_iProfileIdAi = $this->_oAI->getProfileId();
+
+        $this->_iAssistantId = 0;
+        if(($iAssistantId = bx_get('aid')) !== false) {
+            $this->_iAssistantId = bx_process_input($iAssistantId, BX_DATA_INT);
+            $this->_aMarkers['assistant_id'] = $this->_iAssistantId;
+        }
+        $this->_sAssistantUrl = BX_DOL_URL_STUDIO . bx_append_url_params('agents.php', ['page' => 'assistants', 'aid' => $this->_iAssistantId]);
+
+        $this->_bAuto = false;
+    }
+
+    public function actionGetCmt ()
+    {
+        if(!$this->isEnabled())
+            return echoJson([]);
+
+        if($this->isViewAllowed() !== CHECK_ACTION_RESULT_ALLOWED)
+            return echoJson([]);
+
+        $mixedCmtId = bx_process_input(bx_get('Cmt'));
+        $sCmtBrowse = ($sCmtBrowse = bx_get('CmtBrowse')) !== false ? bx_process_input($sCmtBrowse, BX_DATA_TEXT) : '';
+        $sCmtDisplay = ($sCmtDisplay = bx_get('CmtDisplay')) !== false ? bx_process_input($sCmtDisplay, BX_DATA_TEXT) : '';
+
+        $aCmtIds = strpos($mixedCmtId, ',') !== false ? explode(',', $mixedCmtId) : [$mixedCmtId];
+
+        $sContent = '';
+        foreach($aCmtIds as $iCmtId)
+            $sContent .= $this->getComment((int)$iCmtId, ['type' => $sCmtBrowse], ['type' => $sCmtDisplay, 'dynamic_mode' => true]);
+
+        $aCmt = $this->getCommentRow((int)reset($aCmtIds));
+        echoJson([
+            'parent_id' => $aCmt['cmt_parent_id'],
+            'vparent_id' => $aCmt['cmt_parent_id'],
+            'content' => $sContent
+        ]);
+    }
+
+    public function getPageJsObject()
+    {
+        return 'oBxDolStudioPageAgents';
+    }
+
+    public function getCommentsBlock($aBp = [], $aDp = [])
+    {
+        $aComments = parent::getCommentsBlock($aBp, ['in_designbox' => false]);
+        if(empty($aComments['content']))
+            return MsgBox(_t('_error occured'));
+
+        $aChat = $this->_oQueryAgents->getChatsBy(['sample' => 'id', 'id' => (int)$this->getId()]);
+        if(empty($aChat) || !is_array($aChat))
+            return MsgBox(_t('_error occured'));
+        
+        $aAssistant = $this->_oQueryAgents->getAssistantsBy(['sample' => 'id', 'id' => (int)$aChat['assistant_id']]);
+        if(empty($aAssistant) || !is_array($aAssistant))
+            return MsgBox(_t('_error occured'));
+
+        $sAssistant = $this->_oTemplate->parseHtmlByName('agents_assistant_info.html', [
+            'assistant_name' => $aAssistant['name'],
+            'assistant_info' => $aAssistant['description'],
+            'bx_if:show_chat' => [
+                'condition' => true,
+                'content' => [
+                    'chat_name' => $aChat['name'],
+                    'chat_info' => $aChat['description'],
+                ]
+            ],
+            'url_back' => $this->_sAssistantUrl
+        ]);
+
+        return [
+            $sAssistant,
+            $aComments['content']
+        ];
+    }
+
+    public function getFormBoxPost($aBp = [], $aDp = [])
+    {
+        $aComments = $this->_oQuery->getCommentsBy(['type' => 'latest', 'object_id' => (int)$this->getId(), 'start' => 0, 'per_page' => 1]);
+        if(!empty($aComments) && is_array($aComments)) {
+            $aLast = current($aComments);
+            if($aLast['cmt_author_id'] != $this->_iProfileIdAi)
+                return '';
+        }
+
+        return parent::getFormBoxPost($aBp, $aDp);
+    }
+
+    public function isAttachImageEnabled()
+    {
+        return false;
+    }
+
+    public function addAuto($aValues)
+    {
+        $this->_bAuto = true;
+        $mixedResult = $this->add($aValues);
+
+        $this->_bAuto = false;
+        return $mixedResult;
+    }
+
+    public function onPostAfter($iCmtId, $aDp = [])
+    {
+        $mixedResult = parent::onPostAfter($iCmtId, $aDp);
+        if($this->_bAuto || $mixedResult === false) 
+            return $mixedResult;
+
+        $iObjId = (int)$this->getId();
+        $aAutomator = $this->_oAI->getAutomator($iObjId, true);
+
+        $aComments = $this->_oQuery->getCommentsBy(['type' => 'object_id', 'object_id' => $iObjId]);
+        if($aAutomator['type'] == BX_DOL_AI_AUTOMATOR_EVENT && !empty($aAutomator['params']['trigger']))
+            $aComments[0]['cmt_text'] .= $aAutomator['params']['trigger'];
+
+        $aMessages = [];
+        foreach($aComments as $aComment)
+            $aMessages[] = [
+                'ai' => (int)$aComment['cmt_author_id'] == $this->_iProfileIdAi,
+                'content' => $aComment['cmt_text']
+            ];
+
+        $oAIModel = $this->_oAI->getModelObject($aAutomator['model_id']);
+        if(($sResponse = $oAIModel->getResponse($aAutomator['type'], $aMessages, $aAutomator['params'])) !== false) {
+            $mixedResultAuto = $this->addAuto([
+                'cmt_author_id' => $this->_iProfileIdAi,
+                'cmt_parent_id' => 0,
+                'cmt_text' => $sResponse
+            ]);
+
+            if($mixedResultAuto !== false)
+                $mixedResult['id'] .= ',' . $mixedResultAuto['id'];
+        }
+
+        return $mixedResult;
+    }
+
+    protected function _getActionsBox(&$aCmt, $aBp = [], $aDp = [])
+    {
+        if((int)$aCmt['cmt_author_id'] != $this->_iProfileIdAi)
+            return parent::_getActionsBox($aCmt, $aBp, array_merge($aDp, ['view_only' => true]));
+
+        return $this->_oTemplate->parseLink('javascript:void(0)', _t('_sys_agents_automators_btn_approve'), [
+            'class' => 'bx-btn bx-btn-small bx-btn-primary',
+            'onclick' => $this->getPageJsObject() . '.approveCode(this, ' . $aCmt['cmt_id'] . ')',
+        ]);
+    }
+
+    protected function _getCountersBox(&$aCmt, $aBp = [], $aDp = [])
+    {
+        return '';
+    }
+
+    protected function _getFormBox($sType, $aBp, $aDp)
+    {
+        return parent::_getFormBox($sType, $aBp, array_merge($aDp, ['min_post_form' => false]));
+    }
+
+    protected function _getTmplVarsText($aCmt)
+    {
+        $aResult = parent::_getTmplVarsText($aCmt);
+
+        if((int)$aCmt['cmt_author_id'] == $this->_iProfileIdAi)
+            $aResult['text'] = '<pre>' . $aResult['text'] . '</pre>';
+
+        return $aResult;
+    }
+    
+    protected function _getForm($sAction, $iId)
+    {
+        $aResult = parent::_getForm($sAction, $iId);
+
+        $aResult->aInputs['cmt_text']['db']['pass'] = 'xss';
+        return $aResult;
+    }
+    
+    protected function _prepareTextForOutput($s, $iCmtId = 0)
+    {
+        return nl2br(parent::_prepareTextForOutput($s, $iCmtId));
+    }
+}
+
+/** @} */

+ 0 - 14
studio/classes/BxDolStudioAgentsAutomators.php

@@ -11,8 +11,6 @@ class BxDolStudioAgentsAutomators extends BxTemplStudioGrid
 {
     protected $_oDb;
 
-    protected $_sCmts;
-
     protected $_iProfileIdAi;
 
     public function __construct ($aOptions, $oTemplate = false)
@@ -23,20 +21,8 @@ class BxDolStudioAgentsAutomators extends BxTemplStudioGrid
 
         $this->_oDb = new BxDolStudioAgentsQuery();
 
-        $this->_sCmts = 'sys_agents_automators';
-
         $this->_iProfileIdAi = BxDolAI::getInstance()->getProfileId();
     }
-
-    protected function _delete ($mixedId)
-    {
-        $mixedResult = parent::_delete($mixedId);
-        if($mixedResult !== false && ($oCmts = BxDolCmts::getObjectInstance($this->_sCmts, $mixedId)) !== null) {
-            $oCmts->onObjectDelete($mixedId);
-        }
-
-        return $mixedResult;
-    }
 }
 
 /** @} */

+ 0 - 14
studio/classes/BxDolStudioAgentsHelpers.php

@@ -11,8 +11,6 @@ class BxDolStudioAgentsHelpers extends BxTemplStudioGrid
 {
     protected $_oDb;
 
-    protected $_sCmts;
-
     protected $_iProfileIdAi;
 
     public function __construct ($aOptions, $oTemplate = false)
@@ -23,20 +21,8 @@ class BxDolStudioAgentsHelpers extends BxTemplStudioGrid
 
         $this->_oDb = new BxDolStudioAgentsQuery();
 
-        $this->_sCmts = 'sys_agents_helpers';
-
         $this->_iProfileIdAi = BxDolAI::getInstance()->getProfileId();
     }
-
-    protected function _delete ($mixedId)
-    {
-        $mixedResult = parent::_delete($mixedId);
-        if($mixedResult !== false && ($oCmts = BxDolCmts::getObjectInstance($this->_sCmts, $mixedId)) !== null) {
-            $oCmts->onObjectDelete($mixedId);
-        }
-
-        return $mixedResult;
-    }
 }
 
 /** @} */

+ 19 - 0
studio/template/agents_assistant_info.html

@@ -0,0 +1,19 @@
+<div class="flex flex-row">
+    <div class="flex-1">
+        <div class="flex gap-2">
+            <div class="w-20 font-semibold"><bx_text:_sys_agents_assistants_txt_assistant /></div>
+            <div>__assistant_name__</div>
+        </div>
+        <div class="flex bx-def-font-meta bx-def-font-grayed">__assistant_info__</div>
+        <bx_if:show_chat>
+            <div class="flex mt-4 gap-2">
+                <div class="w-20 font-semibold"><bx_text:_sys_agents_assistants_chats_txt_chat /></div>
+                <div>__chat_name__</div>
+            </div>
+            <div class="flex bx-def-font-meta bx-def-font-grayed">__chat_info__</div>
+        </bx_if:show_chat>
+    </div>
+    <div class="flex-0">
+        <a class="bx-btn" href="__url_back__"><i class="sys-icon arrow-left"></i></a>
+    </div>
+</div>

+ 14 - 0
studio/template/images/icons/mi-agt-assistants.svg

@@ -0,0 +1,14 @@
+<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M14.0352 8.7193C14.0352 8.13795 14.5064 7.66667 15.0878 7.66667H20.0001C20.5814 7.66667 21.0527 8.13795 21.0527 8.7193V12.579H27.3685C28.2991 12.579 29.1916 12.9486 29.8496 13.6067C30.5076 14.2647 30.8773 15.1571 30.8773 16.0877V19.9474H32.2808C32.8621 19.9474 33.3334 20.4187 33.3334 21C33.3334 21.5814 32.8621 22.0527 32.2808 22.0527H30.8773V25.9123C30.8773 26.8429 30.5076 27.7354 29.8496 28.3934C29.1916 29.0514 28.2991 29.4211 27.3685 29.4211H15.5238L10.9198 34.0251C10.6188 34.3261 10.166 34.4162 9.7727 34.2532C9.37935 34.0903 9.12289 33.7065 9.12289 33.2807V22.0527H7.71938C7.13803 22.0527 6.66675 21.5814 6.66675 21C6.66675 20.4187 7.13803 19.9474 7.71938 19.9474H9.12289V16.0877C9.12289 15.1571 9.49256 14.2647 10.1506 13.6067C10.8086 12.9486 11.7011 12.579 12.6317 12.579H18.9474V9.77194H15.0878C14.5064 9.77194 14.0352 9.30066 14.0352 8.7193ZM12.6317 14.6842C12.2594 14.6842 11.9024 14.8321 11.6392 15.0953C11.376 15.3585 11.2282 15.7155 11.2282 16.0877V30.7395L14.3435 27.6241C14.5409 27.4267 14.8086 27.3158 15.0878 27.3158H27.3685C27.7407 27.3158 28.0977 27.1679 28.3609 26.9047C28.6241 26.6415 28.772 26.2845 28.772 25.9123V16.0877C28.772 15.7155 28.6241 15.3585 28.3609 15.0953C28.0977 14.8321 27.7407 14.6842 27.3685 14.6842H12.6317ZM16.3159 18.7193C16.8972 18.7193 17.3685 19.1906 17.3685 19.7719V22.2281C17.3685 22.8094 16.8972 23.2807 16.3159 23.2807C15.7345 23.2807 15.2632 22.8094 15.2632 22.2281V19.7719C15.2632 19.1906 15.7345 18.7193 16.3159 18.7193ZM23.6843 18.7193C24.2656 18.7193 24.7369 19.1906 24.7369 19.7719V22.2281C24.7369 22.8094 24.2656 23.2807 23.6843 23.2807C23.1029 23.2807 22.6317 22.8094 22.6317 22.2281V19.7719C22.6317 19.1906 23.1029 18.7193 23.6843 18.7193Z" fill="black" fill-opacity="0.2"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M14.0352 7.7193C14.0352 7.13795 14.5064 6.66667 15.0878 6.66667H20.0001C20.5814 6.66667 21.0527 7.13795 21.0527 7.7193V11.579H27.3685C28.2991 11.579 29.1916 11.9486 29.8496 12.6067C30.5076 13.2647 30.8773 14.1571 30.8773 15.0877V18.9474H32.2808C32.8621 18.9474 33.3334 19.4187 33.3334 20C33.3334 20.5814 32.8621 21.0527 32.2808 21.0527H30.8773V24.9123C30.8773 25.8429 30.5076 26.7354 29.8496 27.3934C29.1916 28.0514 28.2991 28.4211 27.3685 28.4211H15.5238L10.9198 33.0251C10.6188 33.3261 10.166 33.4162 9.7727 33.2532C9.37935 33.0903 9.12289 32.7065 9.12289 32.2807V21.0527H7.71938C7.13803 21.0527 6.66675 20.5814 6.66675 20C6.66675 19.4187 7.13803 18.9474 7.71938 18.9474H9.12289V15.0877C9.12289 14.1571 9.49256 13.2647 10.1506 12.6067C10.8086 11.9486 11.7011 11.579 12.6317 11.579H18.9474V8.77194H15.0878C14.5064 8.77194 14.0352 8.30066 14.0352 7.7193ZM12.6317 13.6842C12.2594 13.6842 11.9024 13.8321 11.6392 14.0953C11.376 14.3585 11.2282 14.7155 11.2282 15.0877V29.7395L14.3435 26.6241C14.5409 26.4267 14.8086 26.3158 15.0878 26.3158H27.3685C27.7407 26.3158 28.0977 26.1679 28.3609 25.9047C28.6241 25.6415 28.772 25.2845 28.772 24.9123V15.0877C28.772 14.7155 28.6241 14.3585 28.3609 14.0953C28.0977 13.8321 27.7407 13.6842 27.3685 13.6842H12.6317ZM16.3159 17.7193C16.8972 17.7193 17.3685 18.1906 17.3685 18.7719V21.2281C17.3685 21.8094 16.8972 22.2807 16.3159 22.2807C15.7345 22.2807 15.2632 21.8094 15.2632 21.2281V18.7719C15.2632 18.1906 15.7345 17.7193 16.3159 17.7193ZM23.6843 17.7193C24.2656 17.7193 24.7369 18.1906 24.7369 18.7719V21.2281C24.7369 21.8094 24.2656 22.2807 23.6843 22.2807C23.1029 22.2807 22.6317 21.8094 22.6317 21.2281V18.7719C22.6317 18.1906 23.1029 17.7193 23.6843 17.7193Z" fill="url(#paint1_linear_1640_8256)"/>
+<defs>
+<linearGradient id="paint0_linear_1640_8256" x1="20" y1="0" x2="20" y2="40" gradientUnits="userSpaceOnUse">
+<stop stop-color="#6B7280"/>
+<stop offset="1" stop-color="#1F2937"/>
+</linearGradient>
+<linearGradient id="paint1_linear_1640_8256" x1="20.0001" y1="6.66667" x2="20.0001" y2="33.3334" gradientUnits="userSpaceOnUse">
+<stop stop-color="#F9FAFB"/>
+<stop offset="1" stop-color="#9CA3AF"/>
+</linearGradient>
+</defs>
+</svg>

+ 9 - 6
studio/template/images/icons/mi-agt-automators.svg

@@ -1,10 +1,13 @@
-<svg width="28" height="24" viewBox="0 0 28 24" fill="none" xmlns="http://www.w3.org/2000/svg">
-<g id="Group 25">
-<path id="Vector" d="M19.2856 10H25.2856C25.8161 10 26.3248 9.78929 26.6999 9.41421C27.0749 9.03914 27.2856 8.53043 27.2856 8V2C27.2856 1.46957 27.0749 0.960859 26.6999 0.585786C26.3248 0.210714 25.8161 0 25.2856 0H19.2856C18.7552 0 18.2465 0.210714 17.8714 0.585786C17.4964 0.960859 17.2856 1.46957 17.2856 2V4H15.2856C14.49 4 13.7269 4.31607 13.1643 4.87868C12.6017 5.44129 12.2856 6.20435 12.2856 7V11H8.28564V10C8.28564 9.46957 8.07493 8.96086 7.69986 8.58579C7.32478 8.21071 6.81608 8 6.28564 8H2.28564C1.75521 8 1.2465 8.21071 0.871431 8.58579C0.496358 8.96086 0.285645 9.46957 0.285645 10V14C0.285645 14.5304 0.496358 15.0391 0.871431 15.4142C1.2465 15.7893 1.75521 16 2.28564 16H6.28564C6.81608 16 7.32478 15.7893 7.69986 15.4142C8.07493 15.0391 8.28564 14.5304 8.28564 14V13H12.2856V17C12.2856 17.7956 12.6017 18.5587 13.1643 19.1213C13.7269 19.6839 14.49 20 15.2856 20H17.2856V22C17.2856 22.5304 17.4964 23.0391 17.8714 23.4142C18.2465 23.7893 18.7552 24 19.2856 24H25.2856C25.8161 24 26.3248 23.7893 26.6999 23.4142C27.0749 23.0391 27.2856 22.5304 27.2856 22V16C27.2856 15.4696 27.0749 14.9609 26.6999 14.5858C26.3248 14.2107 25.8161 14 25.2856 14H19.2856C18.7552 14 18.2465 14.2107 17.8714 14.5858C17.4964 14.9609 17.2856 15.4696 17.2856 16V18H15.2856C15.0204 18 14.7661 17.8946 14.5785 17.7071C14.391 17.5196 14.2856 17.2652 14.2856 17V7C14.2856 6.73478 14.391 6.48043 14.5785 6.29289C14.7661 6.10536 15.0204 6 15.2856 6H17.2856V8C17.2856 8.53043 17.4964 9.03914 17.8714 9.41421C18.2465 9.78929 18.7552 10 19.2856 10ZM6.28564 14H2.28564V10H6.28564V14ZM19.2856 16H25.2856V22H19.2856V16ZM19.2856 2H25.2856V8H19.2856V2Z" fill="url(#paint0_linear_905_2572)"/>
-</g>
+<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M25.2856 18.5714H31.2856C31.8161 18.5714 32.3248 18.3607 32.6999 17.9856C33.0749 17.6106 33.2856 17.1019 33.2856 16.5714V10.5714C33.2856 10.041 33.0749 9.53229 32.6999 9.15721C32.3248 8.78214 31.8161 8.57143 31.2856 8.57143H25.2856C24.7552 8.57143 24.2465 8.78214 23.8714 9.15721C23.4964 9.53229 23.2856 10.041 23.2856 10.5714V12.5714H21.2856C20.49 12.5714 19.7269 12.8875 19.1643 13.4501C18.6017 14.0127 18.2856 14.7758 18.2856 15.5714V19.5714H14.2856V18.5714C14.2856 18.041 14.0749 17.5323 13.6999 17.1572C13.3248 16.7821 12.8161 16.5714 12.2856 16.5714H8.28564C7.75521 16.5714 7.2465 16.7821 6.87143 17.1572C6.49636 17.5323 6.28564 18.041 6.28564 18.5714V22.5714C6.28564 23.1019 6.49636 23.6106 6.87143 23.9856C7.2465 24.3607 7.75521 24.5714 8.28564 24.5714H12.2856C12.8161 24.5714 13.3248 24.3607 13.6999 23.9856C14.0749 23.6106 14.2856 23.1019 14.2856 22.5714V21.5714H18.2856V25.5714C18.2856 26.3671 18.6017 27.1301 19.1643 27.6927C19.7269 28.2554 20.49 28.5714 21.2856 28.5714H23.2856V30.5714C23.2856 31.1019 23.4964 31.6106 23.8714 31.9856C24.2465 32.3607 24.7552 32.5714 25.2856 32.5714H31.2856C31.8161 32.5714 32.3248 32.3607 32.6999 31.9856C33.0749 31.6106 33.2856 31.1019 33.2856 30.5714V24.5714C33.2856 24.041 33.0749 23.5323 32.6999 23.1572C32.3248 22.7821 31.8161 22.5714 31.2856 22.5714H25.2856C24.7552 22.5714 24.2465 22.7821 23.8714 23.1572C23.4964 23.5323 23.2856 24.041 23.2856 24.5714V26.5714H21.2856C21.0204 26.5714 20.7661 26.4661 20.5785 26.2785C20.391 26.091 20.2856 25.8366 20.2856 25.5714V15.5714C20.2856 15.3062 20.391 15.0519 20.5785 14.8643C20.7661 14.6768 21.0204 14.5714 21.2856 14.5714H23.2856V16.5714C23.2856 17.1019 23.4964 17.6106 23.8714 17.9856C24.2465 18.3607 24.7552 18.5714 25.2856 18.5714ZM12.2856 22.5714H8.28564V18.5714H12.2856V22.5714ZM25.2856 24.5714H31.2856V30.5714H25.2856V24.5714ZM25.2856 10.5714H31.2856V16.5714H25.2856V10.5714Z" fill="black" fill-opacity="0.2"/>
+<path d="M25.2856 18H31.2856C31.8161 18 32.3248 17.7893 32.6999 17.4142C33.0749 17.0391 33.2856 16.5304 33.2856 16V10C33.2856 9.46957 33.0749 8.96086 32.6999 8.58579C32.3248 8.21071 31.8161 8 31.2856 8H25.2856C24.7552 8 24.2465 8.21071 23.8714 8.58579C23.4964 8.96086 23.2856 9.46957 23.2856 10V12H21.2856C20.49 12 19.7269 12.3161 19.1643 12.8787C18.6017 13.4413 18.2856 14.2044 18.2856 15V19H14.2856V18C14.2856 17.4696 14.0749 16.9609 13.6999 16.5858C13.3248 16.2107 12.8161 16 12.2856 16H8.28564C7.75521 16 7.2465 16.2107 6.87143 16.5858C6.49636 16.9609 6.28564 17.4696 6.28564 18V22C6.28564 22.5304 6.49636 23.0391 6.87143 23.4142C7.2465 23.7893 7.75521 24 8.28564 24H12.2856C12.8161 24 13.3248 23.7893 13.6999 23.4142C14.0749 23.0391 14.2856 22.5304 14.2856 22V21H18.2856V25C18.2856 25.7956 18.6017 26.5587 19.1643 27.1213C19.7269 27.6839 20.49 28 21.2856 28H23.2856V30C23.2856 30.5304 23.4964 31.0391 23.8714 31.4142C24.2465 31.7893 24.7552 32 25.2856 32H31.2856C31.8161 32 32.3248 31.7893 32.6999 31.4142C33.0749 31.0391 33.2856 30.5304 33.2856 30V24C33.2856 23.4696 33.0749 22.9609 32.6999 22.5858C32.3248 22.2107 31.8161 22 31.2856 22H25.2856C24.7552 22 24.2465 22.2107 23.8714 22.5858C23.4964 22.9609 23.2856 23.4696 23.2856 24V26H21.2856C21.0204 26 20.7661 25.8946 20.5785 25.7071C20.391 25.5196 20.2856 25.2652 20.2856 25V15C20.2856 14.7348 20.391 14.4804 20.5785 14.2929C20.7661 14.1054 21.0204 14 21.2856 14H23.2856V16C23.2856 16.5304 23.4964 17.0391 23.8714 17.4142C24.2465 17.7893 24.7552 18 25.2856 18ZM12.2856 22H8.28564V18H12.2856V22ZM25.2856 24H31.2856V30H25.2856V24ZM25.2856 10H31.2856V16H25.2856V10Z" fill="url(#paint1_linear_834_8427)"/>
 <defs>
-<linearGradient id="paint0_linear_905_2572" x1="13.7856" y1="0" x2="13.7856" y2="24" gradientUnits="userSpaceOnUse">
-<stop stop-color="#F3F4F6"/>
+<linearGradient id="paint0_linear_834_8427" x1="20" y1="0" x2="20" y2="40" gradientUnits="userSpaceOnUse">
+<stop stop-color="#6B7280"/>
+<stop offset="1" stop-color="#1F2937"/>
+</linearGradient>
+<linearGradient id="paint1_linear_834_8427" x1="19.7856" y1="8" x2="19.7856" y2="32" gradientUnits="userSpaceOnUse">
+<stop stop-color="#F9FAFB"/>
 <stop offset="1" stop-color="#9CA3AF"/>
 </linearGradient>
 </defs>

+ 13 - 5
studio/template/images/icons/mi-agt-helpers.svg

@@ -1,6 +1,14 @@
-<svg width="28" height="28" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
-<g id="Icon">
-<path id="Ellipse 1" d="M14 17C17.3137 17 20 14.3137 20 11C20 7.68629 17.3137 5 14 5C10.6863 5 8 7.68629 8 11" stroke="#D1D5DB" stroke-width="2" stroke-linecap="round"/>
-<circle id="Ellipse 3" cx="14" cy="22" r="1" stroke="#D1D5DB" stroke-width="2"/>
-</g>
+<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M13.5237 9.76191C13.5237 9.13072 14.0354 8.61905 14.6665 8.61905H19.9999C20.6311 8.61905 21.1427 9.13072 21.1427 9.76191V13.9524H27.9999C30.1038 13.9524 31.8094 15.658 31.8094 17.7619V21.9524H33.3332C33.9644 21.9524 34.4761 22.4641 34.4761 23.0952C34.4761 23.7264 33.9644 24.2381 33.3332 24.2381H31.8094V28.4286C31.8094 30.5325 30.1038 32.2381 27.9999 32.2381H11.9999C9.89593 32.2381 8.19035 30.5325 8.19035 28.4286V24.2381H6.66654C6.03536 24.2381 5.52368 23.7264 5.52368 23.0952C5.52368 22.4641 6.03536 21.9524 6.66654 21.9524H8.19035V17.7619C8.19035 15.658 9.89593 13.9524 11.9999 13.9524H18.857V10.9048H14.6665C14.0354 10.9048 13.5237 10.3931 13.5237 9.76191ZM11.9999 16.2381C11.1583 16.2381 10.4761 16.9203 10.4761 17.7619V28.4286C10.4761 29.2701 11.1583 29.9524 11.9999 29.9524H27.9999C28.8414 29.9524 29.5237 29.2701 29.5237 28.4286V17.7619C29.5237 16.9203 28.8414 16.2381 27.9999 16.2381H11.9999ZM15.9999 20.619C16.6311 20.619 17.1427 21.1307 17.1427 21.7619V24.4286C17.1427 25.0598 16.6311 25.5714 15.9999 25.5714C15.3687 25.5714 14.857 25.0598 14.857 24.4286V21.7619C14.857 21.1307 15.3687 20.619 15.9999 20.619ZM23.9999 20.619C24.6311 20.619 25.1427 21.1307 25.1427 21.7619V24.4286C25.1427 25.0598 24.6311 25.5714 23.9999 25.5714C23.3687 25.5714 22.857 25.0598 22.857 24.4286V21.7619C22.857 21.1307 23.3687 20.619 23.9999 20.619Z" fill="black" fill-opacity="0.2"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M13.5237 8.76191C13.5237 8.13072 14.0354 7.61905 14.6665 7.61905H19.9999C20.6311 7.61905 21.1427 8.13072 21.1427 8.76191V12.9524H27.9999C30.1038 12.9524 31.8094 14.658 31.8094 16.7619V20.9524H33.3332C33.9644 20.9524 34.4761 21.4641 34.4761 22.0952C34.4761 22.7264 33.9644 23.2381 33.3332 23.2381H31.8094V27.4286C31.8094 29.5325 30.1038 31.2381 27.9999 31.2381H11.9999C9.89593 31.2381 8.19035 29.5325 8.19035 27.4286V23.2381H6.66654C6.03536 23.2381 5.52368 22.7264 5.52368 22.0952C5.52368 21.4641 6.03536 20.9524 6.66654 20.9524H8.19035V16.7619C8.19035 14.658 9.89593 12.9524 11.9999 12.9524H18.857V9.90476H14.6665C14.0354 9.90476 13.5237 9.39309 13.5237 8.76191ZM11.9999 15.2381C11.1583 15.2381 10.4761 15.9203 10.4761 16.7619V27.4286C10.4761 28.2701 11.1583 28.9524 11.9999 28.9524H27.9999C28.8414 28.9524 29.5237 28.2701 29.5237 27.4286V16.7619C29.5237 15.9203 28.8414 15.2381 27.9999 15.2381H11.9999ZM15.9999 19.619C16.6311 19.619 17.1427 20.1307 17.1427 20.7619V23.4286C17.1427 24.0598 16.6311 24.5714 15.9999 24.5714C15.3687 24.5714 14.857 24.0598 14.857 23.4286V20.7619C14.857 20.1307 15.3687 19.619 15.9999 19.619ZM23.9999 19.619C24.6311 19.619 25.1427 20.1307 25.1427 20.7619V23.4286C25.1427 24.0598 24.6311 24.5714 23.9999 24.5714C23.3687 24.5714 22.857 24.0598 22.857 23.4286V20.7619C22.857 20.1307 23.3687 19.619 23.9999 19.619Z" fill="url(#paint1_linear_1640_8278)"/>
+<defs>
+<linearGradient id="paint0_linear_1640_8278" x1="20" y1="0" x2="20" y2="40" gradientUnits="userSpaceOnUse">
+<stop stop-color="#6B7280"/>
+<stop offset="1" stop-color="#1F2937"/>
+</linearGradient>
+<linearGradient id="paint1_linear_1640_8278" x1="19.9999" y1="7.61905" x2="19.9999" y2="31.2381" gradientUnits="userSpaceOnUse">
+<stop stop-color="#F9FAFB"/>
+<stop offset="1" stop-color="#9CA3AF"/>
+</linearGradient>
+</defs>
 </svg>

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 2
studio/template/images/icons/mi-agt-providers.svg


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 1
studio/template/images/icons/mi-cog.svg


+ 64 - 7
studio/template/scripts/BxBaseStudioAgents.php

@@ -35,12 +35,15 @@ class BxBaseStudioAgents extends BxDolStudioAgents
             BX_DOL_STUDIO_AGENTS_TYPE_SETTINGS => ['icon' => 'mi-cog.svg', 'icon_bg' => true],
             BX_DOL_STUDIO_AGENTS_TYPE_PROVIDERS => ['icon' => 'mi-agt-providers.svg', 'icon_bg' => true],
             BX_DOL_STUDIO_AGENTS_TYPE_HELPERS => ['icon' => 'mi-agt-helpers.svg', 'icon_bg' => true],
+            BX_DOL_STUDIO_AGENTS_TYPE_ASSISTANTS => ['icon' => 'mi-agt-assistants.svg', 'icon_bg' => true],
             BX_DOL_STUDIO_AGENTS_TYPE_AUTOMATORS => ['icon' => 'mi-agt-automators.svg', 'icon_bg' => true],
         ];
 
         $this->aGridObjects = [
             BX_DOL_STUDIO_AGENTS_TYPE_AUTOMATORS => 'sys_studio_agents_automators',
             BX_DOL_STUDIO_AGENTS_TYPE_PROVIDERS => 'sys_studio_agents_providers',
+            BX_DOL_STUDIO_AGENTS_TYPE_ASSISTANTS => 'sys_studio_agents_assistants',
+            BX_DOL_STUDIO_AGENTS_TYPE_ASSISTANTS . '_chats' => 'sys_studio_agents_assistants_chats',
             BX_DOL_STUDIO_AGENTS_TYPE_HELPERS => 'sys_studio_agents_helpers',
         ];
     }
@@ -81,12 +84,10 @@ class BxBaseStudioAgents extends BxDolStudioAgents
     protected function getAutomators()
     {
         $oTemplate = BxDolStudioTemplate::getInstance();
-        
+
         $this->aPageJsOptions['sPageUrl'] .= 'automators';
 
         if(($iId = bx_get('id')) !== false) {
-            $sCmts = 'sys_agents_automators';
-
             $this->aPageJsOptions = array_merge($this->aPageJsOptions, [
                 'sPageUrl' => $this->sSubpageUrl . 'automators&id=' . $iId,
                 'sActionUrlCmts' => bx_append_url_params(BX_DOL_URL_ROOT . 'cmts.php', [
@@ -95,8 +96,10 @@ class BxBaseStudioAgents extends BxDolStudioAgents
                 ])
             ]);
 
-            $oCmts = BxDolCmts::getObjectInstance($sCmts, (int)$iId, true, $oTemplate);
-            return $oCmts->getCommentsBlock();
+            if(($oCmts = BxDolAI::getInstance()->getAutomatorCmts($iId, $oTemplate)) !== false)
+                return $oCmts->getCommentsBlock();
+            else
+                return MsgBox(_t('_error occured'));
         }
 
         return $this->getGrid($this->aGridObjects[BX_DOL_STUDIO_AGENTS_TYPE_AUTOMATORS]);
@@ -132,6 +135,60 @@ class BxBaseStudioAgents extends BxDolStudioAgents
         return $this->getGrid($this->aGridObjects[BX_DOL_STUDIO_AGENTS_TYPE_HELPERS]);
     }
 
+    protected function getAssistants()
+    {
+        $oAi = BxDolAI::getInstance();
+        $oTemplate = BxDolStudioTemplate::getInstance();
+        
+        $this->aPageJsOptions['sPageUrl'] .= 'assistants';
+
+        $iAssistantId = 0;
+        if(($iAssistantId = bx_get('aid')) !== false)
+            $iAssistantId = bx_process_input($iAssistantId, BX_DATA_INT);
+
+        $iChatId = 0;
+        if(($iChatId = bx_get('cid')) !== false)
+            $iChatId = bx_process_input($iChatId, BX_DATA_INT);
+
+        if($iAssistantId && $iChatId) {
+            $sCmts = 'sys_agents_assistants_chats';
+
+            $this->aPageJsOptions = array_merge($this->aPageJsOptions, [
+                'sPageUrl' => $this->sSubpageUrl . 'assistants&aid=' . $iAssistantId . '&cid=' . $iChatId,
+                'sActionUrlCmts' => bx_append_url_params(BX_DOL_URL_ROOT . 'cmts.php', [
+                    'sys' => $sCmts,
+                    'id' => $iChatId
+                ])
+            ]);
+
+            if(($oCmts = $oAi->getAssistantChatCmts($iChatId, $oTemplate)) !== false)
+                return $oCmts->getCommentsBlock();
+            else
+                return MsgBox(_t('_error occured'));
+        }
+        else if($iAssistantId) {
+            $aResult = [];
+
+            $aAssistant = $oAi->getAssistantById($iAssistantId);
+            if(!empty($aAssistant) && is_array($aAssistant))
+                $aResult[] = $oTemplate->parseHtmlByName('agents_assistant_info.html', [
+                    'assistant_name' => $aAssistant['name'],
+                    'assistant_info' => $aAssistant['description'],
+                    'bx_if:show_chat' => [
+                        'condition' => false,
+                        'content' => [true]
+                    ],
+                    'url_back' => $this->aPageJsOptions['sPageUrl']
+                ]);
+            
+            $aResult[] = $this->getGrid($this->aGridObjects[BX_DOL_STUDIO_AGENTS_TYPE_ASSISTANTS . '_chats']);
+
+            return $aResult;
+        }
+
+        return $this->getGrid($this->aGridObjects[BX_DOL_STUDIO_AGENTS_TYPE_ASSISTANTS]);
+    }
+
     protected function getProviders()
     {
         $this->aPageJsOptions = array_merge($this->aPageJsOptions, [
@@ -144,13 +201,13 @@ class BxBaseStudioAgents extends BxDolStudioAgents
         return $this->getGrid($this->aGridObjects[BX_DOL_STUDIO_AGENTS_TYPE_PROVIDERS]);
     }
 
-    protected function getGrid($sObjectName)
+    protected function getGrid($sObjectName, $bObject = false)
     {
         $oGrid = BxDolGrid::getObjectInstance($sObjectName);
         if(!$oGrid)
             return '';
 
-        return $oGrid->getCode();
+        return $bObject ? $oGrid : $oGrid->getCode();
     }
     
     protected function _getHelpersForm($sAction, $aHelper = [])

+ 338 - 0
studio/template/scripts/BxBaseStudioAgentsAssistants.php

@@ -0,0 +1,338 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    UnaView UNA Studio Representation classes
+ * @ingroup     UnaStudio
+ * @{
+ */
+
+class BxBaseStudioAgentsAssistants extends BxDolStudioAgentsAssistants
+{
+    protected $_sUrlPage;
+    protected $_sFieldName;
+
+    public function __construct ($aOptions, $oTemplate = false)
+    {
+        parent::__construct ($aOptions, $oTemplate);
+
+        $this->_sUrlPage = BX_DOL_URL_STUDIO . 'agents.php?page=assistants';
+
+        $this->_sFieldName = 'name';
+    }
+
+    public function getPageJsObject()
+    {
+        return 'oBxDolStudioPageAgents';
+    }
+
+    public function performActionAdd()
+    {
+        $sAction = 'add';
+
+        $oAI = BxDolAI::getInstance();
+
+        $aForm = $this->_getForm($sAction);
+        $oForm = new BxTemplFormView($aForm);
+        $oForm->initChecker();
+
+        if($oForm->isSubmittedAndValid()) {
+            $aValsToAdd = ['added' => time()];
+
+            $sName = $oForm->getCleanValue($this->_sFieldName);
+            $sName = $this->_getAssistantName($sName);
+            BxDolForm::setSubmittedValue($this->_sFieldName, $sName, $oForm->aFormAttrs['method']);
+
+            $iProfileId = $oForm->getCleanValue('profile_id');
+            if(empty($iProfileId)) {
+                $iProfileId = (int)getParam('sys_agents_profile');
+                if(empty($iProfileId))
+                    $iProfileId = current(bx_srv('system', 'get_options_agents_profile', [false], 'TemplServices'))['key'];
+
+                $aValsToAdd['profile_id'] = $iProfileId;
+            }
+
+            $iAIModel = $oForm->getCleanValue('model_id');
+            $oAIModel = $oAI->getModelObject($iAIModel);
+
+            $sMessage = $oForm->getCleanValue('message');
+            $oAIModel->getAssistant($sMessage, ['name' => $sName]);
+
+            //TODO: Make calls to create Storage and Assistante
+
+            $bIsValid = true;
+            if($bIsValid) {
+                if(($iId = $oForm->insert($aValsToAdd)) !== false) {
+                    $aRes = ['grid' => $this->getCode(false), 'blink' => $iId];
+                }
+                else
+                    $aRes = ['msg' => _t('_sys_txt_error_occured')];
+
+                return echoJson($aRes);
+            }
+        }
+
+        $sFormId = $oForm->getId();
+        $sContent = BxTemplStudioFunctions::getInstance()->popupBox($sFormId . '_popup', _t('_sys_agents_assistants_popup_add'), $this->_oTemplate->parseHtmlByName('agents_automator_form.html', [
+            'form_id' => $sFormId,
+            'form' => $oForm->getCode(true),
+            'object' => $this->_sObject,
+            'action' => $sAction
+        ]));
+
+        return echoJson(['popup' => ['html' => $sContent, 'options' => ['closeOnOuterClick' => false]]]);
+    }
+
+    public function performActionEdit()
+    {
+        $sAction = 'edit';
+
+        $iId = $this->_getId();
+        $aHelper = $this->_oDb->getAssistantsBy(['sample' => 'id', 'id' => $iId]);
+
+        $aForm = $this->_getFormEdit($sAction, $aHelper);
+        $oForm = new BxTemplFormView($aForm);
+        $oForm->initChecker();
+
+        if($oForm->isSubmittedAndValid()) {
+            $aValsToAdd = [];
+
+            $sName = $oForm->getCleanValue($this->_sFieldName);
+            if($aHelper[$this->_sFieldName] != $sName) {
+                $sName = $this->_getAssistantName($sName);
+                BxDolForm::setSubmittedValue($this->_sFieldName, $sName, $oForm->aFormAttrs['method']);
+            }
+
+            $iProfileId = $oForm->getCleanValue('profile_id');
+            if(empty($iProfileId)) {
+                $iProfileId = (int)getParam('sys_agents_profile');
+                if(empty($iProfileId))
+                    $iProfileId = current(bx_srv('system', 'get_options_agents_profile', [false], 'TemplServices'))['key'];
+
+                $aValsToAdd['profile_id'] = $iProfileId;
+            }
+            
+            if($oForm->update($iId, $aValsToAdd) !== false)
+                $aRes = ['grid' => $this->getCode(false), 'blink' => $iId];
+            else
+                $aRes = ['msg' => _t('_sys_txt_error_occured')];
+
+            return echoJson($aRes);
+        } 
+
+        $sFormId = $oForm->getId();
+        $sContent = BxTemplStudioFunctions::getInstance()->popupBox($sFormId . '_popup', _t('_sys_agents_assistants_popup_edit'), $this->_oTemplate->parseHtmlByName('agents_automator_form.html', [
+            'form_id' => $sFormId,
+            'form' => $oForm->getCode(true),
+            'object' => $this->_sObject,
+            'action' => $sAction
+        ]));
+
+        return echoJson(['popup' => ['html' => $sContent, 'options' => ['closeOnOuterClick' => false]]]);
+    }
+
+    protected function _getCellModelId($mixedValue, $sKey, $aField, $aRow)
+    {
+        $aModel = $this->_oDb->getModelsBy(['sample' => 'id', 'id' => $mixedValue]);
+        if(!empty($aModel) && is_array($aModel))
+            $mixedValue = $aModel['title'];
+
+        return parent::_getCellDefault($mixedValue, $sKey, $aField, $aRow);
+    }
+
+    protected function _getCellProfileId($mixedValue, $sKey, $aField, $aRow)
+    {
+        return parent::_getCellDefault(BxDolProfile::getInstanceMagic($mixedValue)->getDisplayName(), $sKey, $aField, $aRow);
+    }
+
+    protected function _getCellAdded($mixedValue, $sKey, $aField, $aRow)
+    {
+        return parent::_getCellDefault(bx_time_js($mixedValue), $sKey, $aField, $aRow);
+    }
+
+    protected function _getActionChats($sType, $sKey, $a, $isSmall = false, $isDisabled = false, $aRow = [])
+    {
+    	$a['attr'] = array_merge($a['attr'], [
+            "onclick" => "window.open('" . $this->_sUrlPage . '&aid=' . $aRow['id'] . "', '_self');"
+    	]);
+
+    	return $this->_getActionDefault ($sType, $sKey, $a, $isSmall, $isDisabled, $aRow);
+    }
+
+    protected function _addJsCss()
+    {
+        parent::_addJsCss();
+
+        $this->_oTemplate->addJs(['jquery.form.min.js']);
+
+        $oForm = new BxTemplStudioFormView([]);
+        $oForm->addCssJs();
+    }
+    
+    protected function _isCheckboxDisabled($aRow)
+    {
+        return false;
+    }
+
+    protected function _getActionsDisabledBehavior($aRow)
+    {
+        return false;
+    }
+
+    protected function _delete ($mixedId)
+    {
+        $mixedResult = parent::_delete($mixedId);
+        if($mixedResult) {
+            $oAi = BxDolAI::getInstance();
+            $iAssistantId = (int)$mixedId;
+
+            $aChats = $this->_oDb->getChatsBy(['sample' => 'assistant_id', 'assistant_id' => $iAssistantId]);
+            foreach($aChats as $aChat)
+                if(($oCmts = $oAi->getAssistantChatCmts($aChat['id'])) !== false)
+                    $oCmts->onObjectDelete();
+
+            $this->_oDb->deleteChats(['assistant_id' => $iAssistantId]);
+
+            $this->_oDb->deleteAutomatorAssistants(['assistant_id' => $iAssistantId]);
+        }
+
+        return $mixedResult;
+    }
+
+    protected function _getFormEdit($sAction, $aHelper = [])
+    {
+        $aForm = $this->_getForm($sAction, $aHelper);
+        $aForm['form_attrs']['action'] .= '&id=' . $aHelper['id'];
+
+        return $aForm;
+    }
+
+    protected function _getForm($sAction, $aHelper = [])
+    {
+        $sJsObject = $this->getPageJsObject();
+
+        $aForm = [
+            'form_attrs' => [
+                'id' => 'bx_std_agents_assistants_' . $sAction,
+                'action' => BX_DOL_URL_ROOT . bx_append_url_params('grid.php', ['o' => 'sys_studio_agents_assistants', 'a' => $sAction]),
+                'method' => 'post',
+            ],
+            'params' => [
+                'db' => [
+                    'table' => 'sys_agents_assistants',
+                    'key' => 'id',
+                    'submit_name' => 'do_submit',
+                ],
+            ],
+            'inputs' => [
+                'name' => [
+                    'type' => 'text',
+                    'name' => 'name',
+                    'required' => '1',
+                    'caption' => _t('_sys_agents_assistants_field_name'),
+                    'value' => isset($aHelper['name']) ? $aHelper['name'] : '',
+                    'required' => '1',
+                    'checker' => [
+                        'func' => 'Avail',
+                        'params' => [],
+                        'error' => _t('_sys_agents_form_field_err_enter'),
+                    ],
+                    'db' => [
+                        'pass' => 'Xss',
+                    ]
+                ],
+                'model_id' => [
+                    'type' => 'select',
+                    'name' => 'model_id',
+                    'caption' => _t('_sys_agents_assistants_field_model_id'),
+                    'info' => '',
+                    'value' => isset($aHelper['model_id']) ? $aHelper['model_id'] : BxDolAI::getInstance()->getDefaultModel(),
+                    'values' => $this->_oDb->getModelsBy(['sample' => 'all_pairs', 'for_asst' => 1]),
+                    'required' => '1',
+                    'db' => [
+                        'pass' => 'Int',
+                    ]
+                ],
+                'profile_id' => [
+                    'type' => 'select',
+                    'name' => 'profile_id',
+                    'caption' => _t('_sys_agents_assistants_field_profile_id'),
+                    'info' => _t('_sys_agents_assistants_field_profile_id_inf'),
+                    'value' => isset($aHelper['profile_id']) ? $aHelper['profile_id'] : 0,
+                    'values' => bx_srv('system', 'get_options_agents_profile', [], 'TemplServices'),
+                    'required' => '0',
+                    'db' => [
+                        'pass' => 'Int',
+                    ]
+                ],
+                'description' => [
+                    'type' => 'textarea',
+                    'name' => 'description',
+                    'caption' => _t('_sys_agents_assistants_field_description'),
+                    'value' => isset($aHelper['description']) ? $aHelper['description'] : '',
+                    'required' => '1',
+                    'checker' => [
+                        'func' => 'Avail',
+                        'params' => [],
+                        'error' => _t('_sys_agents_form_field_err_enter'),
+                    ],
+                    'db' => [
+                        'pass' => 'Xss',
+                    ]
+                ],
+                'prompt' => [
+                    'type' => 'textarea',
+                    'name' => 'prompt',
+                    'caption' => _t('_sys_agents_assistants_field_prompt'),
+                    'value' => isset($aHelper['prompt']) ? $aHelper['prompt'] : '',
+                    'required' => '1',
+                    'checker' => [
+                        'func' => 'Avail',
+                        'params' => [],
+                        'error' => _t('_sys_agents_assistants_field_prompt_err'),
+                    ],
+                    'db' => [
+                        'pass' => 'Xss',
+                    ]
+                ],
+                'submit' => [
+                    'type' => 'input_set',
+                    0 => [
+                        'type' => 'submit',
+                        'name' => 'do_submit',
+                        'value' => _t('_sys_submit'),
+                    ],
+                    1 => [
+                        'type' => 'reset',
+                        'name' => 'close',
+                        'value' => _t('_sys_close'),
+                        'attrs' => ['class' => 'bx-def-margin-sec-left', 'onclick' => '$(\'.bx-popup-applied:visible\').dolPopupHide();'],
+                    ],
+                ],
+            ],
+        ];
+
+        return $aForm;
+    }
+    
+    protected function _getId()
+    {
+        $aIds = bx_get('ids');
+        if(!empty($aIds) && is_array($aIds))
+            return array_shift($aIds);
+
+        $iId = (int)bx_get('id');
+        if(!$iId)
+            return false;
+
+        return $iId;
+    }
+
+    protected function _getAssistantName($sName)
+    {
+        return uriGenerate($sName, 'sys_agents_assistants', 'name', ['lowercase' => false]);
+    }
+}
+
+/** @} */

+ 239 - 0
studio/template/scripts/BxBaseStudioAgentsAsstChats.php

@@ -0,0 +1,239 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    UnaView UNA Studio Representation classes
+ * @ingroup     UnaStudio
+ * @{
+ */
+
+class BxBaseStudioAgentsAsstChats extends BxDolStudioAgentsAsstChats
+{
+    protected $_sUrlPage;
+    protected $_sFieldName;
+
+    public function __construct ($aOptions, $oTemplate = false)
+    {
+        parent::__construct ($aOptions, $oTemplate);
+
+        $this->_sUrlPage = BX_DOL_URL_STUDIO . 'agents.php?page=assistants&aid=' . $this->_iAssistantId;
+
+        $this->_sFieldName = 'name';
+    }
+
+    public function getPageJsObject()
+    {
+        return 'oBxDolStudioPageAgents';
+    }
+
+    public function performActionAdd()
+    {
+        $sAction = 'add';
+
+        $aForm = $this->_getForm($sAction);
+        $oForm = new BxTemplFormView($aForm);
+        $oForm->initChecker();
+
+        if($oForm->isSubmittedAndValid()) {
+            $aValsToAdd = ['assistant_id' => $this->_iAssistantId, 'added' => time()];
+
+            $sName = $oForm->getCleanValue($this->_sFieldName);
+            $sName = $this->_getChatName($sName);
+            BxDolForm::setSubmittedValue($this->_sFieldName, $sName, $oForm->aFormAttrs['method']);
+
+            if(($iId = $oForm->insert($aValsToAdd)) !== false)
+                $aRes = ['grid' => $this->getCode(false), 'blink' => $iId];
+            else
+                $aRes = ['msg' => _t('_sys_txt_error_occured')];
+
+            return echoJson($aRes);
+        }
+
+        $sFormId = $oForm->getId();
+        $sContent = BxTemplStudioFunctions::getInstance()->popupBox($sFormId . '_popup', _t('_sys_agents_assistants_chats_popup_add'), $this->_oTemplate->parseHtmlByName('agents_automator_form.html', [
+            'form_id' => $sFormId,
+            'form' => $oForm->getCode(true),
+            'object' => $this->_sObject,
+            'action' => $sAction
+        ]));
+
+        return echoJson(['popup' => ['html' => $sContent, 'options' => ['closeOnOuterClick' => false]]]);
+    }
+
+    public function performActionEdit()
+    {
+        $sAction = 'edit';
+
+        $iId = $this->_getId();
+        $aChat = $this->_oDb->getChatsBy(['sample' => 'id', 'id' => $iId]);
+
+        $aForm = $this->_getFormEdit($sAction, $aChat);
+        $oForm = new BxTemplFormView($aForm);
+        $oForm->initChecker();
+
+        if($oForm->isSubmittedAndValid()) {
+            $aValsToAdd = [];
+
+            $sName = $oForm->getCleanValue($this->_sFieldName);
+            if($aChat[$this->_sFieldName] != $sName) {
+                $sName = $this->_getChatName($sName);
+                BxDolForm::setSubmittedValue($this->_sFieldName, $sName, $oForm->aFormAttrs['method']);
+            }
+
+            if($oForm->update($iId, $aValsToAdd) !== false)
+                $aRes = ['grid' => $this->getCode(false), 'blink' => $iId];
+            else
+                $aRes = ['msg' => _t('_sys_txt_error_occured')];
+
+            return echoJson($aRes);
+        } 
+
+        $sFormId = $oForm->getId();
+        $sContent = BxTemplStudioFunctions::getInstance()->popupBox($sFormId . '_popup', _t('_sys_agents_assistants_chats_popup_edit'), $this->_oTemplate->parseHtmlByName('agents_automator_form.html', [
+            'form_id' => $sFormId,
+            'form' => $oForm->getCode(true),
+            'object' => $this->_sObject,
+            'action' => $sAction
+        ]));
+
+        return echoJson(['popup' => ['html' => $sContent, 'options' => ['closeOnOuterClick' => false]]]);
+    }
+
+    protected function _getCellAdded($mixedValue, $sKey, $aField, $aRow)
+    {
+        return parent::_getCellDefault(bx_time_js($mixedValue), $sKey, $aField, $aRow);
+    }
+
+    protected function _getCellStored($mixedValue, $sKey, $aField, $aRow)
+    {
+        return parent::_getCellDefault($mixedValue ? bx_time_js($mixedValue) : '', $sKey, $aField, $aRow);
+    }
+
+    protected function _getActionChat($sType, $sKey, $a, $isSmall = false, $isDisabled = false, $aRow = [])
+    {
+    	$a['attr'] = array_merge($a['attr'], [
+            "onclick" => "window.open('" . $this->_sUrlPage . "&cid=" . $aRow['id'] . "', '_self');"
+    	]);
+
+    	return $this->_getActionDefault ($sType, $sKey, $a, $isSmall, $isDisabled, $aRow);
+    }
+
+    protected function _addJsCss()
+    {
+        parent::_addJsCss();
+
+        $this->_oTemplate->addJs(['jquery.form.min.js']);
+
+        $oForm = new BxTemplStudioFormView([]);
+        $oForm->addCssJs();
+    }
+    
+    protected function _isCheckboxDisabled($aRow)
+    {
+        return false;
+    }
+
+    protected function _getActionsDisabledBehavior($aRow)
+    {
+        return false;
+    }
+
+    protected function _getFormEdit($sAction, $aChat = [])
+    {
+        $aForm = $this->_getForm($sAction, $aChat);
+        $aForm['form_attrs']['action'] .= '&id=' . $aChat['id'];
+
+        return $aForm;
+    }
+
+    protected function _getForm($sAction, $aChat = [])
+    {
+        $sJsObject = $this->getPageJsObject();
+
+        $aForm = array(
+            'form_attrs' => array(
+                'id' => 'bx_std_agents_assistants_' . $sAction,
+                'action' => BX_DOL_URL_ROOT . bx_append_url_params('grid.php', ['o' => 'sys_studio_agents_assistants_chats', 'a' => $sAction, 'aid' => $this->_iAssistantId]),
+                'method' => 'post',
+            ),
+            'params' => array (
+                'db' => array(
+                    'table' => 'sys_agents_assistants_chats',
+                    'key' => 'id',
+                    'submit_name' => 'do_submit',
+                ),
+            ),
+            'inputs' => array(
+                'name' => [
+                    'type' => 'text',
+                    'name' => 'name',
+                    'required' => '1',
+                    'caption' => _t('_sys_agents_assistants_chats_field_name'),
+                    'value' => isset($aChat['name']) ? $aChat['name'] : '',
+                    'required' => '1',
+                    'checker' => [
+                        'func' => 'Avail',
+                        'params' => [],
+                        'error' => _t('_sys_agents_form_field_err_enter'),
+                    ],
+                    'db' => [
+                        'pass' => 'Xss',
+                    ]
+                ],
+                'description' => [
+                    'type' => 'textarea',
+                    'name' => 'description',
+                    'caption' => _t('_sys_agents_assistants_chats_field_description'),
+                    'value' => isset($aChat['description']) ? $aChat['description'] : '',
+                    'required' => '1',
+                    'checker' => [
+                        'func' => 'Avail',
+                        'params' => [],
+                        'error' => _t('_sys_agents_form_field_err_enter'),
+                    ],
+                    'db' => [
+                        'pass' => 'Xss',
+                    ]
+                ],
+                'submit' => array(
+                    'type' => 'input_set',
+                    0 => array (
+                        'type' => 'submit',
+                        'name' => 'do_submit',
+                        'value' => _t('_sys_submit'),
+                    ),
+                    1 => array (
+                        'type' => 'reset',
+                        'name' => 'close',
+                        'value' => _t('_sys_close'),
+                        'attrs' => array('class' => 'bx-def-margin-sec-left', 'onclick' => '$(\'.bx-popup-applied:visible\').dolPopupHide();'),
+                    ),
+                ),
+
+            ),
+        );
+
+        return $aForm;
+    }
+    
+    protected function _getId()
+    {
+        $aIds = bx_get('ids');
+        if(!empty($aIds) && is_array($aIds))
+            return array_shift($aIds);
+
+        $iId = (int)bx_get('id');
+        if(!$iId)
+            return false;
+
+        return $iId;
+    }
+
+    protected function _getChatName($sName)
+    {
+        return uriGenerate($sName, 'sys_agents_assistants_chats', 'name', ['lowercase' => false]);
+    }
+}
+
+/** @} */

+ 12 - 6
studio/template/scripts/BxBaseStudioAgentsAutomators.php

@@ -70,7 +70,7 @@ class BxBaseStudioAgentsAutomators extends BxDolStudioAgentsAutomators
 
             $oAIModel = $oAI->getModelObject($iModel);
 
-            $sInstructions = "\nAvailable data for code creation:\n".$oAI->getAutomatorInstruction('profile', $iProfileId);
+            $sInstructions = $oAI->getAutomatorInstruction('profile', $iProfileId);
             if(!empty($aProviders) && is_array($aProviders))
                 $sInstructions .= $oAI->getAutomatorInstruction('providers', $aProviders);
             if(!empty($aHelpers) && is_array($aHelpers))
@@ -112,7 +112,7 @@ class BxBaseStudioAgentsAutomators extends BxDolStudioAgentsAutomators
             }
 
             if($bIsValid) {
-                if(($sResponse = $oAIModel->getResponse($sType, $sMessage . $sInstructions . "\n Use data from alert accoding documentation:" . $sMessageAdd, $oAIModel->getParams())) !== false) {
+                if(($sResponse = $oAIModel->getResponse($sType, $sMessage . $sInstructions . $sMessageAdd, $oAIModel->getParams())) !== false) {
                     $sMessageResponse = $sResponse;
                 }
                 else {
@@ -287,7 +287,7 @@ class BxBaseStudioAgentsAutomators extends BxDolStudioAgentsAutomators
 
             if($oForm->update($iId, $aValsToAdd) !== false) {
                 if(($oCmts = BxDolCmts::getObjectInstance($this->_sCmts, $iId)) !== null) {
-                    $sInstructions = "\nAvailable data for code creation:\n".$oAI->getAutomatorInstruction('profile', $iProfileId);
+                    $sInstructions = $oAI->getAutomatorInstruction('profile', $iProfileId);
 
                     $aProviders = $this->_oDb->getAutomatorsBy(['sample' => 'providers_by_id_pairs', 'id' => $iId]);
                     if(!empty($aProviders) && is_array($aProviders))
@@ -361,7 +361,7 @@ class BxBaseStudioAgentsAutomators extends BxDolStudioAgentsAutomators
 
     protected function _getCellData($sKey, $aField, $aRow)
     {
-        if($sKey == 'message_id' && ($iCmtId = (int)$aRow[$sKey]) != 0 && ($oCmts = BxDolCmts::getObjectInstance($this->_sCmts, $aRow['id'])) !== null) {
+        if($sKey == 'message_id' && ($iCmtId = (int)$aRow[$sKey]) != 0 && ($oCmts = BxDolAI::getInstance()->getAutomatorCmts($aRow['id'])) !== false) {
             $aCmt = $oCmts->getCommentSimple($iCmtId);
             if(!empty($aCmt) && is_array($aCmt))
                 $aRow[$sKey] = $aCmt['cmt_text'];
@@ -393,7 +393,7 @@ class BxBaseStudioAgentsAutomators extends BxDolStudioAgentsAutomators
     {
         parent::_addJsCss();
 
-        $this->_oTemplate->addJs(['jquery.form.min.js', 'agents_automators.js']);
+        $this->_oTemplate->addJs(['jquery.form.min.js']);
 
         $oForm = new BxTemplStudioFormView([]);
         $oForm->addCssJs();
@@ -412,8 +412,14 @@ class BxBaseStudioAgentsAutomators extends BxDolStudioAgentsAutomators
     protected function _delete ($mixedId)
     {
         $mixedResult = parent::_delete($mixedId);
-        if($mixedResult)
+        if($mixedResult) {
             $this->_oDb->deleteAutomatorProviders(['automator_id' => (int)$mixedId]);
+            $this->_oDb->deleteAutomatorHelpers(['automator_id' => (int)$mixedId]);
+            $this->_oDb->deleteAutomatorAssistants(['automator_id' => (int)$mixedId]);
+
+            if(($oCmts = BxDolAI::getInstance()->getAutomatorCmts($mixedId)) !== false)
+                $oCmts->onObjectDelete();
+        }
 
         return $mixedResult;
     }

+ 10 - 1
studio/template/scripts/BxBaseStudioAgentsHelpers.php

@@ -154,7 +154,7 @@ class BxBaseStudioAgentsHelpers extends BxDolStudioAgentsHelpers
     {
         parent::_addJsCss();
 
-        $this->_oTemplate->addJs(['jquery.form.min.js', 'agents_helpers.js']);
+        $this->_oTemplate->addJs(['jquery.form.min.js']);
 
         $oForm = new BxTemplStudioFormView([]);
         $oForm->addCssJs();
@@ -170,6 +170,15 @@ class BxBaseStudioAgentsHelpers extends BxDolStudioAgentsHelpers
         return false;
     }
 
+    protected function _delete ($mixedId)
+    {
+        $mixedResult = parent::_delete($mixedId);
+        if($mixedResult)
+            $this->_oDb->deleteAutomatorHelpers(['helper_id' => (int)$mixedId]);
+
+        return $mixedResult;
+    }
+
     protected function _getFormEdit($sAction, $aHelper = [])
     {
         $aForm = $this->_getForm($sAction, $aHelper);

+ 5 - 2
studio/template/scripts/BxBaseStudioAgentsProviders.php

@@ -166,7 +166,7 @@ class BxBaseStudioAgentsProviders extends BxDolStudioAgentsProviders
     {
         parent::_addJsCss();
 
-        $this->_oTemplate->addJs(['jquery.form.min.js', 'agents_automators.js']);
+        $this->_oTemplate->addJs(['jquery.form.min.js']);
 
         $oForm = new BxTemplStudioFormView([]);
         $oForm->addCssJs();
@@ -185,9 +185,12 @@ class BxBaseStudioAgentsProviders extends BxDolStudioAgentsProviders
     protected function _delete ($mixedId)
     {
         $mixedResult = parent::_delete($mixedId);
-        if($mixedResult)
+        if($mixedResult) {
             $this->_oDb->deleteProviderValues(['provider_id' => (int)$mixedId]);
 
+            $this->_oDb->deleteAutomatorProviders(['provider_id' => (int)$mixedId]);
+        }
+
         return $mixedResult;
     }
 

+ 19 - 0
studio/template/scripts_templ/BxTemplStudioAgentsAssistants.php

@@ -0,0 +1,19 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    UnaStudioView UNA Studio Representation classes
+ * @ingroup     UnaStudio
+ * @{
+ */
+
+class BxTemplStudioAgentsAssistants extends BxBaseStudioAgentsAssistants
+{
+    public function __construct ($aOptions, $oTemplate = false)
+    {
+        parent::__construct ($aOptions, $oTemplate);
+    }
+}
+
+/** @} */

+ 19 - 0
studio/template/scripts_templ/BxTemplStudioAgentsAsstChats.php

@@ -0,0 +1,19 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    UnaStudioView UNA Studio Representation classes
+ * @ingroup     UnaStudio
+ * @{
+ */
+
+class BxTemplStudioAgentsAsstChats extends BxBaseStudioAgentsAsstChats
+{
+    public function __construct ($aOptions, $oTemplate = false)
+    {
+        parent::__construct ($aOptions, $oTemplate);
+    }
+}
+
+/** @} */

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно