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

Ticket #4711 - Automations: Assistants.

AntonLV 2 лет назад
Родитель
Сommit
7caa97ed27

+ 69 - 13
inc/classes/BxDolAIModelGpt40.php

@@ -16,15 +16,19 @@ class BxDolAIModelGpt40 extends BxDolAIModel
     protected $_sEndpointRunsCheck;
     protected $_sEndpointMessages;
 
+    protected $_sEndpointAssistants;
+    protected $_sEndpointAssistantsDelete;
+
     protected $_sEndpointFiles;
+    protected $_sEndpointFilesRetrieve;
     protected $_sEndpointFilesDelete;
-            
+
     protected $_sEndpointVectorStores;
+    protected $_sEndpointVectorStoresDelete;
+
     protected $_sEndpointVectorStoresFiles;
     protected $_sEndpointVectorStoresFilesRetrieve;
-    protected $_sEndpointVectorStoresFilesDelete;
-
-    protected $_sEndpointAssistants;
+    protected $_sEndpointVectorStoresFilesDelete;   
 
     protected $_sEndpointChat;
 
@@ -39,16 +43,20 @@ class BxDolAIModelGpt40 extends BxDolAIModel
         $this->_sEndpointRunsCheck = $this->_sEndpoint . '/%s/runs/%s';
         $this->_sEndpointMessages = $this->_sEndpoint . '/%s/messages';
 
+        $this->_sEndpointAssistants = 'https://api.openai.com/v1/assistants';
+        $this->_sEndpointAssistantsDelete = $this->_sEndpointAssistants . '/%s';
+
         $this->_sEndpointFiles = 'https://api.openai.com/v1/files';
-        $this->_sEndpointFilesDelete = 'https://api.openai.com/v1/files/%s';
-            
+        $this->_sEndpointFilesRetrieve = $this->_sEndpointFiles . '/%s';
+        $this->_sEndpointFilesDelete = $this->_sEndpointFilesRetrieve;
+
         $this->_sEndpointVectorStores = 'https://api.openai.com/v1/vector_stores';
+        $this->_sEndpointVectorStoresDelete = $this->_sEndpointVectorStores . '/%s';
+
         $this->_sEndpointVectorStoresFiles = $this->_sEndpointVectorStores . '/%s/files';
         $this->_sEndpointVectorStoresFilesRetrieve = $this->_sEndpointVectorStoresFiles . '/%s';
         $this->_sEndpointVectorStoresFilesDelete = $this->_sEndpointVectorStoresFiles . '/%s';
 
-        $this->_sEndpointAssistants = 'https://api.openai.com/v1/assistants';
-
         $this->_sEndpointChat = 'https://api.openai.com/v1/chat/completions';
     }
     
@@ -237,6 +245,21 @@ class BxDolAIModelGpt40 extends BxDolAIModel
 
         return $mixedResponse;
     }
