Просмотр исходного кода

Merge branch 'master' of https://github.com/unacms/UNA

AntonLV 3 месяцев назад
Родитель
Сommit
206ed2e3f0

+ 7 - 2
inc/classes/BxDolAI.php

@@ -392,7 +392,7 @@ class BxDolAI extends BxDolFactory implements iBxDolSingleton
 
 
         // set additional params
         // set additional params
         $aParams = [];
         $aParams = [];
-        if ('message' == $sType) {
+        if ('message' == $sType || 'form-input' == $sType) {
             $aParams = ['chat_history_subindex' => $mixedParams['sender_profile_id']];
             $aParams = ['chat_history_subindex' => $mixedParams['sender_profile_id']];
         }
         }
 
 
@@ -436,7 +436,7 @@ class BxDolAI extends BxDolFactory implements iBxDolSingleton
         $aAgents = [];
         $aAgents = [];
         $a = $this->_oDb->getAgentsWithAlert();
         $a = $this->_oDb->getAgentsWithAlert();
         foreach ($a as $r) {
         foreach ($a as $r) {
-            $aAlert = explode(':', $r['alert']);
+            $aAlert = explode(':', $r['alert']); // TODO: remake to concantenate $sUnit and $sAction and then compare
             if (count($aAlert) == 2 && $aAlert[0] == $sUnit && $aAlert[1] == $sAction)
             if (count($aAlert) == 2 && $aAlert[0] == $sUnit && $aAlert[1] == $sAction)
                 $aAgents[] = $r;
                 $aAgents[] = $r;
         }
         }
@@ -449,6 +449,11 @@ class BxDolAI extends BxDolFactory implements iBxDolSingleton
         return $this->_oDb->getAgentsByProfileId($iProfileId);
         return $this->_oDb->getAgentsByProfileId($iProfileId);
     }
     }
     
     
+    public function getAgentsByFormObject($sFormObject)
+    {
+        return $this->_oDb->getAgentsByFormObject($sFormObject);
+    }
+
     public function getAgentsByTriggerType($sTrigger)
     public function getAgentsByTriggerType($sTrigger)
     {
     {
         return $this->_oDb->getAgentsByTriggerType($sTrigger);
         return $this->_oDb->getAgentsByTriggerType($sTrigger);

+ 32 - 0
inc/classes/BxDolAIQuery.php

@@ -901,6 +901,11 @@ class BxDolAIQuery extends BxDolDb
         return $this->getAll("SELECT * FROM `sys_agents_agents` WHERE `trigger` = 'message' AND `profile_id` = :profile AND `active` = :active", ['profile' => $iProfileId, 'active' => $bActiveOnly ? 1 : 0]);
         return $this->getAll("SELECT * FROM `sys_agents_agents` WHERE `trigger` = 'message' AND `profile_id` = :profile AND `active` = :active", ['profile' => $iProfileId, 'active' => $bActiveOnly ? 1 : 0]);
     }
     }
 
 
+    public function getAgentsByFormObject($sFormObject, $bActiveOnly = true)
+    {
+        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 getAgentByTriggerWebhookKey($sKey, $bActiveOnly = true)
     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]);
         return $this->getRow("SELECT * FROM `sys_agents_agents` WHERE `trigger` = 'scheduler' AND `webhook_key` = :key AND `active` = :active", ['key' => $sKey, 'active' => $bActiveOnly ? 1 : 0]);
@@ -975,6 +980,33 @@ class BxDolAIQuery extends BxDolDb
         return $aValues;
         return $aValues;
     }
     }
 
 
