Bläddra i källkod

#5406 AI Agents revamp: form input trigger

Aleksandr Trofimov 3 månader sedan
förälder
incheckning
a84ba70033

+ 6 - 1
inc/classes/BxDolAI.php

@@ -436,7 +436,7 @@ class BxDolAI extends BxDolFactory implements iBxDolSingleton
         $aAgents = [];
         $a = $this->_oDb->getAgentsWithAlert();
         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)
                 $aAgents[] = $r;
         }
@@ -449,6 +449,11 @@ class BxDolAI extends BxDolFactory implements iBxDolSingleton
         return $this->_oDb->getAgentsByProfileId($iProfileId);
     }
     
+    public function getAgentsByFormObject($sFormObject)
+    {
+        return $this->_oDb->getAgentsByFormObject($sFormObject);
+    }
+
     public function getAgentsByTriggerType($sTrigger)
     {
         return $this->_oDb->getAgentsByTriggerType($sTrigger);

+ 5 - 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]);
     }
 
+    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)
     {
         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 - 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
 ('^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,7 +7194,7 @@ CREATE TABLE `sys_agents_agents` (
   `tools_max_run` int(11) NOT NULL DEFAULT 10,
   `chat_history_context` int(11) NOT NULL DEFAULT 50000,
   `vector_store_id` int(11) NOT NULL,
-  `trigger` enum('alert','scheduler','webhook','manual','agent','message','form-field') 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,
   `alert` varchar(192) NOT NULL DEFAULT '',
   `scheduler_cron` varchar(64) NOT NULL,

+ 37 - 0
studio/template/agents_agents_form_input_select.html

@@ -0,0 +1,37 @@
+<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>
+        function formatItem(state) {
+            return $(`
+            <div class="bx-form-input-wrap">
+                <div>
+                    <div class="bx-form-input-data">${state.text || state.id}</div>
+                </div>
+            </div>
+            `);
+        }
+        
+        $('#bx-agents-agents-form-input').select2({
+            templateResult: formatItem,
+            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>

+ 53 - 0
studio/template/agents_agents_form_object_select.html

@@ -0,0 +1,53 @@
+<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>
+    function formatItem(state) {
+        return $(`
+        <div class="bx-form-object-wrap">
+            <div>
+                <div class="bx-form-object-text">${state.text || state.id}</div>
+            </div>
+        </div>
+        `);
+    }
+    
+    $('#bx-agents-agents-form-object').select2({
+        templateResult: formatItem,
+        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>

+ 1 - 1
studio/template/scripts/BxBaseStudioAgentsAgents.php

@@ -365,7 +365,7 @@ class BxBaseStudioAgentsAgents extends BxDolStudioAgentsAgents
                         'manual' => 'manual',
                         'agent' => 'agent',
                         'message' => 'message',
-                        'form-field' => 'form field',
+                        'form-input' => 'form input',
                     ],
                     'attrs' => [
                         'onchange' => $this->getPageJsObject() . '.onChangeAgentTrigger(this)',

+ 34 - 0
template/form_field_textarea.html

@@ -6,4 +6,38 @@
         </div>
     </div>
 </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>

+ 26 - 0
template/scripts/BxBaseFormView.php

@@ -101,6 +101,9 @@ class BxBaseFormView extends BxDolForm
     protected $_sJsObjectName;
     
     protected $_aHtmlIds;
+
+    protected $_aAgentsFormObject;
+    protected $_sAgentFormObject;
     
     /**
      * Constructor
@@ -132,6 +135,8 @@ class BxBaseFormView extends BxDolForm
             $sName = $aInfo['params']['object'];
         if(empty($sName) && !empty($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('_' , '-'));
 
@@ -142,6 +147,9 @@ class BxBaseFormView extends BxDolForm
             'pgc_popup' => $sHtmlId . '-pgc-popup-',
             'pgc_form' => $sHtmlId . '-pgc-form-',
         );
+
+        $this->_sAgentFormObject = $aInfo['params']['object'] ?? $this->id;
+        $this->_aAgentsFormObject = BxDolAI::getInstance()->getAgentsByFormObject($this->_sAgentFormObject);
     }
 
     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']) : '';
 
+        $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', [
             'attrs' => bx_convert_array2attrs($aAttrs, $sClassAdd),
             'value' => $sValue,
             'bx_if:show_switcher' => [
                 'condition' => !empty($aTmplVarsSwitcher),
                 'content' => $aTmplVarsSwitcher
+            ],
+            'bx_if:show_agent' => [
+                'condition' => !empty($aAgent),
+                'content' => [
+                    'name' => $aInput['name'],
+                    'agent_id' => $aAgent['id'] ?? 0,
+                    'form_id' => $this->getId(),
+                ]
             ]
         ]);
     }

+ 17 - 0
template/scripts/BxBaseServices.php

@@ -1753,6 +1753,23 @@ class BxBaseServices extends BxDol implements iBxDolProfileService
         return $oAi->callAgent($sType, $aAgent, $aParams);
     }
 
+    public function serviceCallAgentForFormInput($iAgentId)
+    {
+        // TODO: check auth and permissions
+
+        $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'] ?? [];
+
+        return echoJson(['code' => 200, 'msg' => 'Great! ' . $sPrompt . random_int(1000, 9999) . ($aValues[$sInputName] ?? '')]);
+    }
+
 }
 
 /** @} */