+    
+    public function callVectorStoresDelete($sVectorStoreId, $aParams = [])
+    {
+        $aData = [];
+        if(!empty($this->_aParams['call_vs_delete']) && is_array($this->_aParams['call_vs_delete']))
+            $aData = array_merge($aData, $this->_aParams['call_vs_delete']);
+        if(!empty($aParams) && is_array($aParams))
+            $aData = array_merge($aData, $aParams);
+
+        $mixedResponse = $this->_call(sprintf($this->_sEndpointVectorStoresDelete, $sVectorStoreId), [], 'DELETE');
+        if(empty($mixedResponse) || !is_array($mixedResponse) || !$mixedResponse['deleted'])
+            return false;
+
+        return $mixedResponse;
+    }
 
     /**
      * Create a vector store file by attaching a File to a vector store.
@@ -259,15 +282,24 @@ class BxDolAIModelGpt40 extends BxDolAIModel
 
         return $mixedResponse;
     }
-
-    public function callVectorStoresFilesRetrieve($sVectorStoreId, $sFileId, $aParams = [])
+    
+    public function callVectorStoresFilesList($sVectorStoreId, $aParams = [])
     {
         $aData = [];
-        if(!empty($this->_aParams['call_vs_files_retrieve']) && is_array($this->_aParams['call_vs_files_retrieve']))
-            $aData = array_merge($aData, $this->_aParams['call_vs_files_retrieve']);
+        if(!empty($this->_aParams['call_vs_flist']) && is_array($this->_aParams['call_vs_flist']))
+            $aData = array_merge($aData, $this->_aParams['call_vs_flist']);
         if(!empty($aParams) && is_array($aParams))
             $aData = array_merge($aData, $aParams);
 
+        $mixedResponse = $this->_call(sprintf($this->_sEndpointVectorStoresFiles, $sVectorStoreId), $aData, 'get');
+        if(empty($mixedResponse) || !is_array($mixedResponse) || $mixedResponse['object'] != 'list')
+            return false;
+
+        return $mixedResponse['data'];
+    }
+
+    public function callVectorStoresFilesRetrieveFile($sVectorStoreId, $sFileId)
+    {
         return $this->_call(sprintf($this->_sEndpointVectorStoresFilesRetrieve, $sVectorStoreId, $sFileId), [], 'get');
     }
     
@@ -296,6 +328,21 @@ class BxDolAIModelGpt40 extends BxDolAIModel
 
         return $mixedResponse;
     }
+    
+    public function callAssistantsDelete($sAsstId, $aParams = [])
+    {
+        $aData = [];
+        if(!empty($this->_aParams['call_assts_delete']) && is_array($this->_aParams['call_assts_delete']))
+            $aData = array_merge($aData, $this->_aParams['call_assts_delete']);
+        if(!empty($aParams) && is_array($aParams))
+            $aData = array_merge($aData, $aParams);
+
+        $mixedResponse = $this->_call(sprintf($this->_sEndpointAssistantsDelete, $sAsstId), $aData, 'DELETE');
+        if(empty($mixedResponse) || !is_array($mixedResponse) || !$mixedResponse['deleted'])
+            return false;
+
+        return $mixedResponse;
+    }
 
     public function callFiles($aFile, $aParams = [])
     {
@@ -318,7 +365,16 @@ class BxDolAIModelGpt40 extends BxDolAIModel
 
         return $mixedResponse;
     }
-    
+
+    public function callFilesRetrieve($sFileId)
+    {
+        $mixedResponse = $this->_callFiles(sprintf($this->_sEndpointFilesRetrieve, $sFileId), [], 'get');
+        if(empty($mixedResponse) || !is_array($mixedResponse) || $mixedResponse['object'] != 'file')
+            return false;
+
+        return $mixedResponse;
+    }
+
     public function callFilesDelete($sFileId, $aParams = [])
     {
         $aData = [];

+ 57 - 0
inc/classes/BxDolAIQuery.php

@@ -653,6 +653,63 @@ class BxDolAIQuery extends BxDolDb
 
         return (int)$this->query("DELETE FROM `sys_agents_assistants_chats` WHERE " . $this->arrayToSQL($aParamsWhere, ' AND ')) > 0;
     }
+    
+    public function getFilesBy($aParams = [])
+    {
+        $aMethod = ['name' => 'getAll', 'params' => [0 => 'query']];
+        $sSelectClause = "`taf`.*";
+    	$sJoinClause = $sWhereClause = "";
+
+        switch($aParams['sample']) {
+            case 'id':
+            	$aMethod['name'] = 'getRow';
+            	$aMethod['params'][1] = [
+                    'id' => $aParams['id']
+                ];
+
+                $sWhereClause .= " AND `taf`.`id`=:id";
+                break;
+
+            case 'assistant_id':
+                $aMethod['params'][1] = [
+                    'assistant_id' => $aParams['assistant_id']
+                ];
+
+                $sWhereClause .= " AND `taf`.`assistant_id`=:assistant_id";
+                break;
+                
+        }
+
+        $aMethod['params'][0] = "SELECT " . $sSelectClause . "
+            FROM `sys_agents_assistants_files` AS `taf` " . $sJoinClause . "
+            WHERE 1" . $sWhereClause;
+
+        return call_user_func_array([$this, $aMethod['name']], $aMethod['params']);
+    }
+
+    public function insertFile($aParamsSet)
+    {
+        if(empty($aParamsSet) || !is_array($aParamsSet))
+            return false;
+
+        return (int)$this->query("INSERT INTO `sys_agents_assistants_files` SET " . $this->arrayToSQL($aParamsSet)) > 0 ? (int)$this->lastId() : false;
+    }
+
+    public function updateFiles($aSetClause, $aWhereClause)
+    {
+        if(empty($aSetClause) || empty($aWhereClause))
+            return false;
+
+        return (int)$this->query("UPDATE `sys_agents_assistants_files` SET " . $this->arrayToSQL($aSetClause) . " WHERE " . $this->arrayToSQL($aWhereClause)) > 0;
+    }
+
+    public function deleteFiles($aParamsWhere)
+    {
+        if(empty($aParamsWhere))
+            return false;
+
+        return (int)$this->query("DELETE FROM `sys_agents_assistants_files` WHERE " . $this->arrayToSQL($aParamsWhere, ' AND ')) > 0;
+    }
 }
 
 /** @} */

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
install/sql/system.sql


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