+    public function getFormDisplay($sObject)
+    {
+        $aDisplays = $this->getColumn("SELECT `display_name` FROM `sys_form_displays` WHERE `object` = :object", ['object' => $sObject]);
+        return $aDisplays ? current($aDisplays) : null;
+    }
+
+    public function getFormObjects()
+    {
+        $aValues = [];
+        $aForms = $this->getAll("SELECT `f`.`object`, `f`.`title`, `f`.`module`, `m`.`title` AS `module_title` FROM `sys_objects_form` AS f INNER JOIN `sys_modules` as `m` ON `m`.`name` = `f`.`module` ORDER BY `f`.`module`, `f`.`object` ASC");
+        foreach ($aForms as $r) {
+            $sDisplay = $this->getFormDisplay($r['object']);
+            if (!$sDisplay) 
+                continue;
+            $oForm = BxDolForm::getObjectInstance($r['object'], $sDisplay);
+            $sFormId = $oForm->getId();
+            $aValues[$r['object']] = [
+                'form_id' => $sFormId,
+                'form_object' => $r['object'],
+                'module' => $r['module'],
+                'module_title' => $r['module_title'],
+                'form_title' => _t($r['title']),
+            ];
+        }
+        return $aValues;
+    }
+
     static public function getAlertDesc($sAlert) 
     static public function getAlertDesc($sAlert) 
     {
     {
         if (!$sAlert)
         if (!$sAlert)

+ 5 - 2
install/sql/system.sql

@@ -6776,7 +6776,8 @@ CREATE TABLE IF NOT EXISTS `sys_rewrite_rules` (
 
 
 INSERT INTO `sys_rewrite_rules` (`preg`, `service`, `active`) VALUES
 INSERT INTO `sys_rewrite_rules` (`preg`, `service`, `active`) VALUES
 ('^sys-action/(.*)$', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:11:"wiki_action";s:6:"params";a:2:{i:0;s:3:"sys";i:1;s:3:"{1}";}s:5:"class";s:16:"TemplServiceWiki";}', '1'),
 ('^sys-action/(.*)$', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:11:"wiki_action";s:6:"params";a:2:{i:0;s:3:"sys";i:1;s:3:"{1}";}s:5:"class";s:16:"TemplServiceWiki";}', '1'),
-('^home/?$', 'a:3:{s:6:\"module\";s:6:\"system\";s:6:\"method\";s:13:\"home_redirect\";s:6:\"params\";a:0:{}}', 1);
+('^home/?$', 'a:3:{s:6:\"module\";s:6:\"system\";s:6:\"method\";s:13:\"home_redirect\";s:6:\"params\";a:0:{}}', 1),
+('^sys-agent-form-input/(.*)$', 'a:4:{s:6:\"module\";s:6:\"system\";s:6:\"method\";s:25:\"call_agent_for_form_input\";s:6:\"params\";a:1:{i:0;s:3:\"{1}\";}s:5:\"class\";s:13:\"TemplServices\";}', 1);
 
 
 -- --------------------------------------------------------
 -- --------------------------------------------------------
 
 
@@ -7193,12 +7194,14 @@ CREATE TABLE `sys_agents_agents` (
   `tools_max_run` int(11) NOT NULL DEFAULT 10,
   `tools_max_run` int(11) NOT NULL DEFAULT 10,
   `chat_history_context` int(11) NOT NULL DEFAULT 50000,
   `chat_history_context` int(11) NOT NULL DEFAULT 50000,
   `vector_store_id` int(11) NOT NULL,
   `vector_store_id` int(11) NOT NULL,
-  `trigger` enum('alert','scheduler','webhook','manual','agent','message') NOT NULL DEFAULT 'message',
+  `trigger` enum('alert','scheduler','webhook','manual','agent','message','form-input') NOT NULL DEFAULT 'message',
   `async` tinyint(4) NOT NULL DEFAULT 0,
   `async` tinyint(4) NOT NULL DEFAULT 0,
   `alert` varchar(192) NOT NULL DEFAULT '',
   `alert` varchar(192) NOT NULL DEFAULT '',
   `scheduler_cron` varchar(64) NOT NULL,
   `scheduler_cron` varchar(64) NOT NULL,
   `webhook_key` varchar(255) NOT NULL,
   `webhook_key` varchar(255) NOT NULL,
   `webhook_sample` text NOT NULL,
   `webhook_sample` text NOT NULL,
+  `form_object` varchar(128) NOT NULL,
+  `form_input` varchar(128) NOT NULL,
   `agent_sample` text NOT NULL,
   `agent_sample` text NOT NULL,
   `message_profile_id` int(11) NOT NULL,
   `message_profile_id` int(11) NOT NULL,
   `added` int(11) UNSIGNED NOT NULL DEFAULT 0,
   `added` int(11) UNSIGNED NOT NULL DEFAULT 0,

+ 5 - 1
modules/boonex/english/data/langs/system/en.xml

@@ -2269,6 +2269,10 @@
     <string name="_sys_agents_form_field_err_enter"><![CDATA[This field is essential. Please enter something here.]]></string>
     <string name="_sys_agents_form_field_err_enter"><![CDATA[This field is essential. Please enter something here.]]></string>
     <string name="_sys_agents_form_field_err_select"><![CDATA[This field is essential. Please select something here.]]></string>
     <string name="_sys_agents_form_field_err_select"><![CDATA[This field is essential. Please select something here.]]></string>
     <string name="_sys_agents_form_field_err_profile_has_agent"><![CDATA[This profile is already used in another agent({0}) with the same 'message' trigger.]]></string>
     <string name="_sys_agents_form_field_err_profile_has_agent"><![CDATA[This profile is already used in another agent({0}) with the same 'message' trigger.]]></string>
+    <string name="_sys_agents_form_object"><![CDATA[Form object]]></string>
+    <string name="_sys_agents_form_object_info"><![CDATA[Form object that contains the required field, for custom forms enter form id here]]></string>
+    <string name="_sys_agents_form_input"><![CDATA[Form input]]></string>
+    <string name="_sys_agents_form_input_info"><![CDATA[Form input where AI-generated text should be pasted]]></string>
     <string name="_sys_agents_json_field_err"><![CDATA[Invalid JSON format.]]></string>
     <string name="_sys_agents_json_field_err"><![CDATA[Invalid JSON format.]]></string>
     <string name="_sys_agents_automators_txt_active"><![CDATA[Active]]></string>
     <string name="_sys_agents_automators_txt_active"><![CDATA[Active]]></string>
     <string name="_sys_agents_automators_txt_name"><![CDATA[Name]]></string>
     <string name="_sys_agents_automators_txt_name"><![CDATA[Name]]></string>
@@ -2313,7 +2317,7 @@
     <string name="_sys_agents_automators_field_type_scheduler"><![CDATA[Scheduler]]></string>
     <string name="_sys_agents_automators_field_type_scheduler"><![CDATA[Scheduler]]></string>
     <string name="_sys_agents_automators_field_type_webhook"><![CDATA[Webhook]]></string>
     <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"><![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.]]></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_alert_sample"><![CDATA[Alert: payload]]></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_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>
     <string name="_sys_agents_waiting_for_sample_data_webhook"><![CDATA[Trigger webhook to see its payload.]]></string>

+ 4 - 0
modules/boonex/russian/data/langs/system/ru.xml

@@ -2244,6 +2244,10 @@
         <string name="_sys_agents_form_field_err_enter"><![CDATA[Это поле имеет важное значение. Пожалуйста, напишите что-нибудь здесь.]]></string>
         <string name="_sys_agents_form_field_err_enter"><![CDATA[Это поле имеет важное значение. Пожалуйста, напишите что-нибудь здесь.]]></string>
         <string name="_sys_agents_form_field_err_select"><![CDATA[Это поле имеет важное значение. Пожалуйста, выберите что-нибудь здесь.]]></string>
         <string name="_sys_agents_form_field_err_select"><![CDATA[Это поле имеет важное значение. Пожалуйста, выберите что-нибудь здесь.]]></string>
         <string name="_sys_agents_form_field_err_profile_has_agent"><![CDATA[Этот профиль уже используется в другом агенте({0}) с тем же триггером 'сообщение'.]]></string>
         <string name="_sys_agents_form_field_err_profile_has_agent"><![CDATA[Этот профиль уже используется в другом агенте({0}) с тем же триггером 'сообщение'.]]></string>
+        <string name="_sys_agents_form_object"><![CDATA[Объект формы]]></string>
+        <string name="_sys_agents_form_object_info"><![CDATA[Объект формы, содержащий необходимое поле]]></string>
+        <string name="_sys_agents_form_input"><![CDATA[Поле формы]]></string>
+        <string name="_sys_agents_form_input_info"><![CDATA[Поле формы, в которое нужно вставить текст, сгенерированный ИИ]]></string>
         <string name="_sys_agents_json_field_err"><![CDATA[Неверный формат JSON.]]></string>
         <string name="_sys_agents_json_field_err"><![CDATA[Неверный формат JSON.]]></string>
         <string name="_sys_agents_automators_txt_active"><![CDATA[Активный]]></string>
         <string name="_sys_agents_automators_txt_active"><![CDATA[Активный]]></string>
         <string name="_sys_agents_automators_txt_name"><![CDATA[Название]]></string>
         <string name="_sys_agents_automators_txt_name"><![CDATA[Название]]></string>

+ 1 - 1
package.json

@@ -5,7 +5,7 @@
     "@claviska/jquery-minicolors": "^2.3.6",
     "@claviska/jquery-minicolors": "^2.3.6",
     "@egjs/hammerjs": "^2.0.17",
     "@egjs/hammerjs": "^2.0.17",
     "@fullcalendar/core": "^6.1.20",
     "@fullcalendar/core": "^6.1.20",
-    "@stripe/connect-js": "^3.4.5",
+    "@stripe/connect-js": "^3.4.6",
     "at.js": "^1.5.4",
     "at.js": "^1.5.4",
     "autosize": "^6.0.1",
     "autosize": "^6.0.1",
     "chart.js": "^4.5.1",
     "chart.js": "^4.5.1",

+ 35 - 0
studio/template/agents_agents_form_input_select.html

@@ -0,0 +1,35 @@
+<div id="bx-agents-agents-form-input-cont" style="overflow:visible;">
+    <select id="bx-agents-agents-form-input" name="form_input" class="bx-def-font-inputs bx-form-input-select">
+        <bx_repeat:form_inputs>
+            <option value="__value__" <bx_if:sel>__sel__</bx_if:sel> data-title="__title_attr__" data-form_input="__value__">__title__</option>
+        </bx_repeat:form_inputs>
+    </select>
+    </div>
+    <script>        
+        $('#bx-agents-agents-form-input').select2({
+            templateResult: (state) => {
+                return $(`
+                    <div class="bx-form-input-wrap">
+                    <div>
+                        <div class="bx-form-input-data">${state.text || state.id}</div>
+                    </div>
+                    </div>
+                `);
+            },
+            templateSelection: d => d.text,
+            tags: true, // allow custom inputs
+            createTag: function (params) {            
+                const term = $.trim(params.term);
+                if (!term) return null;
+                return {
+                    id: term,
+                    text: term,
+                    title: term,
+                    title_attr: term,
+                    value: term,
+                };
+            },
+            placeholder: "Select or type a value"
+        });    
+    
+    </script>

+ 51 - 0
studio/template/agents_agents_form_object_select.html

@@ -0,0 +1,51 @@
+<div id="bx-agents-agents-form-object-cont" style="overflow:visible;">
+<select id="bx-agents-agents-form-object" name="form_object" class="bx-def-font-inputs bx-form-input-select">
+    <bx_repeat:form_objects>
+        <option value="__value__" <bx_if:sel>__sel__</bx_if:sel>>__title__</option>
+    </bx_repeat:form_objects>
+</select>
+</div>
+<script>
+    $('#bx-agents-agents-form-object').select2({
+        templateResult: (state) => {
+            return $(`
+                <div class="bx-form-object-wrap">
+                    <div>
+                        <div class="bx-form-object-text">${state.text || state.id}</div>
+                    </div>
+                </div>
+            `);
+        },
+        templateSelection: d => d.text,
+        tags: true, // allow custom inputs
+        createTag: function (params) {            
+            const term = $.trim(params.term);
+            if (!term) return null;
+            return {
+                id: term,
+                text: term,
+                title: term,
+                value: term,
+            };
+        },
+        placeholder: "Select or type a value"
+    });
+
+    $('#bx-agents-agents-form-object').on('change', function () {
+        const value = $(this).val();
+        const sUrl = sUrlRoot + "grid.php?o=__grid_object__&a=get_form_inputs&csrf_token=" + window.glGrids.__grid_object__._sCsrfToken;
+        $.post(sUrl, {form_object: value}, function(oResult) {
+            if (typeof(oResult.code) !== 'undefined' && oResult.code == 200) {
+                const newData = oResult.form_inputs;
+                const select = $('#bx-agents-agents-form-input');
+                select.empty();
+                Object.values(newData).forEach(input => {
+                    select.append('<option value="' + input.name + '">' + input.name + (input.caption.length > 0 ? ' - ' + input.caption : '') + '</option>');
+                });
+                select.val(null).trigger('change');
+            }
+        }, 'json');
+    });
+
+
+</script>

+ 176 - 2
studio/template/scripts/BxBaseStudioAgentsAgents.php

@@ -37,6 +37,19 @@ class BxBaseStudioAgentsAgents extends BxDolStudioAgentsAgents
         ]);
         ]);
     }
     }
 
 
