Переглянути джерело

Ticket #5406 - AI Agents rewamp. Agent builder.

AntonLV 3 місяців тому
батько
коміт
8a1d6b27e4

+ 10 - 0
inc/classes/BxDolAI.php

@@ -444,6 +444,11 @@ class BxDolAI extends BxDolFactory implements iBxDolSingleton
         return $aAgents;
     }
 
+    public function getAgentsBy($aParams)
+    {
+        return $this->_oDb->getAgentsBy($aParams);
+    }
+
     public function getAgentsByProfileId($iProfileId)
     {
         return $this->_oDb->getAgentsByProfileId($iProfileId);
@@ -459,6 +464,11 @@ class BxDolAI extends BxDolFactory implements iBxDolSingleton
         return $this->_oDb->getAgentsByTriggerType($sTrigger);
     }
 
+    public function getAgentById($iId)
+    {
+        return $this->_oDb->getAgentById($iId);
+    }
+
     public function getAgentByTriggerWebhookKey($sKey)
     {
         return $this->_oDb->getAgentByTriggerWebhookKey($sKey);

+ 36 - 0
inc/classes/BxDolAIQuery.php

@@ -906,6 +906,42 @@ class BxDolAIQuery extends BxDolDb
         return $this->fromMemory('sys_agents_with_form_' . $sFormObject, 'getAll', "SELECT * FROM `sys_agents_agents` WHERE `trigger` = 'form-input' AND `form_object` = :form_object AND `active` = :active", ['form_object' => $sFormObject, 'active' => $bActiveOnly ? 1 : 0]);
     }
 