@@ -2236,6 +2236,7 @@
     <string name="_sys_agents_assistants_txt_assistant"><![CDATA[Assistant]]></string>
     <string name="_sys_agents_assistants_btn_add"><![CDATA[Add Assistant]]></string>
     <string name="_sys_agents_assistants_btn_chats"><![CDATA[Chats]]></string>
+    <string name="_sys_agents_assistants_btn_files"><![CDATA[Files]]></string>
     <string name="_sys_agents_assistants_field_name"><![CDATA[Name]]></string>
     <string name="_sys_agents_assistants_field_model_id"><![CDATA[Model]]></string>
     <string name="_sys_agents_assistants_field_profile_id"><![CDATA[Profile]]></string>
@@ -2260,6 +2261,19 @@
     <string name="_sys_agents_assistants_chats_field_description"><![CDATA[Description]]></string>
     <string name="_sys_agents_assistants_chats_popup_add"><![CDATA[Add chat]]></string>
     <string name="_sys_agents_assistants_chats_popup_edit"><![CDATA[Edit chat]]></string>
+    <string name="_sys_agents_assistants_files_txt_name"><![CDATA[Name]]></string>
+    <string name="_sys_agents_assistants_files_txt_size"><![CDATA[Size]]></string>
+    <string name="_sys_agents_assistants_files_txt_status"><![CDATA[Status]]></string>
+    <string name="_sys_agents_assistants_files_txt_status_in_progress"><![CDATA[In progress]]></string>
+    <string name="_sys_agents_assistants_files_txt_status_completed"><![CDATA[Completed]]></string>
+    <string name="_sys_agents_assistants_files_txt_status_failed"><![CDATA[Failed]]></string>
+    <string name="_sys_agents_assistants_files_txt_status_cancelled"><![CDATA[Cancelled]]></string>
+    <string name="_sys_agents_assistants_files_txt_added"><![CDATA[Added]]></string>
+    <string name="_sys_agents_assistants_files_btn_add"><![CDATA[Add File]]></string>
+    <string name="_sys_agents_assistants_files_btn_sync"><![CDATA[Sync]]></string>
+    <string name="_sys_agents_assistants_files_btn_delete"><![CDATA[Delete file]]></string>
+    <string name="_sys_agents_assistants_files_field_file"><![CDATA[File]]></string>
+    <string name="_sys_agents_assistants_files_popup_add"><![CDATA[Add File]]></string>
 
   <string name="_sys_audit_content_info_popup_title"><![CDATA[Information]]></string>
   <string name="_sys_audit_action_edit_content"><![CDATA[Content edited]]></string>

+ 15 - 1
modules/boonex/russian/data/langs/system/ru.xml

@@ -2211,7 +2211,8 @@
         <string name="_sys_agents_assistants_txt_added"><![CDATA[Добавлено]]></string>
         <string name="_sys_agents_assistants_txt_assistant"><![CDATA[Ассистент]]></string>
         <string name="_sys_agents_assistants_btn_add"><![CDATA[Добавить ассистента]]></string>
-        <string name="_sys_agents_assistants_btn_tune"><![CDATA[Настройка]]></string>
+        <string name="_sys_agents_assistants_btn_chats"><![CDATA[Чаты]]></string>
+        <string name="_sys_agents_assistants_btn_files"><![CDATA[Файлы]]></string>
         <string name="_sys_agents_assistants_field_name"><![CDATA[Название]]></string>
         <string name="_sys_agents_assistants_field_model_id"><![CDATA[Модель]]></string>
         <string name="_sys_agents_assistants_field_profile_id"><![CDATA[Профиль]]></string>
@@ -2236,6 +2237,19 @@
         <string name="_sys_agents_assistants_chats_field_description"><![CDATA[Описание]]></string>
         <string name="_sys_agents_assistants_chats_popup_add"><![CDATA[Добавить чат]]></string>
         <string name="_sys_agents_assistants_chats_popup_edit"><![CDATA[Редактировать чат]]></string>