+    public function performActionGetFormInputs()
+    {
+        $aFormInputs = $this->_getFormInputs(bx_get('form_object'));
+        if (!$aFormInputs) {
+            echoJson(['code' => 404, 'msg' => _t('_sys_not_available')]);
+            return;
+        }
+        echoJson([
+            'code' => $aFormInputs ? 200 : 404,
+            'form_inputs' => $aFormInputs,
+        ]);
+    }
+
     public function performActionManual()
     public function performActionManual()
     {
     {
         $iId = $this->_getId();        
         $iId = $this->_getId();        
@@ -343,7 +356,7 @@ class BxBaseStudioAgentsAgents extends BxDolStudioAgentsAgents
                     'type' => 'select',
                     'type' => 'select',
                     'name' => 'trigger',
                     'name' => 'trigger',
                     'caption' => _t('_sys_agents_field_trigger'),
                     'caption' => _t('_sys_agents_field_trigger'),
-                    'info' => _t('_sys_agents_field_trigger_info'),                    
+                    'info' => _t('_sys_agents_field_trigger_info'),
                     'value' => isset($aAgent['trigger']) ? $aAgent['trigger'] : 0,
                     'value' => isset($aAgent['trigger']) ? $aAgent['trigger'] : 0,
                     'values' => [
                     'values' => [
                         'alert' => 'alert',
                         'alert' => 'alert',
@@ -352,6 +365,7 @@ class BxBaseStudioAgentsAgents extends BxDolStudioAgentsAgents
                         'manual' => 'manual',
                         'manual' => 'manual',
                         'agent' => 'agent',
                         'agent' => 'agent',
                         'message' => 'message',
                         'message' => 'message',
+                        'form-input' => 'form input',
                     ],
                     ],
                     'attrs' => [
                     'attrs' => [
                         'onchange' => $this->getPageJsObject() . '.onChangeAgentTrigger(this)',
                         'onchange' => $this->getPageJsObject() . '.onChangeAgentTrigger(this)',
@@ -466,7 +480,36 @@ class BxBaseStudioAgentsAgents extends BxDolStudioAgentsAgents
                     ],
                     ],
                 ],
                 ],
 
 