+    public function getAgentsBy($aParams = [])
+    {
+        $aMethod = ['name' => 'getAll', 'params' => [0 => 'query']];
+    	$sWhereClause = "";
+
+        switch($aParams['sample']) {
+            case 'id':
+            	$aMethod['name'] = 'getRow';
+            	$aMethod['params'][1] = [
+                    'id' => $aParams['id']
+                ];
+
+                $sWhereClause .= " AND `id`=:id";
+                break;
+
+            case 'all':
+                if(isset($aParams['active'])) {
+                    $aMethod['params'][3]['active'] = $aParams['active'];
+
+                    $sWhereClause .= " AND `active`=:active";
+                }
+                break;
+        }
+
+        $aMethod['params'][0] = "SELECT * 
+            FROM `sys_agents_agents`
+            WHERE 1" . $sWhereClause;
+
+        return call_user_func_array([$this, $aMethod['name']], $aMethod['params']);
+    }
+
+    public function getAgentById(int $iId): mixed
+    {
+        return $this->getAgentsBy(['sample' => 'id', 'id' => $iId]);
+    }
+
     public function getAgentByTriggerWebhookKey($sKey, $bActiveOnly = true)
     {
         return $this->getRow("SELECT * FROM `sys_agents_agents` WHERE `trigger` = 'scheduler' AND `webhook_key` = :key AND `active` = :active", ['key' => $sKey, 'active' => $bActiveOnly ? 1 : 0]);

+ 3 - 0
install/sql/system.sql

@@ -7198,6 +7198,9 @@ CREATE TABLE IF NOT EXISTS `sys_agents_assistants_chats_files` (
 CREATE TABLE `sys_agents_agents` (
   `id` int(11) NOT NULL AUTO_INCREMENT,
   `name` varchar(128) NOT NULL DEFAULT '',
+  `title` varchar(128) NOT NULL DEFAULT '',
+  `description` text NOT NULL,
+  `icon` text NOT NULL,
   `model_id` int(11) NOT NULL DEFAULT 0,
   `profile_id` int(11) NOT NULL DEFAULT 0,
   `prompt_system` text NOT NULL,

+ 18 - 6
modules/boonex/english/data/langs/system/en.xml

@@ -1128,13 +1128,12 @@
     <string name="_adm_lmi_cpt_actions"><![CDATA[Actions]]></string>
     <string name="_adm_lmi_cpt_api_config"><![CDATA[Configuration]]></string>
     <string name="_adm_lmi_cpt_agents"><![CDATA[Agents]]></string>
-    <string name="_adm_lmi_cpt_ai_providers"><![CDATA[AI Providers]]></string>
+    <string name="_adm_lmi_cpt_ai_providers"><![CDATA[Models]]></string>
     <string name="_adm_lmi_cpt_tools"><![CDATA[Tools]]></string>
-    <string name="_adm_lmi_cpt_vector_store"><![CDATA[Vector Store]]></string>
+    <string name="_adm_lmi_cpt_vector_store"><![CDATA[Knowledge]]></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_vector_store"><![CDATA[Vector Store]]></string>
     <string name="_adm_lmi_cpt_badges"><![CDATA[Badges]]></string>
     <string name="_adm_lmi_cpt_categories"><![CDATA[Categories]]></string>
     <string name="_adm_lmi_cpt_checkout"><![CDATA[Checkout {checkout_counter}]]></string>
@@ -2288,14 +2287,15 @@
     <string name="_sys_agents_automators_txt_code"><![CDATA[Code]]></string>
     <string name="_sys_agents_automators_txt_added"><![CDATA[Added]]></string>
     <string name="_sys_agents_automators_txt_status"><![CDATA[Status]]></string>
-    
     <string name="_sys_agents_agents_txt_name"><![CDATA[Name]]></string>
     <string name="_sys_agents_agents_txt_trigger"><![CDATA[Trigger]]></string>
     <string name="_sys_agents_agents_txt_profile_id"><![CDATA[Profile]]></string>
     <string name="_sys_agents_agents_popup_add"><![CDATA[Add agent]]></string>
-    
+    <string name="_sys_agents_builder_view_list"><![CDATA[List view]]></string>
+    <string name="_sys_agents_builder_view_grid"><![CDATA[Grid view]]></string>
+
     <string name="_Run"><![CDATA[Run]]></string>
-    
+
     <string name="_sys_agents_automators_btn_add"><![CDATA[Add]]></string>
     <string name="_sys_agents_automators_btn_tune"><![CDATA[Tune]]></string>
     <string name="_sys_agents_automators_btn_approve"><![CDATA[Approve]]></string>
@@ -2319,6 +2319,13 @@
     <string name="_sys_agents_automators_field_type_webhook"><![CDATA[Webhook]]></string>
     <string name="_sys_agents_field_trigger"><![CDATA[Trigger]]></string>
     <string name="_sys_agents_field_trigger_info"><![CDATA[Trigger which will initiate agent to run. Alert — system event notification. Scheduler — time-based scheduled execution. Webhook — external HTTP trigger. Manual — user-initiated run. Agent — triggered by another agent. Message — triggered by chat message. Form field — compose form field value.]]></string>
+    <string name="_sys_agents_field_trigger_alert"><![CDATA[Alert]]></string>
+    <string name="_sys_agents_field_trigger_scheduler"><![CDATA[Scheduler]]></string>
+    <string name="_sys_agents_field_trigger_webhook"><![CDATA[Webhook]]></string>
+    <string name="_sys_agents_field_trigger_manual"><![CDATA[Manual]]></string>
+    <string name="_sys_agents_field_trigger_agent"><![CDATA[Agent]]></string>
+    <string name="_sys_agents_field_trigger_message"><![CDATA[Message]]></string>
+    <string name="_sys_agents_field_trigger_form_input"><![CDATA[Form input]]></string>
     <string name="_sys_agents_field_alert_sample"><![CDATA[Alert: payload]]></string>
     <string name="_sys_agents_waiting_for_sample_data_alert"><![CDATA[Please select an alert to see its payload.]]></string>
     <string name="_sys_agents_waiting_for_sample_data_webhook"><![CDATA[Trigger webhook to see its payload.]]></string>
@@ -2347,6 +2354,11 @@
     <string name="_sys_agents_field_prompt_tools_info"><![CDATA[Instructions for using available tools.]]></string>
     <string name="_sys_agents_tools_popup_edit"><![CDATA[Edit tool]]></string>
     <string name="_sys_agents_field_title"><![CDATA[Title]]></string>
+    <string name="_sys_agents_field_title_info"><![CDATA[Title to display]]></string>
+    <string name="_sys_agents_field_description"><![CDATA[Description]]></string>
+    <string name="_sys_agents_field_description_info"><![CDATA[Provide a brief description for future references.]]></string>
+    <string name="_sys_agents_field_icon"><![CDATA[Icon]]></string>
+    <string name="_sys_agents_field_icon_info"><![CDATA[Icon to describe an agent better.]]></string>
     <string name="_sys_agents_tools_field_params"><![CDATA[Parameters]]></string>
     <string name="_sys_agents_tools_field_params_info"><![CDATA[Parameters for configuring the tool, specific to each tool]]></string>
     <string name="_sys_agents_field_chat_history_context"><![CDATA[Chat history context window]]></string>

+ 18 - 6
modules/boonex/russian/data/langs/system/ru.xml

@@ -1112,13 +1112,12 @@
     <string name="_adm_lmi_cpt_actions"><![CDATA[Действия]]></string>
     <string name="_adm_lmi_cpt_api_config"><![CDATA[Конфигурация]]></string>
     <string name="_adm_lmi_cpt_agents"><![CDATA[Агенты]]></string>
-    <string name="_adm_lmi_cpt_ai_providers"><![CDATA[ИИ поставщики]]></string>
+    <string name="_adm_lmi_cpt_ai_providers"><![CDATA[Модели]]></string>
     <string name="_adm_lmi_cpt_tools"><![CDATA[Инструменты]]></string>
-    <string name="_adm_lmi_cpt_vector_store"><![CDATA[Вектороное хранилище]]></string>
+    <string name="_adm_lmi_cpt_vector_store"><![CDATA[Знание]]></string>
     <string name="_adm_lmi_cpt_assistants"><![CDATA[Ассистент]]></string>
     <string name="_adm_lmi_cpt_automators"><![CDATA[Автоматизаторы]]></string>
     <string name="_adm_lmi_cpt_helpers"><![CDATA[Помощники]]></string>
-    <string name="_adm_lmi_cpt_vector_store"><![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>
@@ -2263,14 +2262,15 @@
         <string name="_sys_agents_automators_txt_code"><![CDATA[Код]]></string>
         <string name="_sys_agents_automators_txt_added"><![CDATA[Добавлено]]></string>
         <string name="_sys_agents_automators_txt_status"><![CDATA[Статус]]></string>
-        
         <string name="_sys_agents_agents_txt_name"><![CDATA[Название]]></string>
         <string name="_sys_agents_agents_txt_trigger"><![CDATA[Триггер]]></string>
         <string name="_sys_agents_agents_txt_profile_id"><![CDATA[Профиль]]></string>
         <string name="_sys_agents_agents_popup_add"><![CDATA[Добавить агента]]></string>
-        
+        <string name="_sys_agents_builder_view_list"><![CDATA[Список]]></string>
+        <string name="_sys_agents_builder_view_grid"><![CDATA[Таблица]]></string>
+
         <string name="_Run"><![CDATA[Запустить]]></string>
-        
+
         <string name="_sys_agents_automators_btn_add"><![CDATA[Добавить]]></string>
         <string name="_sys_agents_automators_btn_tune"><![CDATA[Настройка]]></string>
         <string name="_sys_agents_automators_btn_approve"><![CDATA[Одобрить]]></string>
@@ -2292,6 +2292,13 @@
         <string name="_sys_agents_automators_field_type_webhook"><![CDATA[Вебхук]]></string>
         <string name="_sys_agents_field_trigger"><![CDATA[Триггер]]></string>
         <string name="_sys_agents_field_trigger_info"><![CDATA[Триггер, который запускает агента. Alert — системное событие. Scheduler — запуск по расписанию. Webhook — HTTP внешний вызов. Manual — ручной запуск. Agent — запуск другим агентом. Message — сообщение пользователя.]]></string>
+        <string name="_sys_agents_field_trigger_alert"><![CDATA[Сигнал]]></string>
+        <string name="_sys_agents_field_trigger_scheduler"><![CDATA[Планировщик]]></string>
+        <string name="_sys_agents_field_trigger_webhook"><![CDATA[Вебхук]]></string>
+        <string name="_sys_agents_field_trigger_manual"><![CDATA[Мануальный]]></string>
+        <string name="_sys_agents_field_trigger_agent"><![CDATA[Агент]]></string>
+        <string name="_sys_agents_field_trigger_message"><![CDATA[Сообщение]]></string>
+        <string name="_sys_agents_field_trigger_form_input"><![CDATA[Ввод данных в форму]]></string>
         <string name="_sys_agents_field_alert_sample"><![CDATA[Alert - пример данных]]></string>
         <string name="_sys_agents_waiting_for_sample_data_alert"><![CDATA[Пожалуйста, выберите алерт, чтобы увидеть его данные.]]></string>
         <string name="_sys_agents_waiting_for_sample_data_webhook"><![CDATA[Пожалуйста, активируйте вебхук, чтобы увидеть его данные.]]></string>       
@@ -2321,6 +2328,11 @@
         <string name="_sys_agents_field_prompt_tools_info"><![CDATA[Инструкции по использованию доступных инструментов.]]></string>
         <string name="_sys_agents_tools_popup_edit"><![CDATA[Редактирование инструмента]]></string>
         <string name="_sys_agents_field_title"><![CDATA[Название]]></string>
+        <string name="_sys_agents_field_title_info"><![CDATA[Название для отображения]]></string>
+        <string name="_sys_agents_field_description"><![CDATA[Описание]]></string>
+        <string name="_sys_agents_field_description_info"><![CDATA[Предоставьте краткое описание для дальнейшего использования в качестве справочного материала.]]></string>
+        <string name="_sys_agents_field_icon"><![CDATA[Значок]]></string>
+        <string name="_sys_agents_field_icon_info"><![CDATA[Значок для более точного описания агента.]]></string>
         <string name="_sys_agents_tools_field_params"><![CDATA[Параметры]]></string>
         <string name="_sys_agents_tools_field_params_info"><![CDATA[Параметры для конфигурации этого инструмента, свои для каждого инструмента]]></string>
         <string name="_sys_agents_field_chat_history_context"><![CDATA[Размер контекста истории чата]]></string>

+ 1 - 1
studio/agents.php

@@ -17,7 +17,7 @@ bx_import('BxDolLanguages');
 bx_require_authentication(true);
 
 $sPage = bx_get('page');
-$sPage = $sPage !== false ? bx_process_input($sPage) : '';
+$sPage = $sPage !== false ? bx_process_input($sPage) : 'agents';
 
 $oPage = new BxTemplStudioAgents($sPage);
 BxDolStudioTemplate::getInstance()->displayPage($oPage);

+ 54 - 0
studio/classes/BxDolStudioAgents.php

@@ -26,16 +26,70 @@ define('BX_DOL_STUDIO_AGENTS_TYPE_DEFAULT', BX_DOL_STUDIO_AGENTS_TYPE_SETTINGS);
 
 class BxDolStudioAgents extends BxTemplStudioWidget
 {
+    protected $oDbAi;
+
     protected $sPage;
 
     function __construct($sPage = "")
     {
         parent::__construct('agents');
 
+        $this->oDbAi = new BxDolAIQuery();
+
         $this->sPage = BX_DOL_STUDIO_AGENTS_TYPE_DEFAULT;
         if(is_string($sPage) && !empty($sPage))
             $this->sPage = $sPage;
     }
+    
+    public function checkAction()
+    {
+        $sAction = bx_get('agt_action');
+    	if($sAction === false)
+            return false;
+
+        $sAction = bx_process_input($sAction);
+
+        $aResult = ['code' => 1, 'message' => _t('_adm_pgt_err_cannot_process_action')];
+        switch($sAction) {
+            case 'agent-check-name':
+                $sValue = false;
+                if(($sValue = bx_get('agt_value')) !== false)
+                    $sValue = bx_process_input($sValue, BX_DATA_TEXT);
+                else
+                    break;
+
+                $sNameFld = 'name';
+                $sNameVal = '';
+                if(($iId = (int)bx_get('id'))) {
+                    $aAgent = $this->oDbAi->getAgentById($iId);
+                    if(strcmp($sValue, $aAgent[$sNameFld]) == 0) 
+                        $sNameVal = $sValue;
+                }
+
+                $aResult = [
+                    'code' => 0,
+                    'title' => $sValue,
+                    'name' => $sNameVal ?: uriGenerate($sValue, 'sys_agents_agents', $sNameFld, ['lowercase' => true])
+                ];
+                break;
+                
+            case 'agent-activate':
+                $iValue = 0;
+                if(($iValue = bx_get('agt_value')) !== false)
+                    $iValue = bx_process_input($iValue, BX_DATA_TEXT);
+                else
+                    break;
+                
+                $aAgent = $this->oDbAi->getAgentById($iValue);
+                if(!$aAgent || !$this->oDbAi->updateAgentField($iValue, 'active', 1 - (int)$aAgent['active']))
+                    $aResult = ['coed' => 2, 'message' => _t('_sys_txt_error_occured')];
+                else
+                    $aResult = ['coed' => 0];
+                break;
+        }
+
+        return $aResult;
+    }
 }
 
 /** @} */

+ 63 - 0
studio/js/agents.js

@@ -10,6 +10,7 @@ function BxDolStudioPageAgents(oOptions)
     BxDolStudioPage.call(this, oOptions);
 
     this.sPageUrl = oOptions.sPageUrl;
+    this.sActionUrl = oOptions.sActionUrl;
     this.sObjName = oOptions.sObjName == undefined ? 'oBxDolStudioPageAgents' : oOptions.sObjName;
 
     this.sActionUrlCmts = oOptions.sActionUrlCmts == undefined ? this.sActionUrl : oOptions.sActionUrlCmts;
@@ -27,6 +28,68 @@ function BxDolStudioPageAgents(oOptions)
 BxDolStudioPageAgents.prototype = Object.create(BxDolStudioPage.prototype);
 BxDolStudioPageAgents.prototype.constructor = BxDolStudioPageAgents;
 
+BxDolStudioPageAgents.prototype.agentActivate = function(oSource) {
+    var oDate = new Date();
+    var oAgent = $(oSource).parents('.bx-agt-agent:first');
+
+    jQuery.get(
+        this.sActionUrl,
+        {
+            agt_action: 'agent-activate',
+            agt_value: parseInt(oAgent.attr('data-id')),
+            _t: oDate.getTime()
+        },
+        function(oData) {
+            processJsonData(oData);
+        },
+        'json'
+    );
+};
+
+BxDolStudioPageAgents.prototype.agentCheckName = function(oSource, sTitleId, sNameId, iId) {
+    var oDate = new Date();
+    var oForm = jQuery(oSource).parents('.bx-form-advanced:first');
+
+    var oName = oForm.find("[name='" + sNameId + "']");
+    var sName = oName.val();
+    var bName = sName.length != 0;
+
+    var oTitle = oForm.find("[name='" + sTitleId + "']");
+    var sTitle = oTitle.val();
+    var bTitle = sTitle.length != 0;
+
+    if(!bName && !bTitle)
+        return;
+
+    var sTitleCheck = '';
+    if(bName)
+        sTitleCheck = sName;
+    else if(bTitle) {
+        sTitleCheck = sTitle;
+
+        sTitle = sTitle.replace(/[^A-Za-z0-9_]/g, '-');
+        sTitle = sTitle.replace(/[-]{2,}/g, '-');
+        oName.val(sTitle.toLowerCase());
+    }
+
+    jQuery.get(
+        this.sActionUrl,
+        {
+            agt_action: 'agent-check-name',
+            agt_value: sTitleCheck,
+            id: iId && parseInt(iId) > 0 ? iId : 0,
+            _t: oDate.getTime()
+        },
+        function(oData) {
+            if(!oData || oData.name == undefined)
+                return;
+
+            oName.val(oData.name);
+        },
+        'json'
+    );
+};
+
 BxDolStudioPageAgents.prototype.onChangeAutomatorType = function(oSelect) {
     var aHide = [];
     var aShow = [];

+ 2 - 0
studio/template/agents.html

@@ -0,0 +1,2 @@
+__content__
+__js_content__

+ 64 - 0
studio/template/agents_agents.html

@@ -0,0 +1,64 @@
+<div class="bx-agt-agents w-full flex flex-row flex-wrap items-stretch -m-1">
+    <bx_repeat:agents>
+        <div class="bx-agt-agent-wrp flex w-full sm:w-1/2 lg:w-1/3 p-1">
+            <div class="bx-agt-agent bx-def-border flex-1 flex flex-col p-4 gap-2 rounded-lg shadow-md" data-id="__id__">
+                <div class="bx-agt-a-ic flex items-center justify-between gap-2">
+                    <div class="bx-agt-aic grow-0">__icon__</div>
+                    <div class="bx-agt-aic-aux flex items-center justify-center gap-1 shrink-0">
+                        <bx_if:show_trigger>
+                            <div class="bx-agt-aic-trigger w-7 h-7 flex items-center justify-center bg-gray-200/80 dark:bg-gray-800/80 rounded-full overflow-hidden">
+                                <img class="w-4 h-4" src="__trigger_icon_src__" title="__trigger_title__" />
+                            </div>
+                        </bx_if:show_trigger>
+                        <bx_if:show_model>
+                            <div class="bx-agt-aic-model w-7 h-7 flex items-center justify-center bg-gray-200/80 dark:bg-gray-800/80 rounded-full overflow-hidden">
+                                <img class="w-4 h-4" src="__model_icon_src__" title="__model_title__" />
+                            </div>
+                        </bx_if:show_model>
+                        <bx_if:show_profile>
+                            <div class="bx-agt-aic-profile w-7 h-7 flex items-center justify-center rounded-full overflow-hidden">__unit__</div>
+                        </bx_if:show_profile>
+                    </div>
+                </div>
+                <div class="bx-agt-a-ttl flex justify-between items-center gap-2 pt-1 min-w-0">
+                    <div class="bx-agt-attl flex-1 min-w-0 font-semibold text-base truncate">__title__</div>
+                    <div class="bx-agt-attl-act">__switcher__</div>
+                </div>
+                <div class="bx-agt-a-dsc text-sm">__description__</div>
+            </div>
+        </div>
+    </bx_repeat:agents>
+</div>
+
+<!--
+<div class="neo-v u-card-base bg-card/60 text-card-foreground shadow-card-outline dark:shadow-card-outline-deep px-4 py-4 gap-2 rounded-lg" role="region" aria-labelledby="_r_5_-region-title" bis_skin_checked="1">
+    <div class="neo-v flex-row items-center justify-between gap-2" bis_skin_checked="1">
+        <div class="neo-v w-9 h-9 bg-linear-to-b from-gray-500 to-gray-700 shadow dark:shadow-md-deep rounded-full items-center justify-center overflow-hidden shrink-0" bis_skin_checked="1">
+            <span class="text-white/90" style="display: inline-flex; width: 20px; height: 20px; min-width: 20px; min-height: 20px; background-color: currentcolor; mask-image: url(&quot;/api/api.icon?icon=ShieldUser&amp;width=20&amp;height=20&amp;strokeWidth=2&quot;); mask-size: contain; mask-repeat: no-repeat; mask-position: center center; mask-mode: alpha; flex-shrink: 0;"></span>
+            <span class="absolute text-black/10 translate-y-px" style="display: inline-flex; width: 20px; height: 20px; min-width: 20px; min-height: 20px; background-color: currentcolor; mask-image: url(&quot;/api/api.icon?icon=ShieldUser&amp;width=20&amp;height=20&amp;strokeWidth=2&quot;); mask-size: contain; mask-repeat: no-repeat; mask-position: center center; mask-mode: alpha; flex-shrink: 0;"></span>
+        </div>
+        <div class="neo-v flex-row items-center justify-center gap-1 shrink-0" bis_skin_checked="1">
+            <div class="neo-v w-7 h-7 bg-muted/50 rounded-full items-center justify-center overflow-hidden" aria-label="Alert trigger" bis_skin_checked="1">
+                <span class="text-card-foreground" style="display: inline-flex; width: 16px; height: 16px; min-width: 16px; min-height: 16px; background-color: currentcolor; mask-image: url(&quot;/api/api.icon?icon=BellRing&amp;width=16&amp;height=16&amp;strokeWidth=2&quot;); mask-size: contain; mask-repeat: no-repeat; mask-position: center center; mask-mode: alpha; flex-shrink: 0;"></span>
+            </div>
+            <div class="neo-v w-7 h-7 bg-muted/50 rounded-full items-center justify-center overflow-hidden text-card-foreground" aria-label="Claude" bis_skin_checked="1">
+                <span aria-label="Claude" role="img" class="text-card-foreground block shrink-0" style="width: 16px; height: 16px; background-color: currentcolor; mask-image: url(&quot;/_next/static/media/claude-color.8b281607.svg&quot;); mask-position: center center; mask-repeat: no-repeat; mask-size: contain;"></span>
+            </div>
+            <div class="neo-v w-7 h-7 rounded-full overflow-hidden shadow-avatar dark:shadow-avatar-deep border border-card/80" aria-label="Community Moderator community profile" bis_skin_checked="1"><div aria-label="Community Moderator community profile" class="css-g5y9jx r-1mlwlqe r-1udh08x r-417010" bis_skin_checked="1" style="width: 28px; height: 28px;">
+                <div class="css-g5y9jx r-1niwhzg r-vvn4in r-u6sd8q r-1p0dtai r-1pi2tsx r-1d2f490 r-u8s1d r-zchlnj r-ipm5af r-13qz1uu r-1wyyakw r-4gszlv" bis_skin_checked="1" style="background-image: url(&quot;/_next/static/media/user-01.d5c24ac2.jpg&quot;);"></div>
+                    <img alt="Community Moderator community profile" draggable="false" class="css-9pa8cd" src="/_next/static/media/user-01.d5c24ac2.jpg">
+                </div>
+            </div>
+        </div>
+    </div>
+    <div class="neo-v flex-row items-center gap-2 pt-1 min-w-0" bis_skin_checked="1">
+        <span class="flex-1 min-w-0 text-foreground font-semibold text-base truncate font-main line-clamp-1">Community Moderator</span>
+        <div class="neo-v shrink-0" bis_skin_checked="1">
+            <div class="neo-p web:cursor-pointer flex-row items-center rounded-full shrink-0 h-5 w-9 px-1 bg-primary" aria-checked="true" aria-disabled="false" role="switch" tabindex="0" bis_skin_checked="1">
+                <div class="neo-v rounded-full bg-popover/80 shadow-btn-outline dark:shadow-btn-outline-deep web:transition-transform web:duration-200 h-3 w-3 translate-x-4" bis_skin_checked="1"></div>
+            </div>
+        </div>
+    </div>
+    <span class="text-sm text-card-foreground font-main line-clamp-3">Reviews flagged posts, enforces guidelines, and keeps discussions constructive across groups and spaces.</span>
+</div>
+-->

+ 1 - 0
studio/template/images/icons/agt-trg-agent.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-bot-icon lucide-bot"><path d="M12 8V4H8"/><rect width="16" height="12" x="4" y="8" rx="2"/><path d="M2 14h2"/><path d="M20 14h2"/><path d="M15 13v2"/><path d="M9 13v2"/></svg>

+ 1 - 0
studio/template/images/icons/agt-trg-alert.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-bell-ring-icon lucide-bell-ring"><path d="M10.268 21a2 2 0 0 0 3.464 0"/><path d="M22 8c0-2.3-.8-4.3-2-6"/><path d="M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326"/><path d="M4 2C2.8 3.7 2 5.7 2 8"/></svg>

+ 1 - 0
studio/template/images/icons/agt-trg-form-input.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-text-cursor-input-icon lucide-text-cursor-input"><path d="M12 20h-1a2 2 0 0 1-2-2 2 2 0 0 1-2 2H6"/><path d="M13 8h7a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-7"/><path d="M5 16H4a2 2 0 0 1-2-2v-4a2 2 0 0 1 2-2h1"/><path d="M6 4h1a2 2 0 0 1 2 2 2 2 0 0 1 2-2h1"/><path d="M9 6v12"/></svg>

+ 1 - 0
studio/template/images/icons/agt-trg-manual.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-hand-icon lucide-hand"><path d="M18 11V6a2 2 0 0 0-2-2a2 2 0 0 0-2 2"/><path d="M14 10V4a2 2 0 0 0-2-2a2 2 0 0 0-2 2v2"/><path d="M10 10.5V6a2 2 0 0 0-2-2a2 2 0 0 0-2 2v8"/><path d="M18 8a2 2 0 1 1 4 0v6a8 8 0 0 1-8 8h-2c-2.8 0-4.5-.86-5.99-2.34l-3.6-3.6a2 2 0 0 1 2.83-2.82L7 15"/></svg>

+ 1 - 0
studio/template/images/icons/agt-trg-message.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-message-square-icon lucide-message-square"><path d="M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z"/></svg>

+ 1 - 0
studio/template/images/icons/agt-trg-scheduler.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-clock-icon lucide-clock"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg>

+ 1 - 0
studio/template/images/icons/agt-trg-webhook.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-webhook-icon lucide-webhook"><path d="M18 16.98h-5.99c-1.1 0-1.95.94-2.48 1.9A4 4 0 0 1 2 17c.01-.7.2-1.4.57-2"/><path d="m6 17 3.13-5.78c.53-.97.1-2.18-.5-3.1a4 4 0 1 1 6.89-4.06"/><path d="m12 6 3.13 5.73C15.66 12.7 16.9 13 18 13a4 4 0 0 1 0 8"/></svg>

+ 1 - 1
studio/template/images/icons/mi-agt-settings.svg

@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-brain-cog"><path d="M12 5a3 3 0 1 0-5.997.142 4 4 0 0 0-2.526 5.77 4 4 0 0 0 .556 6.588 4 4 0 0 0 7.636 2.106 3.2 3.2 0 0 0 .164-.546c.028-.13.306-.13.335 0a3.2 3.2 0 0 0 .163.546 4 4 0 0 0 7.636-2.106 4 4 0 0 0 .556-6.588 4 4 0 0 0-2.526-5.77A3 3 0 1 0 12 5"/><path d="M17.599 6.5a3 3 0 0 0 .399-1.375"/><path d="M6.003 5.125A3 3 0 0 0 6.401 6.5"/><path d="M3.477 10.896a4 4 0 0 1 .585-.396"/><path d="M19.938 10.5a4 4 0 0 1 .585.396"/><path d="M6 18a4 4 0 0 1-1.967-.516"/><path d="M19.967 17.484A4 4 0 0 1 18 18"/><circle cx="12" cy="12" r="3"/><path d="m15.7 10.4-.9.4"/><path d="m9.2 13.2-.9.4"/><path d="m13.6 15.7-.4-.9"/><path d="m10.8 9.2-.4-.9"/><path d="m15.7 13.5-.9-.4"/><path d="m9.2 10.9-.9-.4"/><path d="m10.5 15.7.4-.9"/><path d="m13.1 9.2.4-.9"/></svg>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-settings-icon lucide-settings"><path d="M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915"/><circle cx="12" cy="12" r="3"/></svg>

+ 1 - 0
studio/template/images/icons/mi-agt-tools.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-wrench-icon lucide-wrench"><path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.106-3.105c.32-.322.863-.22.983.218a6 6 0 0 1-8.259 7.057l-7.91 7.91a1 1 0 0 1-2.999-3l7.91-7.91a6 6 0 0 1 7.057-8.259c.438.12.54.662.219.984z"/></svg>

+ 1 - 0
studio/template/images/icons/mi-agt-vector-store.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-book-open-icon lucide-book-open"><path d="M12 7v14"/><path d="M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z"/></svg>

+ 1 - 0
studio/template/images/icons/ui-layout-grid.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-layout-grid-icon lucide-layout-grid"><rect width="7" height="7" x="3" y="3" rx="1"/><rect width="7" height="7" x="14" y="3" rx="1"/><rect width="7" height="7" x="14" y="14" rx="1"/><rect width="7" height="7" x="3" y="14" rx="1"/></svg>

+ 1 - 0
studio/template/images/icons/ui-list.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-list-icon lucide-list"><path d="M3 5h.01"/><path d="M3 12h.01"/><path d="M3 19h.01"/><path d="M8 5h13"/><path d="M8 12h13"/><path d="M8 19h13"/></svg>

+ 138 - 6
studio/template/scripts/BxBaseStudioAgents.php

@@ -15,6 +15,8 @@ class BxBaseStudioAgents extends BxDolStudioAgents
     protected $aMenuItems;
     protected $aGridObjects;
 
+    protected $sSessionKeyAgentsView;
+
     public function __construct($sPage = '')
     {
         parent::__construct($sPage);
@@ -32,11 +34,11 @@ class BxBaseStudioAgents extends BxDolStudioAgents
         ];
 
         $this->aMenuItems = [
-            BX_DOL_STUDIO_AGENTS_TYPE_SETTINGS => ['icon' => 'mi-agt-settings.svg'],
-            BX_DOL_STUDIO_AGENTS_TYPE_AI_PROVIDERS => ['icon' => 'mi-agt-providers.svg'],
-            BX_DOL_STUDIO_AGENTS_TYPE_TOOLS => ['icon' => 'mi-agt-helpers.svg'],
-            BX_DOL_STUDIO_AGENTS_TYPE_VECTOR_STORE => ['icon' => 'mi-agt-helpers.svg'],
             BX_DOL_STUDIO_AGENTS_TYPE_AGENTS => ['icon' => 'mi-agt-assistants.svg'],
+            BX_DOL_STUDIO_AGENTS_TYPE_AI_PROVIDERS => ['icon' => 'mi-agt-providers.svg'],
+            BX_DOL_STUDIO_AGENTS_TYPE_TOOLS => ['icon' => 'mi-agt-tools.svg'],
+            BX_DOL_STUDIO_AGENTS_TYPE_VECTOR_STORE => ['icon' => 'mi-agt-vector-store.svg'],
+            BX_DOL_STUDIO_AGENTS_TYPE_SETTINGS => ['icon' => 'mi-agt-settings.svg'],
 
             /*
              * Hidden for now. Most probably they will be removed.
@@ -56,6 +58,7 @@ class BxBaseStudioAgents extends BxDolStudioAgents
             BX_DOL_STUDIO_AGENTS_TYPE_ASSISTANTS . '_chats' => 'sys_studio_agents_assistants_chats',
             BX_DOL_STUDIO_AGENTS_TYPE_ASSISTANTS . '_files' => 'sys_studio_agents_assistants_files',
             BX_DOL_STUDIO_AGENTS_TYPE_AGENTS => 'sys_studio_agents_agents',
+
             /*
              * Hidden for now. Most probably they will be removed.
              * 
@@ -65,6 +68,8 @@ class BxBaseStudioAgents extends BxDolStudioAgents
              * 
              */
         ];
+
+        $this->sSessionKeyAgentsView = 'bx_std_agents_view';
     }
 
     public function getPageJsCode($aOptions = [], $bWrap = true)
@@ -107,7 +112,7 @@ class BxBaseStudioAgents extends BxDolStudioAgents
 
         return $oOptions->getCode();
     }
-    
+
     protected function getAiProviders()
     {
         $this->aPageJsOptions = array_merge($this->aPageJsOptions, [
@@ -119,7 +124,7 @@ class BxBaseStudioAgents extends BxDolStudioAgents
 
         return $this->getGrid($this->aGridObjects[BX_DOL_STUDIO_AGENTS_TYPE_AI_PROVIDERS]);
     }
-    
+
     protected function getTools()
     {
         $this->aPageJsOptions['sPageUrl'] .= 'tools';
@@ -225,7 +230,134 @@ class BxBaseStudioAgents extends BxDolStudioAgents
         return $this->getGrid($this->aGridObjects[BX_DOL_STUDIO_AGENTS_TYPE_ASSISTANTS]);
     }
 
+    protected function _setView($sView)
+    {
+        return BxDolSession::getInstance()->setValue($this->{'sSessionKey' . ucfirst($this->sPage) . 'View'}, $sView);
+    }
+
+    protected function _getView()
+    {
+        return BxDolSession::getInstance()->getValue($this->{'sSessionKey' . ucfirst($this->sPage) . 'View'});
+    }
+
     protected function getAgents()
+    {
+        $aTs = ['list' => 'grid', 'grid' => 'list'];
+        $aT2i = ['list' => 'ui-list.svg', 'grid' => 'ui-layout-grid.svg'];
+
+        $sType = 'list';
+        if(($sTypeGt = bx_get('view')) !== false && in_array($sTypeGt, $aTs)) {
+            $sType = $sTypeGt;
+            $this->_setView($sTypeGt);
+        }
+        else if(($sTypeSn = $this->_getView()) && in_array($sTypeSn, $aTs))
+            $sType = $sTypeSn;
+
+        $sTypeNew = $aTs[$sType];
+
+        return [
+            'type' => BX_DB_DEF,
+            'caption' => '',
+            'actions' => [[
+                'name' => $sTypeNew,
+                'caption' => _t('_sys_agents_builder_view_' . $sTypeNew),
+                'title_only' => true,
+                'url' => $this->sSubpageUrl . $this->sPage . '&view=' . $sTypeNew,
+                'icon' => $aT2i[$sTypeNew]
+            ]],
+            'content' => ($sMethod = 'getAgents' . bx_gen_method_name($sType)) && method_exists($this, $sMethod) ? $this->$sMethod() : ''
+        ];
+    }
+
+    protected function getAgentsList()
+    {
+        $sJsObject = $this->getPageJsObject();
+        $oTemplate = BxDolStudioTemplate::getInstance();
+
+        $oAi = BxDolAI::getInstance();
+        $aAgents = $oAi->getAgentsBy(['sample' => 'all']);
+
+        $oForm = new BxTemplFormView([]);
+        $aInput = [
+            'type' => 'switcher',
+            'name' => 'tabs',
+            'caption' => '',
+            'info' => '',
+            'value' => '1',
+            'checked' => '',
+            'attrs' => [
+                'onchange' => $sJsObject . '.agentActivate(this)'
+            ],
+            'db' => []
+        ];
+        
+        $aTmplVarsAgents = [];
+        foreach($aAgents as $aAgent) {
+
+            $sIcon = '';
+            if(($sIcon = $aAgent['icon'])) {
+                list($sIcon, $sIconUrl, $sIconA, $sIconHtml) = $oTemplate->getTemplateFunctions()->getIcon($sIcon);
+
+                if($sIcon)
+                    $sIcon = $oTemplate->parseIcon(BxDolIconset::getObjectInstance()->getIcon($sIcon));
+                else if($sIconHtml)
+                    $sIcon = $sIconHtml;
+            }
+            
+            $aTmplVarsTrigger = [];
+            if(($sTrigger = $aAgent['trigger']))
+                $aTmplVarsTrigger = [
+                    'trigger_title' => bx_html_attribute(_t('_sys_agents_field_trigger_' . str_replace(['-', ' '], '_', $sTrigger))),
+                    'trigger_icon_src' => $oTemplate->getIconUrl('agt-trg-' . $sTrigger . '.svg')
+                ];
+
+            $aTmplVarsModel = [];
+            if(($iModelId = (int)$aAgent['model_id'])) {
+                $aModel = $this->oDbAi->getModelsBy(['sample' => 'id', 'id' => $iModelId]);
+                if(($sModelTitle = $aModel['title'] ?? false))
+                    $aTmplVarsModel['model_title'] = bx_html_attribute($sModelTitle);
+                if(($sModelIcon = $aModel['icon'] ?? false))
+                    $aTmplVarsModel['model_icon_src'] = $oTemplate->getIconUrl($sModelIcon);
+            }
+
+            $sProfile = '';
+            if(($iProfileId = (int)$aAgent['profile_id']) && ($oProfile = BxDolProfile::getInstance($iProfileId)) !== false)
+                $sProfile = $oProfile->getUnit(0, ['template' => 'unit_wo_info']);
+
+            $aInput['checked'] = (int)$aAgent['active'] != 0;
+
+            $aTmplVarsAgents[] = [
+                'id' => $aAgent['id'],
+                'icon' => $sIcon,
+                'bx_if:show_trigger' => [
+                    'condition' => !empty($aTmplVarsTrigger),
+                    'content' => $aTmplVarsTrigger
+                ],
+                'bx_if:show_model' => [
+                    'condition' => !empty($aTmplVarsModel),
+                    'content' => $aTmplVarsModel
+                ],
+                'bx_if:show_profile' => [
+                    'condition' => (bool)$sProfile,
+                    'content' => [
+                        'unit' => $sProfile
+                    ]
+                ],
+                'title' => $aAgent['title'],
+                'switcher' => $oForm->genInput($aInput),
+                'description' => bx_process_output($aAgent['description'])
+            ];
+        }
+
+        return $oTemplate->parseHtmlByName('agents.html', [
+            'content' => $oTemplate->parseHtmlByName('agents_agents.html', [
+                'bx_repeat:agents' => $aTmplVarsAgents,
+            ]),
+            'js_content' => $this->getPageJsCode()
+        ]);
+    }
+
+    protected function getAgentsGrid()
     {
         return $this->getGrid($this->aGridObjects[BX_DOL_STUDIO_AGENTS_TYPE_AGENTS]);
     }

+ 57 - 8
studio/template/scripts/BxBaseStudioAgentsAgents.php

@@ -290,6 +290,8 @@ class BxBaseStudioAgentsAgents extends BxDolStudioAgentsAgents
 
     protected function _getForm($sAction, $aAgent = [])
     {
+        $sJsObject = $this->getPageJsObject();
+
         $aForm = array(
             'form_attrs' => array(
                 'id' => 'bx_std_agents_' . $sAction,
@@ -304,6 +306,21 @@ class BxBaseStudioAgentsAgents extends BxDolStudioAgentsAgents
                 ),
             ),
             'inputs' => array(
+                'title' => [
+                    'type' => 'text',
+                    'name' => 'title',
+                    'caption' => _t('_sys_agents_field_title'),
+                    'info' => _t('_sys_agents_field_title_info'),
+                    'value' => $aAgent['title'] ?? '',
+                    'required' => '1',
+                    'checker' => [
+                        'func' => 'Avail',
+                        'error' => _t('_sys_agents_form_field_err_enter'),
+                    ],
+                    'db' => [
+                        'pass' => 'Xss',
+                    ],
+                ],
                 'name' => [
                     'type' => 'text',
                     'name' => 'name',
@@ -319,6 +336,26 @@ class BxBaseStudioAgentsAgents extends BxDolStudioAgentsAgents
                         'pass' => 'Xss',
                     ],
                 ],
+                'description' => [
+                    'type' => 'textarea',
+                    'name' => 'description',
+                    'caption' => _t('_sys_agents_field_description'),
+                    'info' => _t('_sys_agents_field_description_info'),
+                    'value' => $aAgent['description'] ?? '',
+                    'db' => [
+                        'pass' => 'Xss',
+                    ],
+                ],
+                'icon' => [
+                    'type' => 'textarea',
+                    'name' => 'icon',
+                    'caption' => _t('_sys_agents_field_icon'),
+                    'info' => _t('_sys_agents_field_icon_info'),
+                    'value' => $aAgent['icon'] ?? '',
+                    'db' => [
+                        'pass' => 'Xss',
+                    ],
+                ],
                 'model_id' => [
                     'type' => 'select',
                     'name' => 'model_id',
@@ -359,13 +396,13 @@ class BxBaseStudioAgentsAgents extends BxDolStudioAgentsAgents
                     'info' => _t('_sys_agents_field_trigger_info'),
                     'value' => isset($aAgent['trigger']) ? $aAgent['trigger'] : 0,
                     'values' => [
-                        'alert' => 'alert',
-                        'scheduler' => 'scheduler',
-                        'webhook' => 'webhook',
-                        'manual' => 'manual',
-                        'agent' => 'agent',
-                        'message' => 'message',
-                        'form-input' => 'form input',
+                        'alert' => _t('_sys_agents_field_trigger_alert'),
+                        'scheduler' => _t('_sys_agents_field_trigger_scheduler'),
+                        'webhook' => _t('_sys_agents_field_trigger_webhook'),
+                        'manual' => _t('_sys_agents_field_trigger_manual'),
+                        'agent' => _t('_sys_agents_field_trigger_agent'),
+                        'message' => _t('_sys_agents_field_trigger_message'),
+                        'form-input' => _t('_sys_agents_field_trigger_form_input'),
                     ],
                     // 'attrs' => [
                     //    'onchange' => $this->getPageJsObject() . '.onChangeAgentTrigger(this)',
@@ -612,7 +649,19 @@ class BxBaseStudioAgentsAgents extends BxDolStudioAgentsAgents
 
             ),
         );
-        
+
+        if(($sFldTitle = 'title') && ($sFldName = 'name') && isset($aForm['inputs'][$sFldTitle], $aForm['inputs'][$sFldName])) {
+            $aMask = array('mask' => "javascript:%s.agentCheckName(this, '%s', '%s');", $sJsObject, 'title', 'name');
+            if($sAction == 'edit' && ($iAgentId = $aAgent['id'] ?? false)) {
+                $aMask['mask'] = "javascript:%s.agentCheckName(this, '%s', '%s', %d);";
+                $aMask[] = (int)$iAgentId;
+            }
+
+            $sOnBlur = call_user_func_array('sprintf', array_values($aMask));
+            $aForm['inputs'][$sFldTitle]['attrs']['onblur'] = $sOnBlur;
+            $aForm['inputs'][$sFldName]['attrs']['onblur'] = $sOnBlur;
+        }
+
         $this->_getMultiField('tools', $aAgent, 'getTools', 'toolAdd', 'agents_agents_form_tools.html', $aForm);
 
         return $aForm;