+        <string name="_sys_agents_assistants_files_txt_name"><![CDATA[Название]]></string>
+        <string name="_sys_agents_assistants_files_txt_size"><![CDATA[Размер]]></string>
+        <string name="_sys_agents_assistants_files_txt_status"><![CDATA[Статус]]></string>
+        <string name="_sys_agents_assistants_files_txt_status_in_progress"><![CDATA[В ходе выполнения]]></string>
+        <string name="_sys_agents_assistants_files_txt_status_completed"><![CDATA[Завершенный]]></string>
+        <string name="_sys_agents_assistants_files_txt_status_failed"><![CDATA[Неудавшийся]]></string>
+        <string name="_sys_agents_assistants_files_txt_status_cancelled"><![CDATA[Отменённый]]></string>
+        <string name="_sys_agents_assistants_files_txt_added"><![CDATA[Добавлен]]></string>
+        <string name="_sys_agents_assistants_files_btn_add"><![CDATA[Добавить файл]]></string>
+        <string name="_sys_agents_assistants_files_btn_sync"><![CDATA[Cинхронизировать]]></string>
+        <string name="_sys_agents_assistants_files_btn_delete"><![CDATA[Удалить файл]]></string>
+        <string name="_sys_agents_assistants_files_field_file"><![CDATA[Файл]]></string>
+        <string name="_sys_agents_assistants_files_popup_add"><![CDATA[Добавить файл]]></string>
 
   <string name="_sys_audit_content_info_popup_title"><![CDATA[Информация]]></string>
   <string name="_sys_audit_action_edit_content"><![CDATA[Контент изменен]]></string>

+ 1 - 1
studio/classes/BxDolStudioAgentsAsstChatsCmts.php

@@ -41,7 +41,7 @@ class BxDolStudioAgentsAsstChatsCmts extends BxTemplCmts
             $this->_iAssistantId = bx_process_input($iAssistantId, BX_DATA_INT);
             $this->_aMarkers['assistant_id'] = $this->_iAssistantId;
         }
-        $this->_sAssistantUrl = BX_DOL_URL_STUDIO . bx_append_url_params('agents.php', ['page' => 'assistants', 'aid' => $this->_iAssistantId]);
+        $this->_sAssistantUrl = BX_DOL_URL_STUDIO . bx_append_url_params('agents.php', ['page' => 'assistants', 'spage' => 'chats', 'aid' => $this->_iAssistantId]);
 
         $this->_bAuto = false;
     }

+ 47 - 0
studio/classes/BxDolStudioAgentsAsstFiles.php

@@ -0,0 +1,47 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    UnaStudio UNA Studio
+ * @{
+ */
+
+class BxDolStudioAgentsAsstFiles extends BxTemplStudioGrid
+{
+    protected $_oDb;
+
+    protected $_iAssistantId;
+    protected $_aAssistantInfo;
+
+    public function __construct ($aOptions, $oTemplate = false)
+    {
+        parent::__construct ($aOptions, $oTemplate);
+
+        $this->_sDefaultSortingOrder = 'DESC';
+
+        $this->_oDb = new BxDolStudioAgentsQuery();
+
+        if(($iAssistantId = bx_get('aid')) !== false) 
+            $this->setAssistantId($iAssistantId);
+    }
+
+    public function setAssistantId($iAssistantId)
+    {
+        $this->_iAssistantId = bx_process_input($iAssistantId, BX_DATA_INT);
+        $this->_aAssistantInfo = $this->_oDb->getAssistantsBy(['sample' => 'id', 'id' => $this->_iAssistantId]);
+
+        $this->_aQueryAppend['aid'] = $this->_iAssistantId;
+    }
+
+    protected function _getDataSql($sFilter, $sOrderField, $sOrderDir, $iStart, $iPerPage)
+    {
+        if(empty($this->_iAssistantId))
+            return [];
+
+        $this->_aOptions['source'] .= $this->_oDb->prepareAsString(" AND `assistant_id`=? ", $this->_iAssistantId);
+        return parent::_getDataSql($sFilter, $sOrderField, $sOrderDir, $iStart, $iPerPage);
+    }
+}
+
+/** @} */

+ 14 - 1
studio/template/scripts/BxBaseStudioAgents.php

@@ -44,6 +44,7 @@ class BxBaseStudioAgents extends BxDolStudioAgents
             BX_DOL_STUDIO_AGENTS_TYPE_PROVIDERS => 'sys_studio_agents_providers',
             BX_DOL_STUDIO_AGENTS_TYPE_ASSISTANTS => 'sys_studio_agents_assistants',
             BX_DOL_STUDIO_AGENTS_TYPE_ASSISTANTS . '_chats' => 'sys_studio_agents_assistants_chats',
+            BX_DOL_STUDIO_AGENTS_TYPE_ASSISTANTS . '_files' => 'sys_studio_agents_assistants_files',
             BX_DOL_STUDIO_AGENTS_TYPE_HELPERS => 'sys_studio_agents_helpers',
         ];
     }