-                'message_section_end' => array(
+                'form_field_section' => array(
+                    'type' => 'block_header',
+                    'caption' => 'Trigger - form field',
+                    'collapsable' => true,
+                    'collapsed' => true,
+                ),
+
+                'form_object' => [
+                    'type' => 'custom',
+                    'name' => 'form_object',
+                    'caption' => _t('_sys_agents_form_object'),
+                    'info' => _t('_sys_agents_form_object_info'),
+                    'content' => $this->_oTemplate->parseHtmlByName('agents_agents_form_object_select.html', $this->_getFormObjectValues(isset($aAgent['form_object']) ? $aAgent['form_object'] : '')),
+                    'db' => [
+                        'pass' => 'Xss',
+                    ],
+                ],
+
+                'form_input' => [
+                    'type' => 'custom',
+                    'name' => 'form_input',
+                    'caption' => _t('_sys_agents_form_input'),
+                    'info' => _t('_sys_agents_form_input_info'),
+                    'content' => $this->_oTemplate->parseHtmlByName('agents_agents_form_input_select.html', $this->_getFormInputValues(isset($aAgent['form_object']) ? $aAgent['form_object'] : '', isset($aAgent['form_input']) ? $aAgent['form_input'] : '')),
+                    'db' => [
+                        'pass' => 'Xss',
+                    ],
+                ],
+
+                'form_field_section_end' => array(
                     'type' => 'block_end',
                     'type' => 'block_end',
                 ),
                 ),
 
 