@@ -142,6 +143,10 @@ class BxBaseStudioAgents extends BxDolStudioAgents
         
         $this->aPageJsOptions['sPageUrl'] .= 'assistants';
 
+        $sSubPage = '';
+        if(($sSubPage = bx_get('spage')) !== false)
+            $sSubPage = bx_process_input($sSubPage, BX_DATA_TEXT);
+
         $iAssistantId = 0;
         if(($iAssistantId = bx_get('aid')) !== false)
             $iAssistantId = bx_process_input($iAssistantId, BX_DATA_INT);
@@ -184,7 +189,15 @@ class BxBaseStudioAgents extends BxDolStudioAgents
                     'url_back' => $this->aPageJsOptions['sPageUrl']
                 ]);
             
-            $aResult[] = $this->getGrid($this->aGridObjects[BX_DOL_STUDIO_AGENTS_TYPE_ASSISTANTS . '_chats']);
+            switch($sSubPage) {
+                case 'chats':
+                    $aResult[] = $this->getGrid($this->aGridObjects[BX_DOL_STUDIO_AGENTS_TYPE_ASSISTANTS . '_chats']);
+                    break;
+
+                case 'files':
+                    $aResult[] = $this->getGrid($this->aGridObjects[BX_DOL_STUDIO_AGENTS_TYPE_ASSISTANTS . '_files']);
+                    break;
+            }
 
             return $aResult;
         }

+ 24 - 3
studio/template/scripts/BxBaseStudioAgentsAssistants.php