@@ -626,6 +669,137 @@ class BxBaseStudioAgentsAgents extends BxDolStudioAgentsAgents
         return $a;
         return $a;
     }
     }
 
 
+    protected function _getFormObjectValues($sValue)
+    {
+        $aFormObjects = $this->_oDb->getFormObjects();
+
+        // add "Please select" option
+        $a = [
+            'sys_stat_not_available' => _t('_sys_not_available'),
+            'grid_object' => $this->_sObject,
+            'bx_repeat:form_objects' => [
+                [
+                    'title' => _t('_sys_please_select'), 
+                    'title_attr' => _t('_sys_please_select'), 
+                    'value' => '', 
+                    'bx_if:sel' => [
+                        'condition' => false,
+                        'content' => ['sel' => '']
+                    ]
+                ]
+            ]
+        ];
+
+        // add form objects
+        $bSelected = false;
+        foreach ($aFormObjects as $k => $r) {
+            if ($sValue == $r['form_object'])
+                $bSelected = true;
+            $a['bx_repeat:form_objects'][] = [
+                'title' => $r['module_title'] . ': ' . $r['form_title'],
+                'title_attr' => bx_html_attribute($r['module_title'] . ': ' . $r['form_title']),
+                'value' => $r['form_object'],
+                // 'form_id' => $r['form_id'],
+                // 'module' => $r['module'],
+                // 'module_title' => $r['module_title'],
+                // 'form_title' => $r['form_title'],
+                'bx_if:sel' => [
+                    'condition' => $sValue == $r['form_object'],
+                    'content' => ['sel' => $sValue == $r['form_object'] ? 'selected' : ''],
+                ]
+            ];
+        }
+
+        //  add selected form object if not found in form objects
+        if ($sValue && !$bSelected) {
+            $a['bx_repeat:form_objects'][] = [
+                'title' => $sValue,
+                'title_attr' => bx_html_attribute($sValue),
+                'value' => $sValue,
+                'bx_if:sel' => [
+                    'condition' => true,
+                    'content' => ['sel' => 'selected'],
+                ]
+            ];
+        }
+
+        return $a;
+    }
+
+    protected function _getFormInputs($sFormObject)
+    {
+        $sDisplay = $this->_oDb->getFormDisplay($sFormObject);
+        $oForm = $sDisplay ? BxDolForm::getObjectInstance($sFormObject, $sDisplay) : null;
+        $aFormInputs = $oForm ? $oForm->aInputs : [];
+        if (!$aFormInputs)
+            return [];
+        $aRet = [];
+        foreach ($aFormInputs as $k => $r) {
+            if ($r['type'] == 'text' || $r['type'] == 'textarea') {
+                $aRet[$r['name']] = [
+                    'name' => $r['name'],
+                    'caption' => $r['caption'],
+                ];
+            }
+        }
+        return $aRet;
+    }
+
+    protected function _getFormInputValues($sFormObject, $sFormInput)
+    {
+        $aFormInputs = $this->_getFormInputs($sFormObject);
+
+        // add "Please select" option
+        $a = [
+            'bx_repeat:form_inputs' => [
+                [
+                    'title' => _t('_sys_please_select'), 
+                    'title_attr' => _t('_sys_please_select'), 
+                    'value' => '', 
+                    'bx_if:sel' => [
+                        'condition' => false,
+                        'content' => ['sel' => '']
+                    ]
+                ]
+            ]
+        ];
+
+        // add form inputs
+        $bSelected = false;
+        if ($aFormInputs) {
+            foreach ($aFormInputs as $k => $r) {
+                if ($sFormInput == $r['name'])
+                    $bSelected = true;
+                $a['bx_repeat:form_inputs'][] = [
+                    'title' => $r['name'] . ' - ' . $r['caption'],
+                    'title_attr' => bx_html_attribute($r['name'] . (!empty($r['caption']) ? ' - ' . $r['caption'] : '')),
+                    'value' => $r['name'],
+                    'bx_if:sel' => [
+                        'condition' => $sFormInput == $r['name'],
+                        'content' => [
+                            'sel' => $sFormInput == $r['name'] ? 'selected' : '',
+                        ]
+                    ]
+                ];
+            }
+        }
+
+        //  add selected input if not found in form inputs
+        if ($sFormInput && !$bSelected) {
+            $a['bx_repeat:form_inputs'][] = [
+                'title' => $sFormInput,
+                'title_attr' => bx_html_attribute($sFormInput),
+                'value' => $sFormInput,
+                'bx_if:sel' => [
+                    'condition' => true,
+                    'content' => ['sel' => 'selected'],
+                ]
+            ];
+        }
+
+        return $a;
+    }
+
     protected function _getUniqName($sName)
     protected function _getUniqName($sName)
     {
     {
         return uriGenerate($sName, 'sys_agents_automators', 'name', ['lowercase' => false]);
         return uriGenerate($sName, 'sys_agents_automators', 'name', ['lowercase' => false]);

+ 34 - 0
template/form_field_textarea.html

@@ -6,4 +6,38 @@
         </div>
         </div>
     </div>
     </div>
 </bx_if:show_switcher>
 </bx_if:show_switcher>
+<bx_if:show_agent>
+    <div class="bx-form-input-agent-button __name__ relative">
+        <a class="flex absolute -top-7 right-0 space-x-2" href="#"><i class="sys-icon magic"></i></a>
+    </div>
+    <script>
+        $(document).ready(function() {
+            $('.bx-form-input-agent-button.__name__ a').click(function() {
+                bx_prompt("Prompt:", '', (o) => {
+                    if(o.getValue()) {
+                        $('.bx-form-input-agent-button.__name__ .sys-icon').removeClass('magic').addClass('sync animate-spin');
+                        $.ajax({
+                            url: sUrlRoot + 'r.php?_q=sys-agent-form-input/__agent_id__',
+                            type: 'POST',
+                            contentType: 'application/json',
+                            dataType: 'json',        // Expect JSON response
+                            data: JSON.stringify({
+                                prompt: o.getValue(),
+                                input_name: '__name__',
+                                values: Object.fromEntries(new FormData($('#__form_id__')[0]))
+                            }),
+                            success: function(data) {
+                                $('.bx-form-input-agent-button.__name__ .sys-icon').addClass('magic').removeClass('sync animate-spin');
+                                $('textarea[name="__name__"]').val(data.msg);
+                            }
+                        });
+
+                        
+                    }
+                });
+                return false;
+            });
+        });
+    </script>
+</bx_if:show_agent>
 <textarea __attrs__>__value__</textarea>
 <textarea __attrs__>__value__</textarea>

+ 26 - 0
template/scripts/BxBaseFormView.php

@@ -101,6 +101,9 @@ class BxBaseFormView extends BxDolForm
     protected $_sJsObjectName;
     protected $_sJsObjectName;
     
     
     protected $_aHtmlIds;
     protected $_aHtmlIds;
+
+    protected $_aAgentsFormObject;
+    protected $_sAgentFormObject;
     
     
     /**
     /**
      * Constructor
      * Constructor
@@ -132,6 +135,8 @@ class BxBaseFormView extends BxDolForm
             $sName = $aInfo['params']['object'];
             $sName = $aInfo['params']['object'];
         if(empty($sName) && !empty($aInfo['form_attrs']['id']))
         if(empty($sName) && !empty($aInfo['form_attrs']['id']))
             $sName = $aInfo['form_attrs']['id'];
             $sName = $aInfo['form_attrs']['id'];
+        if(empty($sName) && !empty($aInfo['form_attrs']['name']))
+            $sName = $aInfo['form_attrs']['name'];
 
 
         $this->_sJsObjectName = 'oForm' . bx_gen_method_name($sName, array('_' , '-'));
         $this->_sJsObjectName = 'oForm' . bx_gen_method_name($sName, array('_' , '-'));
 
 
@@ -142,6 +147,9 @@ class BxBaseFormView extends BxDolForm
             'pgc_popup' => $sHtmlId . '-pgc-popup-',
             'pgc_popup' => $sHtmlId . '-pgc-popup-',
             'pgc_form' => $sHtmlId . '-pgc-form-',
             'pgc_form' => $sHtmlId . '-pgc-form-',
         );
         );
+
+        $this->_sAgentFormObject = $aInfo['params']['object'] ?? $this->id;
+        $this->_aAgentsFormObject = BxDolAI::getInstance()->getAgentsByFormObject($this->_sAgentFormObject);
     }
     }
 
 
     public function performActionGetHelp()
     public function performActionGetHelp()
@@ -1663,12 +1671,30 @@ BLAH;
 
 
         $sValue = isset($aInput['value']) ? bx_process_output($bHtml || $bCode ? $aInput['value'] : strip_tags($aInput['value']), BX_DATA_TEXT, ['no_process_macros']) : '';
         $sValue = isset($aInput['value']) ? bx_process_output($bHtml || $bCode ? $aInput['value'] : strip_tags($aInput['value']), BX_DATA_TEXT, ['no_process_macros']) : '';
 
 
+        $aAgent = [];
+        if(!empty($this->_aAgentsFormObject)) {
+            foreach($this->_aAgentsFormObject as $a) {
+                if($a['form_object'] == $this->_sAgentFormObject && $a['form_input'] == $aInput['name']) {
+                    $aAgent = $a;
+                    break;
+                }
+            }
+        }
+
         return $this->oTemplate->parseHtmlByName('form_field_textarea.html', [
         return $this->oTemplate->parseHtmlByName('form_field_textarea.html', [
             'attrs' => bx_convert_array2attrs($aAttrs, $sClassAdd),
             'attrs' => bx_convert_array2attrs($aAttrs, $sClassAdd),
             'value' => $sValue,
             'value' => $sValue,
             'bx_if:show_switcher' => [
             'bx_if:show_switcher' => [
                 'condition' => !empty($aTmplVarsSwitcher),
                 'condition' => !empty($aTmplVarsSwitcher),
                 'content' => $aTmplVarsSwitcher
                 'content' => $aTmplVarsSwitcher
+            ],
+            'bx_if:show_agent' => [
+                'condition' => !empty($aAgent),
+                'content' => [
+                    'name' => $aInput['name'],
+                    'agent_id' => $aAgent['id'] ?? 0,
+                    'form_id' => $this->getId(),
+                ]
             ]
             ]
         ]);
         ]);
     }
     }

+ 32 - 0
template/scripts/BxBaseServices.php

@@ -1753,6 +1753,38 @@ class BxBaseServices extends BxDol implements iBxDolProfileService
         return $oAi->callAgent($sType, $aAgent, $aParams);
         return $oAi->callAgent($sType, $aAgent, $aParams);
     }
     }
 
 
+    public function serviceCallAgentForFormInput($iAgentId)
+    {
+        if (!bx_get_logged_profile_id())
+            return echoJson(['code' => 403, 'msg' => _t('_sys_agents_unauthorized')]);
+
+        $sJson = file_get_contents('php://input');
+        $aData = json_decode($sJson, true);
+
+        if (json_last_error() !== JSON_ERROR_NONE)
+            return echoJson(['code' => 500, 'msg' => _t('_sys_agents_json_field_err')]);
+        
+        $sPrompt = $aData['prompt'] ?? null;
+        $sInputName = $aData['input_name'] ?? null;
+        $aValues = $aData['values'] ?? [];
+
+        $aAgent = BxDolAiQuery::getAgentObject($iAgentId);
+        if (!$aAgent || !$aAgent['active'])
+            return echoJson(['code' => 404, 'msg' => _t('_sys_agents_agent_not_found')]);
+        
+        $aParams = [
+            'sender_profile_id' => bx_get_logged_profile_id(),
+            'user_prompt' => $sPrompt,
+            'form_field_name' => $sInputName,
+            'form_values' => $aValues,
+        ];
+
+        $oAi = BxDolAI::getInstance();
+        $mixed = $oAi->callAgent('form-input', $aAgent, $aParams);
+
+        return echoJson(['code' => 200, 'msg' => $mixed]);
+    }
+
 }
 }
 
 
 /** @} */
 /** @} */

+ 7 - 6
yarn.lock

@@ -564,10 +564,10 @@
     "@sigstore/core" "^3.0.0"
     "@sigstore/core" "^3.0.0"
     "@sigstore/protobuf-specs" "^0.5.0"
     "@sigstore/protobuf-specs" "^0.5.0"
 
 
-"@stripe/connect-js@^3.4.5":
-  version "3.4.5"
-  resolved "https://registry.yarnpkg.com/@stripe/connect-js/-/connect-js-3.4.5.tgz#ed8ef5e7a6f89653cc865ecd1567d25cf4d4b795"
-  integrity sha512-2GZYc1pO2gYtq5rooZei483oSqeNROTD4XwnKXK8GXILvrLVJjMUCLDXi8Rmu8ojL5DWMnEOtXdnZxs8xxZecQ==
+"@stripe/connect-js@^3.4.6":
+  version "3.4.6"
+  resolved "https://registry.yarnpkg.com/@stripe/connect-js/-/connect-js-3.4.6.tgz#03bf1fbb812226015f8e2c1f103f6082149dc5a8"
+  integrity sha512-fuC/U/ONDBMKwTBxKAnEBQH+m0x+Tze62/bV1ZDLT7oRnsJgddEnRi7FzdwIxz9pmFZhOJpSaikLIBw9g/1o1w==
 
 
 "@svta/cml-608@1.0.2":
 "@svta/cml-608@1.0.2":
   version "1.0.2"
   version "1.0.2"
@@ -1717,8 +1717,9 @@ headroom.js@^0.12.0:
   integrity sha512-iXnAafUm3FdzfJ91uixLws2hkKI1jC8bAKK/pt7XYr8Ie1jO7xbK48Ycpl9tUPyBgkzuj1p/PhJS0fy4E/5anA==
   integrity sha512-iXnAafUm3FdzfJ91uixLws2hkKI1jC8bAKK/pt7XYr8Ie1jO7xbK48Ycpl9tUPyBgkzuj1p/PhJS0fy4E/5anA==
 
 
 "highlight.js@github:highlightjs/highlight.js":
 "highlight.js@github:highlightjs/highlight.js":
-  version "11.11.1"
-  resolved "https://codeload.github.com/highlightjs/highlight.js/tar.gz/5697ae5187746c24732e62cd625f3f83004a44ce"
+  version "11.11.2"
+  uid f273f007f85e2096de41c42bf40b870dcb5a5a05
+  resolved "https://codeload.github.com/highlightjs/highlight.js/tar.gz/f273f007f85e2096de41c42bf40b870dcb5a5a05"
 
 
 hls.js@^1.6.16:
 hls.js@^1.6.16:
   version "1.6.16"
   version "1.6.16"