@@ -149,7 +149,16 @@ class BxBaseStudioAgentsAssistants extends BxDolStudioAgentsAssistants
     protected function _getActionChats($sType, $sKey, $a, $isSmall = false, $isDisabled = false, $aRow = [])
     {
     	$a['attr'] = array_merge($a['attr'], [
-            "onclick" => "window.open('" . $this->_sUrlPage . '&aid=' . $aRow['id'] . "', '_self');"
+            "onclick" => "window.open('" . $this->_sUrlPage . '&spage=chats&aid=' . $aRow['id'] . "', '_self');"
+    	]);
+
+    	return $this->_getActionDefault ($sType, $sKey, $a, $isSmall, $isDisabled, $aRow);
+    }
+
+    protected function _getActionFiles($sType, $sKey, $a, $isSmall = false, $isDisabled = false, $aRow = [])
+    {
+    	$a['attr'] = array_merge($a['attr'], [
+            "onclick" => "window.open('" . $this->_sUrlPage . '&spage=files&aid=' . $aRow['id'] . "', '_self');"
     	]);
 
     	return $this->_getActionDefault ($sType, $sKey, $a, $isSmall, $isDisabled, $aRow);
@@ -177,19 +186,31 @@ class BxBaseStudioAgentsAssistants extends BxDolStudioAgentsAssistants
 
     protected function _delete ($mixedId)
     {
+        $iAssistantId = (int)$mixedId;
+        $aAssistant = $this->_oDb->getAssistantsBy(['sample' => 'id', 'id' => $iAssistantId]);
+
         $mixedResult = parent::_delete($mixedId);
         if($mixedResult) {
             $oAi = BxDolAI::getInstance();
-            $iAssistantId = (int)$mixedId;
+            $oAIModel = $oAi->getModelObject($aAssistant['model_id']);
 
             $aChats = $this->_oDb->getChatsBy(['sample' => 'assistant_id', 'assistant_id' => $iAssistantId]);
-            foreach($aChats as $aChat)
+            foreach($aChats as $aChat) {
                 if(($oCmts = $oAi->getAssistantChatCmtsObject($aChat['id'])) !== false)
                     $oCmts->onObjectDelete();
 
+                if(!empty($aChat['ai_file_id'])) {
+                    $oAIModel->callVectorStoresFilesDelete($aAssistant['ai_vs_id'], $aChat['ai_file_id']);
+                    $oAIModel->callFilesDelete($aChat['ai_file_id']);
+                }
+            }
+
             $this->_oDb->deleteChats(['assistant_id' => $iAssistantId]);
 
             $this->_oDb->deleteAutomatorAssistants(['assistant_id' => $iAssistantId]);
+
+            $oAIModel->callVectorStoresDelete($aAssistant['ai_vs_id']);
+            $oAIModel->callAssistantsDelete($aAssistant['ai_asst_id']);
         }
 
         return $mixedResult;

+ 29 - 4
studio/template/scripts/BxBaseStudioAgentsAsstChats.php

@@ -17,7 +17,7 @@ class BxBaseStudioAgentsAsstChats extends BxDolStudioAgentsAsstChats
     {
         parent::__construct ($aOptions, $oTemplate);
 
-        $this->_sUrlPage = BX_DOL_URL_STUDIO . 'agents.php?page=assistants&aid=' . $this->_iAssistantId;
+        $this->_sUrlPage = BX_DOL_URL_STUDIO . 'agents.php?page=assistants&spage=chats&aid=' . $this->_iAssistantId;
 
         $this->_sFieldName = 'name';
     }
@@ -134,10 +134,12 @@ class BxBaseStudioAgentsAsstChats extends BxDolStudioAgentsAsstChats
         }
 
         $aRes = [];
-        if(($aFile = $oAIModel->callFiles(['content' => json_encode($aMessages), 'name' => $aChat['name'] . '.json', 'mime' => 'application/json'])) !== false) {
+        if(($sFile = $aChat['name'] . '.json') && ($aFile = $oAIModel->callFiles(['content' => json_encode($aMessages), 'name' => $sFile, 'mime' => 'application/json'])) !== false) {
             if(($aResponse = $oAIModel->callVectorStoresFiles($aAssistant['ai_vs_id'], ['file_id' => $aFile['id']])) !== false) {
-                $this->_oDb->updateChats(['ai_file_id' => $aFile['id'], 'stored' => time()], ['id' => $iId]);
-                
+                $iNow = time();
+                $this->_oDb->insertFile(['name' => $sFile, 'assistant_id' => $aAssistant['id'], 'added' => $iNow, 'ai_file_id' => $aFile['id'], 'locked' => 1]);
+                $this->_oDb->updateChats(['ai_file_id' => $aFile['id'], 'stored' => $iNow], ['id' => $iId]);
+
                 $aRes = ['grid' => $this->getCode(false), 'blink' => $iId];
             }
         }
@@ -165,6 +167,7 @@ class BxBaseStudioAgentsAsstChats extends BxDolStudioAgentsAsstChats
         if(!$oAIModel->callFilesDelete($aChat['ai_file_id']))
             return echoJson([]);
 
+        $this->_oDb->deleteFiles(['ai_file_id' => $aChat['ai_file_id']]);
         $this->_oDb->updateChats(['ai_file_id' => '', 'stored' => 0], ['id' => $iId]);
 
         echoJson(['grid' => $this->getCode(false), 'blink' => $iId]);
@@ -227,6 +230,28 @@ class BxBaseStudioAgentsAsstChats extends BxDolStudioAgentsAsstChats
         return false;
     }
 
+    protected function _delete ($mixedId)
+    {
+        $iChatId = (int)$mixedId;
+        $aChat = $this->_oDb->getChatsBy(['sample' => 'id', 'id' => $iChatId]);
+        $aAssistant = $this->_oDb->getAssistantsBy(['sample' => 'id', 'id' => $aChat['assistant_id']]);
+
+        $mixedResult = parent::_delete($mixedId);
+        if($mixedResult) {
+            $oAi = BxDolAI::getInstance();
+            $oAIModel = $oAi->getModelObject($aAssistant['model_id']);
+
+            if(($oCmts = $oAi->getAssistantChatCmtsObject($iChatId)) !== false)
+                $oCmts->onObjectDelete();
+
+            if(!empty($aChat['ai_file_id'])) {
+                $oAIModel->callVectorStoresFilesDelete($aAssistant['ai_vs_id'], $aChat['ai_file_id']);
+                $oAIModel->callFilesDelete($aChat['ai_file_id']);
+            }
+        }
+
+        return $mixedResult;
+    }
     protected function _getFormEdit($sAction, $aChat = [])
     {
         $aForm = $this->_getForm($sAction, $aChat);

+ 236 - 0
studio/template/scripts/BxBaseStudioAgentsAsstFiles.php

@@ -0,0 +1,236 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    UnaView UNA Studio Representation classes
+ * @ingroup     UnaStudio
+ * @{
+ */
+
+class BxBaseStudioAgentsAsstFiles extends BxDolStudioAgentsAsstFiles
+{
+    protected $_sUrlPage;
+
+    public function __construct ($aOptions, $oTemplate = false)
+    {
+        parent::__construct ($aOptions, $oTemplate);
+
+        $this->_sUrlPage = BX_DOL_URL_STUDIO . 'agents.php?page=assistants&spage=files&aid=' . $this->_iAssistantId;
+    }
+
+    public function getPageJsObject()
+    {
+        return 'oBxDolStudioPageAgents';
+    }
+
+    public function performActionAdd()
+    {
+        $sAction = 'add';
+
+        $aForm = $this->_getForm($sAction);
+        $oForm = new BxTemplFormView($aForm);
+        $oForm->initChecker();
+
+        if($oForm->isSubmittedAndValid()) {
+            $aValsToAdd = ['assistant_id' => $this->_iAssistantId, 'added' => time()];
+
+            if(!empty($_FILES['file']['tmp_name'])) {
+                $sName = $_FILES['file']['name'];
+                $sMime = $_FILES['file']['type'];
+                $iSize = $_FILES['file']['size'];
+
+                $oHandle = fopen($_FILES['file']['tmp_name'], "r");
+                $sContents = fread($oHandle, $iSize);
+                fclose($oHandle);
+
+                $oAIModel = BxDolAI::getInstance()->getModelObject($this->_aAssistantInfo['model_id']);
+                if(($aFile = $oAIModel->callFiles(['content' => $sContents, 'name' => $sName, 'mime' => $sMime])) !== false) {
+                    if(($aResponse = $oAIModel->callVectorStoresFiles($this->_aAssistantInfo['ai_vs_id'], ['file_id' => $aFile['id']])) !== false) {
+                        $aValsToAdd = array_merge($aValsToAdd, [
+                            'name' => $sName,
+                            'ai_file_id' => $aFile['id'],
+                            'ai_file_size' => $iSize
+                        ]);
+                    }
+                }
+            }
+
+            if(($iId = $oForm->insert($aValsToAdd)) !== false)
+                $aRes = ['grid' => $this->getCode(false), 'blink' => $iId];
+            else
+                $aRes = ['msg' => _t('_sys_txt_error_occured')];
+
+            return echoJson($aRes);
+        }
+
+        $sFormId = $oForm->getId();
+        $sContent = BxTemplStudioFunctions::getInstance()->popupBox($sFormId . '_popup', _t('_sys_agents_assistants_files_popup_add'), $this->_oTemplate->parseHtmlByName('agents_automator_form.html', [
+            'form_id' => $sFormId,
+            'form' => $oForm->getCode(true),
+            'object' => $this->_sObject,
+            'action' => $sAction
+        ]));
+
+        return echoJson(['popup' => ['html' => $sContent, 'options' => ['closeOnOuterClick' => false]]]);
+    }
+
+    public function performActionSync()
+    {
+        $sAction = 'sync';
+
+        $oAIModel = BxDolAI::getInstance()->getModelObject($this->_aAssistantInfo['model_id']);
+        if(($aFiles = $oAIModel->callVectorStoresFilesList($this->_aAssistantInfo['ai_vs_id'])) === false)
+            return echoJson([]);
+
+        foreach($aFiles as $aFile) {
+            $aFileInfo = $oAIModel->callFilesRetrieve($aFile['id']);
+
+            $this->_oDb->updateFiles([
+                'ai_file_size' => is_array($aFileInfo) && !empty($aFileInfo['bytes']) ? $aFileInfo['bytes'] : 0, 
+                'ai_file_status' => $aFile['status']
+            ], ['ai_file_id' => $aFile['id']]);
+        }
+
+        return echoJson(['grid' => $this->getCode(false)]);
+    }
+    
+    public function performActionDelete()
+    {
+        $sAction = 'delete';
+
+        $iId = $this->_getId();
+
+        $aFile = $this->_oDb->getFilesBy(['sample' => 'id', 'id' => $iId]);
+        if(empty($aFile) || !is_array($aFile))
+            return echoJson([]);
+
+        return parent::performActionDelete();
+    }
+
+    protected function _getCellSize($mixedValue, $sKey, $aField, $aRow)
+    {
+        return parent::_getCellDefault(!empty($aRow['ai_file_size']) ? _t_format_size($aRow['ai_file_size']) : _t('_undefined'), $sKey, $aField, $aRow);
+    }
+
+    protected function _getCellStatus($mixedValue, $sKey, $aField, $aRow)
+    {
+        return parent::_getCellDefault(_t('_sys_agents_assistants_files_txt_status_' . $aRow['ai_file_status']), $sKey, $aField, $aRow);
+    }
+
+    protected function _getCellAdded($mixedValue, $sKey, $aField, $aRow)
+    {
+        return parent::_getCellDefault(bx_time_js($mixedValue), $sKey, $aField, $aRow);
+    }
+
+    protected function _getActionDelete($sType, $sKey, $a, $isSmall = false, $isDisabled = false, $aRow = [])
+    {
+        if((int)$aRow['locked'] != 0) 
+            return '';
+
+        return $this->_getActionDefault ($sType, $sKey, $a, $isSmall, $isDisabled, $aRow);
+    }
+
+    protected function _addJsCss()
+    {
+        parent::_addJsCss();
+
+        $this->_oTemplate->addJs(['jquery.form.min.js']);
+
+        $oForm = new BxTemplStudioFormView([]);
+        $oForm->addCssJs();
+    }
+    
+    protected function _isCheckboxDisabled($aRow)
+    {
+        return false;
+    }
+
+    protected function _getActionsDisabledBehavior($aRow)
+    {
+        return false;
+    }
+
+    protected function _delete ($mixedId)
+    {
+        $iFileId = (int)$mixedId;
+        $aFile = $this->_oDb->getFilesBy(['sample' => 'id', 'id' => $iFileId]);
+
+        $mixedResult = parent::_delete($mixedId);
+        if($mixedResult && !empty($aFile['ai_file_id'])) {
+            $oAi = BxDolAI::getInstance();
+
+            $oAIModel = $oAi->getModelObject($this->_aAssistantInfo['model_id']);
+            $oAIModel->callVectorStoresFilesDelete($this->_aAssistantInfo['ai_vs_id'], $aFile['ai_file_id']);
+            $oAIModel->callFilesDelete($aFile['ai_file_id']);
+        }
+
+        return $mixedResult;
+    }
+
+    protected function _getForm($sAction, $aFiles = [])
+    {
+        $sJsObject = $this->getPageJsObject();
+
+        $aForm = array(
+            'form_attrs' => array(
+                'id' => 'bx_std_agents_assistants_files_' . $sAction,
+                'action' => BX_DOL_URL_ROOT . bx_append_url_params('grid.php', ['o' => 'sys_studio_agents_assistants_files', 'a' => $sAction, 'aid' => $this->_iAssistantId]),
+                'method' => 'post',
+            ),
+            'params' => array (
+                'db' => array(
+                    'table' => 'sys_agents_assistants_files',
+                    'key' => 'id',
+                    'submit_name' => 'do_submit',
+                ),
+            ),
+            'inputs' => array(
+                'file' => [
+                    'type' => 'file',
+                    'name' => 'file',
+                    'required' => '1',
+                    'caption' => _t('_sys_agents_assistants_files_field_file'),
+                    'value' => '',
+                    'checker' => [
+                        'func' => 'Avail',
+                        'params' => '',
+                        'error' => _t('_sys_agents_form_field_err_enter'),
+                    ]
+                ],
+                'submit' => array(
+                    'type' => 'input_set',
+                    0 => array (
+                        'type' => 'submit',
+                        'name' => 'do_submit',
+                        'value' => _t('_sys_submit'),
+                    ),
+                    1 => array (
+                        'type' => 'reset',
+                        'name' => 'close',
+                        'value' => _t('_sys_close'),
+                        'attrs' => array('class' => 'bx-def-margin-sec-left', 'onclick' => '$(\'.bx-popup-applied:visible\').dolPopupHide();'),
+                    ),
+                ),
+
+            ),
+        );
+
+        return $aForm;
+    }
+
+    protected function _getId()
+    {
+        $aIds = bx_get('ids');
+        if(!empty($aIds) && is_array($aIds))
+            return array_shift($aIds);
+
+        $iId = (int)bx_get('id');
+        if(!$iId)
+            return false;
+
+        return $iId;
+    }
+}
+
+/** @} */

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

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

Некоторые файлы не были показаны из-за большого количества измененных файлов