BxBaseStudioAgentsAgents.php 54 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329
  1. <?php defined('BX_DOL') or die('hack attempt');
  2. /**
  3. * Copyright (c) UNA, Inc - https://una.io
  4. * MIT License - https://opensource.org/licenses/MIT
  5. *
  6. * @defgroup UnaView UNA Studio Representation classes
  7. * @ingroup UnaStudio
  8. * @{
  9. */
  10. class BxBaseStudioAgentsAgents extends BxDolStudioAgentsAgents
  11. {
  12. protected $_sUrlPage;
  13. protected $_sFieldName;
  14. public function __construct ($aOptions, $oTemplate = false)
  15. {
  16. parent::__construct ($aOptions, $oTemplate);
  17. $this->_sUrlPage = BX_DOL_URL_STUDIO . 'agents.php?page=agents';
  18. $this->_sFieldName = 'name';
  19. }
  20. public function getPageJsObject()
  21. {
  22. return 'oBxDolStudioPageAgents';
  23. }
  24. public function performActionGetAlert()
  25. {
  26. $aAlert = $this->_getAlertPayload(bx_get('alert'));
  27. echoJson([
  28. 'code' => $aAlert ? 200 : 404,
  29. 'desc' => $aAlert ? $this->_oDb->getAlertDesc(bx_get('alert')) : '',
  30. 'payload' => $aAlert,
  31. ]);
  32. }
  33. public function performActionGetFormInputs()
  34. {
  35. $aFormInputs = $this->_getFormInputs(bx_get('form_object'));
  36. if (!$aFormInputs) {
  37. echoJson(['code' => 404, 'msg' => _t('_sys_not_available')]);
  38. return;
  39. }
  40. echoJson([
  41. 'code' => $aFormInputs ? 200 : 404,
  42. 'form_inputs' => $aFormInputs,
  43. ]);
  44. }
  45. public function performActionManual()
  46. {
  47. $iId = $this->_getId();
  48. $aAgent = BxDolAiQuery::getAgentObject($iId);
  49. if (!$aAgent) {
  50. echoJson(['msg' => _t('_sys_txt_error_occured')]);
  51. return;
  52. }
  53. if (!$aAgent['active']) {
  54. echoJson(['msg' => _t('_sys_txt_agent_inactive')]);
  55. return;
  56. }
  57. $oAi = BxDolAi::getInstance();
  58. try {
  59. $sResponse = $oAi->callAgent('manual', $aAgent);
  60. } catch (Throwable $o) {
  61. echoJson(['msg' => $o->getMessage()]);
  62. return;
  63. }
  64. $oParsedown = new Parsedown();
  65. $oParsedown->setSafeMode(true);
  66. $sMessageHtml = $oParsedown->text($sResponse);
  67. $oTemplate = BxDolStudioTemplate::getInstance();
  68. $sHtml = $oTemplate->parseHtmlByName('agents_manual_response.html', [
  69. 'response' => $sMessageHtml
  70. ]);
  71. echoJson(['msg' => $sHtml]);
  72. }
  73. public function performActionWipeChatHistory()
  74. {
  75. $iId = $this->_getId();
  76. $aAgent = BxDolAiQuery::getAgentObject($iId);
  77. if (!$aAgent) {
  78. echoJson(['msg' => _t('_sys_txt_error_occured')]);
  79. return;
  80. }
  81. $oDb = new BxDolAiQuery();
  82. $oDb->wipeAgentChatHistory($aAgent);
  83. $aRes = ['grid' => $this->getCode(false), 'blink' => $iId];
  84. echoJson($aRes);
  85. }
  86. public function performActionAdd()
  87. {
  88. $sAction = 'add';
  89. $oTemplate = BxDolStudioTemplate::getInstance();
  90. $oAI = BxDolAi::getInstance();
  91. $aForm = $this->_getForm($sAction);
  92. $oForm = new BxTemplFormView($aForm);
  93. $oForm->initChecker();
  94. if ($oForm->isSubmitted() && $oForm->getCleanValue('trigger') == 'message') {
  95. $aAgent = $this->_getAgentWithProfile($oForm->getCleanValue('profile_id'));
  96. if ($aAgent) {
  97. $oForm->aInputs['profile_id']['error'] = _t('_sys_agents_form_field_err_profile_has_agent', $aAgent['name']);
  98. $oForm->setValid(false);
  99. }
  100. }
  101. if($oForm->isSubmittedAndValid()) {
  102. $aValsToAdd = [
  103. 'added' => time()
  104. ];
  105. $sName = $oForm->getCleanValue($this->_sFieldName);
  106. $sName = $this->_getUniqName($sName);
  107. BxDolForm::setSubmittedValue($this->_sFieldName, $sName, $oForm->aFormAttrs['method']);
  108. $iProfileId = $oForm->getCleanValue('profile_id');
  109. if(empty($iProfileId)) {
  110. $iProfileId = (int)getParam('sys_profile_bot');
  111. if(empty($iProfileId))
  112. $iProfileId = current(bx_srv('system', 'get_options_agents_profile', [false], 'TemplServices'))['key'];
  113. $aValsToAdd['profile_id'] = $iProfileId;
  114. }
  115. $iModel = $oForm->getCleanValue('model_id');
  116. $sTrigger = $oForm->getCleanValue('trigger');
  117. $sTools = is_array($oForm->getCleanValue('tools')) ? implode(',', $oForm->getCleanValue('tools')) : '';
  118. $aValsToAdd['tools'] = $sTools;
  119. $aValsToAdd['acl_levels'] = (int)$oForm->getCleanValue('acl_levels');
  120. $bIsValid = true;
  121. if($bIsValid) {
  122. if(($iId = $oForm->insert($aValsToAdd)) !== false) {
  123. $this->_oDb->cleanCache('sys_agents_with_alert');
  124. $aRes = ['grid' => $this->getCode(false), 'blink' => $iId];
  125. }
  126. else
  127. $aRes = ['msg' => _t('_sys_txt_error_occured')];
  128. return echoJson($aRes);
  129. }
  130. }
  131. $sFormId = $oForm->getId();
  132. $sContent = BxTemplStudioFunctions::getInstance()->popupBox($sFormId . '_popup', _t('_sys_agents_agents_popup_add'), $this->_oTemplate->parseHtmlByName('agents_agents_form.html', [
  133. 'form_id' => $sFormId,
  134. 'form' => $oForm->getCode(true),
  135. 'object' => $this->_sObject,
  136. 'action' => $sAction
  137. ]));
  138. return echoJson(['popup' => ['html' => $sContent, 'options' => ['closeOnOuterClick' => false]]]);
  139. }
  140. public function performActionEdit()
  141. {
  142. $sAction = 'edit';
  143. $oTemplate = BxDolStudioTemplate::getInstance();
  144. $oAI = BxDolAi::getInstance();
  145. $iId = $this->_getId();
  146. $aAgent = BxDolAiQuery::getAgentObject($iId);
  147. $aForm = $this->_getFormEdit($sAction, $aAgent);
  148. $oForm = new BxTemplFormView($aForm);
  149. $oForm->initChecker();
  150. if ($oForm->isSubmitted() && $oForm->getCleanValue('trigger') == 'message') {
  151. $aAgent = $this->_getAgentWithProfile($oForm->getCleanValue('profile_id'), $iId);
  152. if ($aAgent) {
  153. $oForm->aInputs['profile_id']['error'] = _t('_sys_agents_form_field_err_profile_has_agent', $aAgent['name']);
  154. $oForm->setValid(false);
  155. }
  156. }
  157. if($oForm->isSubmittedAndValid()) {
  158. $aValsToAdd = [];
  159. $sName = $oForm->getCleanValue($this->_sFieldName);
  160. $sName = $this->_getUniqName($sName);
  161. BxDolForm::setSubmittedValue($this->_sFieldName, $sName, $oForm->aFormAttrs['method']);
  162. $iProfileId = $oForm->getCleanValue('profile_id');
  163. if(empty($iProfileId)) {
  164. $iProfileId = (int)getParam('sys_profile_bot');
  165. if(empty($iProfileId))
  166. $iProfileId = current(bx_srv('system', 'get_options_agents_profile', [false], 'TemplServices'))['key'];
  167. $aValsToAdd['profile_id'] = $iProfileId;
  168. }
  169. $iModel = $oForm->getCleanValue('model_id');
  170. $sTrigger = $oForm->getCleanValue('trigger');
  171. $sTools = is_array($oForm->getCleanValue('tools')) ? implode(',', $oForm->getCleanValue('tools')) : '';
  172. $aValsToAdd['tools'] = $sTools;
  173. $aValsToAdd['acl_levels'] = (int)$oForm->getCleanValue('acl_levels');
  174. $bIsValid = true;
  175. if($bIsValid) {
  176. if(($iId = $oForm->update($iId, $aValsToAdd)) !== false) {
  177. $this->_oDb->cleanCache('sys_agents_with_alert');
  178. $aRes = ['grid' => $this->getCode(false), 'blink' => $iId];
  179. }
  180. else
  181. $aRes = ['msg' => _t('_sys_txt_error_occured')];
  182. return echoJson($aRes);
  183. }
  184. }
  185. $sFormId = $oForm->getId();
  186. $sContent = BxTemplStudioFunctions::getInstance()->popupBox($sFormId . '_popup', _t('_sys_agents_agents_popup_edit', $aAgent['name']), $this->_oTemplate->parseHtmlByName('agents_agents_form.html', [
  187. 'form_id' => $sFormId,
  188. 'form' => $oForm->getCode(true),
  189. 'object' => $this->_sObject,
  190. 'action' => $sAction
  191. ]));
  192. return echoJson(['popup' => ['html' => $sContent, 'options' => ['closeOnOuterClick' => false]]]);
  193. }
  194. public function performActionLogs()
  195. {
  196. $iId = $this->_getId();
  197. $aAgent = BxDolAiQuery::getAgentObject($iId);
  198. if (!$aAgent) {
  199. echoJson(['msg' => _t('_sys_txt_error_occured')]);
  200. return;
  201. }
  202. $oGrid = BxDolGrid::getObjectInstance('sys_studio_agents_logs');
  203. $oGrid->addMarkers(['agent_id' => $iId]);
  204. $oGrid->setBrowseParams(['agent_id' => $iId]);
  205. $sGrid = $oGrid->getCode();
  206. $sContent = BxTemplStudioFunctions::getInstance()->popupBox('popup_files_' . $iId, _t('_sys_agents_logs_popup', $aAgent['name']), $this->_oTemplate->parseHtmlByName('agents_popup_grid.html', [
  207. 'grid' => $sGrid,
  208. ]));
  209. return echoJson(['popup' => ['html' => $sContent, 'options' => ['closeOnOuterClick' => false]]]);
  210. }
  211. public function performActionMessage()
  212. {
  213. $iId = $this->_getId();
  214. $aAgent = BxDolAiQuery::getAgentObject($iId);
  215. if (!$aAgent) {
  216. echoJson(['msg' => _t('_sys_txt_error_occured')]);
  217. return;
  218. }
  219. if (!$aAgent['active']) {
  220. echoJson(['msg' => _t('_sys_txt_agent_inactive')]);
  221. return;
  222. }
  223. $sChatId = 'bx-ai-chat-' . $iId;
  224. $sName = !empty($aAgent['title']) ? $aAgent['title'] : $aAgent['name'];
  225. $aThreadsTpl = [];
  226. $oChat = BxDolAiChat::getInstance();
  227. $aThreads = $oChat->listAgentChatThreads($aAgent);
  228. foreach ($aThreads as $aThread) {
  229. $aThreadsTpl[] = [
  230. 'thread_id' => bx_html_attribute($aThread['thread_id']),
  231. 'writable' => (int)$aThread['writable'],
  232. 'context_pid' => (int)$aThread['context_pid'],
  233. 'title' => bx_process_output($aThread['title']),
  234. 'meta' => bx_process_output($aThread['meta']),
  235. 'class_mine' => $aThread['class_mine'],
  236. ];
  237. }
  238. $sContent = BxTemplStudioFunctions::getInstance()->popupBox('popup_agent_chat_' . $iId, _t('_sys_agents_agents_popup_message', $sName), $this->_oTemplate->parseHtmlByName('agents_popup_chat.html', [
  239. 'chat_id' => $sChatId,
  240. 'agent_id' => (int)$iId,
  241. 'txt_readonly' => _t('_sys_agents_agents_txt_readonly'),
  242. 'txt_chats' => _t('_sys_agents_agents_txt_chats'),
  243. 'txt_search' => bx_html_attribute(_t('_sys_agents_agents_txt_search')),
  244. 'txt_search_empty' => _t('_sys_agents_agents_txt_search_empty'),
  245. 'bx_repeat:threads' => $aThreadsTpl,
  246. ]));
  247. $aThreadsJs = [];
  248. foreach ($aThreads as $aThread)
  249. $aThreadsJs[] = $this->_agentChatThreadJs($aThread);
  250. $sThreadsJson = json_encode($aThreadsJs, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT);
  251. if ($sThreadsJson === false)
  252. $sThreadsJson = '[]';
  253. $sJsObject = $this->getPageJsObject();
  254. return echoJson(['popup' => [
  255. 'html' => $sContent,
  256. 'options' => [
  257. 'closeOnOuterClick' => false,
  258. 'onShow' => $sJsObject . ".initAgentChat('#" . $sChatId . "', " . (int)$iId . ", " . $sThreadsJson . ");",
  259. 'onHide' => $sJsObject . ".destroyAgentChat();",
  260. ]
  261. ]]);
  262. }
  263. public function performActionGetChatThreads()
  264. {
  265. $iId = $this->_getId();
  266. $aAgent = BxDolAiQuery::getAgentObject($iId);
  267. if (!$aAgent) {
  268. echoJson(['code' => 404, 'threads' => []]);
  269. return;
  270. }
  271. $aThreadsJs = [];
  272. $aThreads = BxDolAiChat::getInstance()->listAgentChatThreads($aAgent);
  273. foreach ($aThreads as $aThread)
  274. $aThreadsJs[] = $this->_agentChatThreadJs($aThread);
  275. echoJson(['code' => 200, 'threads' => $aThreadsJs]);
  276. }
  277. public function performActionGetChatThread()
  278. {
  279. $iId = $this->_getId();
  280. $aAgent = BxDolAiQuery::getAgentObject($iId);
  281. if (!$aAgent) {
  282. echoJson(['code' => 404, 'msg' => _t('_sys_txt_error_occured'), 'messages' => []]);
  283. return;
  284. }
  285. $sThreadId = trim((string)bx_get('thread_id'));
  286. $oChat = BxDolAiChat::getInstance();
  287. $aMessages = $oChat->getChatHistoryUiMessagesByThread($aAgent, $sThreadId);
  288. if ($aMessages === false) {
  289. echoJson(['code' => 404, 'msg' => _t('_sys_txt_error_occured'), 'messages' => []]);
  290. return;
  291. }
  292. echoJson([
  293. 'code' => 200,
  294. 'messages' => $aMessages,
  295. 'writable' => $oChat->isOwnAgentChatThread($aAgent, $sThreadId) ? 1 : 0,
  296. 'artifacts' => $oChat->getChatHistoryArtifactsByThread($aAgent, $sThreadId),
  297. ]);
  298. }
  299. protected function _agentChatThreadJs($aThread)
  300. {
  301. $aArtifacts = [];
  302. if (!empty($aThread['artifacts']) && is_array($aThread['artifacts'])) {
  303. foreach ($aThread['artifacts'] as $aItem) {
  304. if (!is_array($aItem))
  305. continue;
  306. $aArtifacts[] = [
  307. 'field_name' => (string)($aItem['field_name'] ?? ''),
  308. 'field_value' => (string)($aItem['field_value'] ?? ''),
  309. ];
  310. }
  311. }
  312. return [
  313. 'thread_id' => (string)$aThread['thread_id'],
  314. 'writable' => (int)$aThread['writable'],
  315. 'context_pid' => (int)$aThread['context_pid'],
  316. 'title' => (string)$aThread['title'],
  317. 'meta' => (string)$aThread['meta'],
  318. 'status' => (string)($aThread['status'] ?? 'opened'),
  319. 'created_at' => (string)($aThread['created_at'] ?? ''),
  320. 'updated_at' => (string)($aThread['updated_at'] ?? ''),
  321. 'artifacts' => $aArtifacts,
  322. 'messages' => (!empty($aThread['messages']) && is_array($aThread['messages'])) ? array_values($aThread['messages']) : [],
  323. ];
  324. }
  325. protected function _getCellProfileId($mixedValue, $sKey, $aField, $aRow)
  326. {
  327. $mixedValue = BxDolProfile::getInstanceMagic($mixedValue)->getUnit(0, ['template' => 'unit_wo_info']);
  328. return parent::_getCellDefault($mixedValue, $sKey, $aField, $aRow);
  329. }
  330. protected function _getCellIcon($mixedValue, $sKey, $aField, $aRow)
  331. {
  332. $sIcon = '';
  333. if($mixedValue) {
  334. list($sIcon, $sIconUrl, $sIconA, $sIconHtml, $sIconFontWithHtml) = $this->_oTemplate->getTemplateFunctions()->getIcon($mixedValue, ['class' => 'sys-colored']);
  335. if($sIcon)
  336. $sIcon = $this->_oTemplate->parseIcon(BxDolIconset::getObjectInstance()->getIcon($sIcon));
  337. else if($sIconHtml)
  338. $sIcon = $sIconHtml;
  339. else if($sIconUrl)
  340. $sIcon = '<img src="' . bx_html_attribute($sIconUrl) . '" />';
  341. else if($sIconFontWithHtml)
  342. $sIcon = $sIconFontWithHtml;
  343. }
  344. if (!$sIcon)
  345. $sIcon = '<i class="sys-icon robot"></i>';
  346. return parent::_getCellDefault($sIcon, $sKey, $aField, $aRow);
  347. }
  348. protected function _getCellModelId($mixedValue, $sKey, $aField, $aRow)
  349. {
  350. $aModel = $this->_oDb->getModelsBy(['sample' => 'id', 'id' => $mixedValue]);
  351. if(!empty($aModel) && is_array($aModel)) {
  352. $mixedValue = $aModel['icon'];
  353. if (strpos($mixedValue, '.svg') !== false)
  354. $mixedValue = $this->_oTemplate->getIconContent($mixedValue);
  355. } else {
  356. $mixedValue = '';
  357. }
  358. return parent::_getCellDefault($mixedValue, $sKey, $aField, $aRow);
  359. }
  360. protected function _getCellTrigger($mixedValue, $sKey, $aField, $aRow)
  361. {
  362. $mixedValue = $this->_oTemplate->getIconContent('agt-trg-' . $mixedValue . '.svg');
  363. return parent::_getCellDefault($mixedValue, $sKey, $aField, $aRow);
  364. }
  365. protected function _getCellName($mixedValue, $sKey, $aField, $aRow)
  366. {
  367. if (!empty($aRow['title']))
  368. $mixedValue = $aRow['title'];
  369. return parent::_getCellDefault($mixedValue, $sKey, $aField, $aRow);
  370. }
  371. protected function _delete ($mixedId)
  372. {
  373. $mixedResult = parent::_delete($mixedId);
  374. $this->_oDb->cleanCache('sys_agents_with_alert');
  375. if ($mixedResult)
  376. BxDolAiActivity::deleteForAgent((int)$mixedId);
  377. return $mixedResult;
  378. }
  379. protected function _getFormEdit($sAction, $aAgent = [])
  380. {
  381. $aForm = $this->_getForm($sAction, $aAgent);
  382. $aForm['form_attrs']['action'] .= '&id=' . $aAgent['id'];
  383. unset($aForm['inputs']['name']);
  384. return $aForm;
  385. }
  386. protected function _getForm($sAction, $aAgent = [])
  387. {
  388. $sJsObject = $this->getPageJsObject();
  389. $aForm = array(
  390. 'form_attrs' => array(
  391. 'id' => 'bx_std_agents_' . $sAction,
  392. 'action' => BX_DOL_URL_ROOT . 'grid.php?o=sys_studio_agents_agents&a=' . $sAction,
  393. 'method' => 'post',
  394. ),
  395. 'params' => array (
  396. 'db' => array(
  397. 'table' => 'sys_agents_agents',
  398. 'key' => 'id',
  399. 'submit_name' => 'do_submit',
  400. ),
  401. ),
  402. 'inputs' => array(
  403. 'title' => [
  404. 'type' => 'text',
  405. 'name' => 'title',
  406. 'caption' => _t('_sys_agents_field_title'),
  407. 'info' => _t('_sys_agents_field_title_info'),
  408. 'value' => $aAgent['title'] ?? '',
  409. 'required' => '1',
  410. 'checker' => [
  411. 'func' => 'Avail',
  412. 'error' => _t('_sys_agents_form_field_err_enter'),
  413. ],
  414. 'db' => [
  415. 'pass' => 'Xss',
  416. ],
  417. ],
  418. 'name' => [
  419. 'type' => 'text',
  420. 'name' => 'name',
  421. 'caption' => _t('_sys_agents_field_name'),
  422. 'info' => _t('_sys_agents_field_name_info'),
  423. 'value' => isset($aAgent['name']) ? $aAgent['name'] : '',
  424. 'required' => '1',
  425. 'checker' => [
  426. 'func' => 'Avail',
  427. 'error' => _t('_sys_agents_form_field_err_enter'),
  428. ],
  429. 'db' => [
  430. 'pass' => 'Xss',
  431. ],
  432. ],
  433. 'description' => [
  434. 'type' => 'textarea',
  435. 'name' => 'description',
  436. 'caption' => _t('_sys_agents_field_description'),
  437. 'info' => _t('_sys_agents_field_description_info'),
  438. 'value' => $aAgent['description'] ?? '',
  439. 'db' => [
  440. 'pass' => 'Xss',
  441. ],
  442. ],
  443. 'icon' => [
  444. 'type' => 'textarea',
  445. 'name' => 'icon',
  446. 'caption' => _t('_sys_agents_field_icon'),
  447. 'info' => _t('_sys_agents_field_icon_info'),
  448. 'value' => $aAgent['icon'] ?? '',
  449. 'code' => 1,
  450. 'db' => [
  451. 'pass' => 'Xss',
  452. ],
  453. ],
  454. 'model_id' => [
  455. 'type' => 'select',
  456. 'name' => 'model_id',
  457. 'caption' => _t('_sys_agents_field_model_id'),
  458. 'info' => _t('_sys_agents_field_model_id_info'),
  459. 'value' => isset($aAgent['model_id']) ? $aAgent['model_id'] : 0,
  460. 'values' => $this->_getModelSelectValues(),
  461. 'required' => '1',
  462. 'checker' => [
  463. 'func' => 'Avail',
  464. 'error' => _t('_sys_agents_form_field_err_select'),
  465. ],
  466. 'db' => [
  467. 'pass' => 'Int',
  468. ],
  469. ],
  470. 'profile_id' => [
  471. 'type' => 'select',
  472. 'name' => 'profile_id',
  473. 'caption' => _t('_sys_agents_field_profile_id'),
  474. 'info' => _t('_sys_agents_field_profile_id_inf'),
  475. 'value' => isset($aAgent['profile_id']) ? $aAgent['profile_id'] : 0,
  476. 'values' => $this->_getProfileSelectValues(),
  477. 'required' => '1',
  478. 'required' => '1',
  479. 'checker' => [
  480. 'func' => 'Avail',
  481. 'error' => _t('_sys_agents_form_field_err_select'),
  482. ],
  483. 'db' => [
  484. 'pass' => 'Int',
  485. ]
  486. ],
  487. 'acl_levels' => [
  488. 'type' => 'checkbox_set',
  489. 'name' => 'acl_levels',
  490. 'caption' => _t('_sys_agents_field_acl_levels'),
  491. 'info' => _t('_sys_agents_field_acl_levels_info'),
  492. 'value' => [],
  493. 'values' => [],
  494. 'db' => [
  495. 'pass' => 'Set',
  496. ]
  497. ],
  498. 'trigger' => [
  499. 'type' => 'select',
  500. 'name' => 'trigger',
  501. 'caption' => _t('_sys_agents_field_trigger'),
  502. 'info' => _t('_sys_agents_field_trigger_info'),
  503. 'value' => isset($aAgent['trigger']) ? $aAgent['trigger'] : 0,
  504. 'values' => [
  505. 'alert' => _t('_sys_agents_field_trigger_alert'),
  506. 'scheduler' => _t('_sys_agents_field_trigger_scheduler'),
  507. 'webhook' => _t('_sys_agents_field_trigger_webhook'),
  508. 'manual' => _t('_sys_agents_field_trigger_manual'),
  509. 'agent' => _t('_sys_agents_field_trigger_agent'),
  510. 'message' => _t('_sys_agents_field_trigger_message'),
  511. 'form-input' => _t('_sys_agents_field_trigger_form_input'),
  512. ],
  513. // 'attrs' => [
  514. // 'onchange' => $this->getPageJsObject() . '.onChangeAgentTrigger(this)',
  515. // ],
  516. 'required' => '1',
  517. 'db' => [
  518. 'pass' => 'Xss',
  519. ]
  520. ],
  521. 'async' => [
  522. 'type' => 'checkbox',
  523. 'name' => 'async',
  524. 'caption' => _t('_sys_agents_field_async'),
  525. 'info' => _t('_sys_agents_field_async_inf'),
  526. 'value' => 1,
  527. 'checked' => isset($aAgent['async']) ? $aAgent['async'] : 0,
  528. 'db' => [
  529. 'pass' => 'Int',
  530. ]
  531. ],
  532. 'alert_section' => [
  533. 'type' => 'block_header',
  534. 'caption' => _t('_sys_agents_block_header_alert'),
  535. 'collapsable' => true,
  536. 'collapsed' => true,
  537. ],
  538. 'alert_sample' => [
  539. 'type' => 'custom',
  540. 'name' => 'alert_sample',
  541. 'caption' => _t('_sys_agents_field_alert_sample'),
  542. 'content' => $this->_oTemplate->parseHtmlByName('agents_agents_alerts_payload.html', [
  543. 'text-visibility' => empty($aAgent['alert']) ? 'block' : 'none',
  544. 'text' => _t('_sys_agents_waiting_for_sample_data_alert'),
  545. 'payload-visibility' => !empty($aAgent['alert']) ? 'block' : 'none',
  546. 'desc' => $aAgent ? $this->_oDb->getAlertDesc($aAgent['alert']) : '',
  547. 'payload' => !empty($aAgent['alert']) ? json_encode($this->_getAlertPayload($aAgent['alert']), JSON_PRETTY_PRINT) : '',
  548. ]),
  549. ],
  550. 'alert' => [
  551. 'type' => 'custom',
  552. 'name' => 'alert',
  553. 'caption' => _t('_sys_agents_field_alert'),
  554. 'info' => _t('_sys_agents_field_alert_info'),
  555. 'content' => $this->_oTemplate->parseHtmlByName('agents_agents_alerts_select.html', $this->_getAlertValues(isset($aAgent['alert']) ? $aAgent['alert'] : '')),
  556. 'db' => [
  557. 'pass' => 'Xss',
  558. ],
  559. ],
  560. 'alert_section_end' => [
  561. 'type' => 'block_end',
  562. ],
  563. 'scheduler_section' => [
  564. 'type' => 'block_header',
  565. 'caption' => _t('_sys_agents_block_header_scheduler'),
  566. 'collapsable' => true,
  567. 'collapsed' => true,
  568. ],
  569. 'scheduler_cron' => [
  570. 'type' => 'text',
  571. 'name' => 'scheduler_cron',
  572. 'caption' => _t('_sys_agents_field_scheduler_cron'),
  573. 'info' => _t('_sys_agents_field_scheduler_cron_info'),
  574. 'value' => isset($aAgent['scheduler_cron']) ? $aAgent['scheduler_cron'] : '',
  575. 'db' => [
  576. 'pass' => 'Xss',
  577. ],
  578. ],
  579. 'scheduler_section_end' => [
  580. 'type' => 'block_end',
  581. ],
  582. 'webhook_section' => [
  583. 'type' => 'block_header',
  584. 'caption' => _t('_sys_agents_block_header_webhook'),
  585. 'collapsable' => true,
  586. 'collapsed' => true,
  587. ],
  588. 'webhook_sample' => [
  589. 'type' => 'custom',
  590. 'name' => 'webhook_sample',
  591. 'caption' => _t('_sys_agents_field_webhook_sample'),
  592. 'content' => isset($aAgent['webhook_sample']) ? $aAgent['webhook_sample'] : _t('_sys_agents_waiting_for_sample_data_webhook'),
  593. ],
  594. 'webhook_key' => [
  595. 'type' => 'text',
  596. 'name' => 'webhook_key',
  597. 'caption' => _t('_sys_agents_field_webhook_key'),
  598. 'info' => _t('_sys_agents_field_webhook_key_info'),
  599. 'value' => isset($aAgent['webhook_key']) ? $aAgent['webhook_key'] : '',
  600. 'db' => [
  601. 'pass' => 'Xss',
  602. ],
  603. ],
  604. 'webhook_section_end' => [
  605. 'type' => 'block_end',
  606. ],
  607. 'message_section' => [
  608. 'type' => 'block_header',
  609. 'caption' => _t('_sys_agents_block_header_message'),
  610. 'collapsable' => true,
  611. 'collapsed' => true,
  612. ],
  613. 'message_profile_id' => [
  614. 'type' => 'select',
  615. 'name' => 'message_profile_id',
  616. 'caption' => _t('_sys_agents_field_message_profile'),
  617. 'info' => _t('_sys_agents_field_message_profile_info'),
  618. 'value' => isset($aAgent['message_profile_id']) ? $aAgent['message_profile_id'] : '',
  619. 'values' => $this->_getProfileSelectValues(true, '_adm_nav_txt_items_visible_for_all'),
  620. 'db' => [
  621. 'pass' => 'Xss',
  622. ],
  623. ],
  624. 'message_section_end' => [
  625. 'type' => 'block_end',
  626. ],
  627. 'form_field_section' => [
  628. 'type' => 'block_header',
  629. 'caption' => _t('_sys_agents_block_header_form_input'),
  630. 'collapsable' => true,
  631. 'collapsed' => true,
  632. ],
  633. 'form_object' => [
  634. 'type' => 'custom',
  635. 'name' => 'form_object',
  636. 'caption' => _t('_sys_agents_form_object'),
  637. 'info' => _t('_sys_agents_form_object_info'),
  638. 'content' => $this->_oTemplate->parseHtmlByName('agents_agents_form_object_select.html', $this->_getFormObjectValues(isset($aAgent['form_object']) ? $aAgent['form_object'] : '')),
  639. 'db' => [
  640. 'pass' => 'Xss',
  641. ],
  642. ],
  643. 'form_input' => [
  644. 'type' => 'custom',
  645. 'name' => 'form_input',
  646. 'caption' => _t('_sys_agents_form_input'),
  647. 'info' => _t('_sys_agents_form_input_info'),
  648. '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'] : '')),
  649. 'db' => [
  650. 'pass' => 'Xss',
  651. ],
  652. ],
  653. 'form_field_section_end' => array(
  654. 'type' => 'block_end',
  655. ),
  656. 'manual_section' => [
  657. 'type' => 'block_header',
  658. 'caption' => _t('_sys_agents_block_header_manual'),
  659. 'collapsable' => true,
  660. 'collapsed' => true,
  661. ],
  662. 'max_turns' => [
  663. 'type' => 'text',
  664. 'name' => 'max_turns',
  665. 'caption' => _t('_sys_agents_field_manual_max_turns'),
  666. 'info' => _t('_sys_agents_field_manual_max_turns_info'),
  667. 'value' => $aAgent['max_turns'] ?? 0,
  668. 'required' => '1',
  669. 'db' => [
  670. 'pass' => 'Int',
  671. ],
  672. ],
  673. 'chat_ttl_min' => [
  674. 'type' => 'text',
  675. 'name' => 'chat_ttl_min',
  676. 'caption' => _t('_sys_agents_field_manual_chat_ttl_min'),
  677. 'info' => _t('_sys_agents_field_manual_chat_ttl_min_info'),
  678. 'value' => $aAgent['chat_ttl_min'] ?? 0,
  679. 'required' => '1',
  680. 'db' => [
  681. 'pass' => 'Int',
  682. ],
  683. ],
  684. 'limit_message' => [
  685. 'type' => 'textarea',
  686. 'name' => 'limit_message',
  687. 'caption' => _t('_sys_agents_field_manual_limit_message'),
  688. 'info' => _t('_sys_agents_field_manual_limit_message_info'),
  689. 'value' => $aAgent['limit_message'] ?? '',
  690. 'db' => [
  691. 'pass' => 'Xss',
  692. ],
  693. ],
  694. 'max_input_chars' => [
  695. 'type' => 'text',
  696. 'name' => 'max_input_chars',
  697. 'caption' => _t('_sys_agents_field_manual_max_input_chars'),
  698. 'info' => _t('_sys_agents_field_manual_max_input_chars_info'),
  699. 'value' => $aAgent['max_input_chars'] ?? 0,
  700. 'required' => '1',
  701. 'db' => [
  702. 'pass' => 'Int',
  703. ],
  704. ],
  705. 'max_tokens' => [
  706. 'type' => 'text',
  707. 'name' => 'max_tokens',
  708. 'caption' => _t('_sys_agents_field_manual_max_tokens'),
  709. 'info' => _t('_sys_agents_field_manual_max_tokens_info'),
  710. 'value' => $aAgent['max_tokens'] ?? 0,
  711. 'required' => '1',
  712. 'db' => [
  713. 'pass' => 'Int',
  714. ],
  715. ],
  716. 'max_sessions_per_hour' => [
  717. 'type' => 'text',
  718. 'name' => 'max_sessions_per_hour',
  719. 'caption' => _t('_sys_agents_field_manual_max_sessions_per_hour'),
  720. 'info' => _t('_sys_agents_field_manual_max_sessions_per_hour_info'),
  721. 'value' => $aAgent['max_sessions_per_hour'] ?? 3,
  722. 'required' => '1',
  723. 'db' => [
  724. 'pass' => 'Int',
  725. ],
  726. ],
  727. 'max_sessions_per_day' => [
  728. 'type' => 'text',
  729. 'name' => 'max_sessions_per_day',
  730. 'caption' => _t('_sys_agents_field_manual_max_sessions_per_day'),
  731. 'info' => _t('_sys_agents_field_manual_max_sessions_per_day_info'),
  732. 'value' => $aAgent['max_sessions_per_day'] ?? 10,
  733. 'required' => '1',
  734. 'db' => [
  735. 'pass' => 'Int',
  736. ],
  737. ],
  738. 'hidden_first_message' => [
  739. 'type' => 'text',
  740. 'name' => 'hidden_first_message',
  741. 'caption' => _t('_sys_agents_field_manual_hidden_first_message'),
  742. 'info' => _t('_sys_agents_field_manual_hidden_first_message_info'),
  743. 'value' => $aAgent['hidden_first_message'] ?? '',
  744. 'attrs' => ['maxlength' => 64],
  745. 'db' => [
  746. 'pass' => 'Xss',
  747. ],
  748. ],
  749. 'manual_section_end' => [
  750. 'type' => 'block_end',
  751. ],
  752. 'vector_store_id' => [
  753. 'type' => 'select',
  754. 'name' => 'vector_store_id',
  755. 'caption' => _t('_sys_agents_field_vector_store_id'),
  756. 'info' => _t('_sys_agents_field_vector_store_id_info'),
  757. 'value' => isset($aAgent['vector_store_id']) ? $aAgent['vector_store_id'] : 0,
  758. 'values' => $this->_oDb->getVectorStores(),
  759. 'required' => '1',
  760. 'checker' => [
  761. 'func' => 'Avail',
  762. 'error' => _t('_sys_agents_form_field_err_select'),
  763. ],
  764. 'db' => [
  765. 'pass' => 'Xss',
  766. ],
  767. ],
  768. 'chat_history_context' => [
  769. 'type' => 'text',
  770. 'name' => 'chat_history_context',
  771. 'caption' => _t('_sys_agents_field_chat_history_context'),
  772. 'info' => _t('_sys_agents_field_chat_history_context_info'),
  773. 'value' => isset($aAgent['chat_history_context']) ? $aAgent['chat_history_context'] : 50000,
  774. 'db' => [
  775. 'pass' => 'Int',
  776. ],
  777. ],
  778. 'tools' => [
  779. 'type' => 'custom',
  780. 'name' => 'tools',
  781. 'caption' => _t('_sys_agents_field_tools'),
  782. 'info' => _t('_sys_agents_field_tools_info'),
  783. 'value' => '',
  784. ],
  785. 'tools_max_run' => [
  786. 'type' => 'text',
  787. 'name' => 'tools_max_run',
  788. 'caption' => _t('_sys_agents_field_tools_max_run'),
  789. 'info' => _t('_sys_agents_field_tools_max_run_info'),
  790. 'value' => isset($aAgent['tools_max_run']) ? $aAgent['tools_max_run'] : '10',
  791. 'required' => '1',
  792. 'db' => [
  793. 'pass' => 'Int',
  794. ],
  795. ],
  796. 'prompt_system' => [
  797. 'type' => 'textarea',
  798. 'name' => 'prompt_system',
  799. 'caption' => _t('_sys_agents_field_prompt_system'),
  800. 'info' => _t('_sys_agents_field_prompt_system_info'),
  801. 'value' => isset($aAgent['prompt_system']) ? $aAgent['prompt_system'] : '',
  802. 'db' => [
  803. 'pass' => 'Xss',
  804. ],
  805. ],
  806. 'prompts_section' => array(
  807. 'type' => 'block_header',
  808. 'caption' => 'Other prompts',
  809. 'collapsable' => true,
  810. 'collapsed' => true,
  811. ),
  812. 'prompt_steps' => [
  813. 'type' => 'textarea',
  814. 'name' => 'prompt_steps',
  815. 'caption' => _t('_sys_agents_field_prompt_steps'),
  816. 'info' => _t('_sys_agents_field_prompt_steps_info'),
  817. 'value' => isset($aAgent['prompt_steps']) ? $aAgent['prompt_steps'] : '',
  818. 'db' => [
  819. 'pass' => 'Xss',
  820. ],
  821. ],
  822. 'prompt_output' => [
  823. 'type' => 'textarea',
  824. 'name' => 'prompt_output',
  825. 'caption' => _t('_sys_agents_field_prompt_output'),
  826. 'info' => _t('_sys_agents_field_prompt_output_info'),
  827. 'value' => isset($aAgent['prompt_output']) ? $aAgent['prompt_output'] : '',
  828. 'db' => [
  829. 'pass' => 'Xss',
  830. ],
  831. ],
  832. 'prompt_tools' => [
  833. 'type' => 'textarea',
  834. 'name' => 'prompt_tools',
  835. 'caption' => _t('_sys_agents_field_prompt_tools'),
  836. 'info' => _t('_sys_agents_field_prompt_tools_info'),
  837. 'value' => isset($aAgent['prompt_tools']) ? $aAgent['prompt_tools'] : '',
  838. 'db' => [
  839. 'pass' => 'Xss',
  840. ],
  841. ],
  842. 'prompts_section_end' => array(
  843. 'type' => 'block_end',
  844. ),
  845. 'submit' => $this->_getFormControls(),
  846. ),
  847. );
  848. if(($sFldTitle = 'title') && ($sFldName = 'name') && isset($aForm['inputs'][$sFldTitle], $aForm['inputs'][$sFldName])) {
  849. $aMask = array('mask' => "javascript:%s.agentCheckName(this, '%s', '%s');", $sJsObject, 'title', 'name');
  850. if($sAction == 'edit' && ($iAgentId = $aAgent['id'] ?? false)) {
  851. $aMask['mask'] = "javascript:%s.agentCheckName(this, '%s', '%s', %d);";
  852. $aMask[] = (int)$iAgentId;
  853. }
  854. $sOnBlur = call_user_func_array('sprintf', array_values($aMask));
  855. $aForm['inputs'][$sFldTitle]['attrs']['onblur'] = $sOnBlur;
  856. $aForm['inputs'][$sFldName]['attrs']['onblur'] = $sOnBlur;
  857. }
  858. $this->_getMultiField('tools', $aAgent, 'getTools', 'toolAdd', 'agents_agents_form_tools.html', $aForm);
  859. BxDolStudioUtils::getVisibilityValues(0, $aForm['inputs']['acl_levels']['values'], $aForm['inputs']['acl_levels']['value']);
  860. $aForm['inputs']['acl_levels']['value'] = (int)($aAgent['acl_levels'] ?? 0);
  861. return $aForm;
  862. }
  863. protected function _getAlertPayload($s)
  864. {
  865. $aAlert = $this->_oDb->getAlert($s);
  866. if (!$aAlert)
  867. return '';
  868. return [
  869. 'object_id' => $aAlert['object'],
  870. 'sender_profile_id' => $aAlert['sender'],
  871. 'extra' => json_decode($aAlert['extra'], true),
  872. 'extra_modifiable_keys' => json_decode($aAlert['extra_refs'], true),
  873. ];
  874. }
  875. protected function _getAlertValues($sValue)
  876. {
  877. $aAlerts = $this->_oDb->getAlerts();
  878. $a = [
  879. 'sys_stat_not_available' => _t('_sys_not_available'),
  880. 'grid_object' => $this->_sObject,
  881. 'bx_repeat:alerts' => [
  882. [
  883. 'name' => _t('_sys_please_select'),
  884. 'value' => '',
  885. 'desc' => '',
  886. 'count' => 0,
  887. 'count_per_req' => 0,
  888. 'bx_if:sel' => [
  889. 'condition' => false,
  890. 'content' => ['sel' => '']
  891. ]
  892. ]
  893. ]
  894. ];
  895. foreach ($aAlerts as $k => $r) {
  896. $a['bx_repeat:alerts'][] = [
  897. 'name' => $r['name'],
  898. 'value' => $r['key'],
  899. 'desc' => bx_html_attribute($r['desc']),
  900. 'count' => bx_html_attribute(_t('_sys_agents_count_today', $r['counter_24h'])),
  901. 'count_per_req' => bx_html_attribute(_t('_sys_agents_count_per_req', $r['counter_per_request'])),
  902. 'bx_if:sel' => [
  903. 'condition' => $sValue == $r['key'],
  904. 'content' => [
  905. 'sel' => $sValue == $r['key'] ? 'selected' : '',
  906. ]
  907. ]
  908. ];
  909. }
  910. return $a;
  911. }
  912. protected function _getFormObjectValues($sValue)
  913. {
  914. $aFormObjects = $this->_oDb->getFormObjects();
  915. // add "Please select" option
  916. $a = [
  917. 'sys_stat_not_available' => _t('_sys_not_available'),
  918. 'grid_object' => $this->_sObject,
  919. 'bx_repeat:form_objects' => [
  920. [
  921. 'title' => _t('_sys_please_select'),
  922. 'title_attr' => _t('_sys_please_select'),
  923. 'value' => '',
  924. 'bx_if:sel' => [
  925. 'condition' => false,
  926. 'content' => ['sel' => '']
  927. ]
  928. ]
  929. ]
  930. ];
  931. // add form objects
  932. $bSelected = false;
  933. foreach ($aFormObjects as $k => $r) {
  934. if ($sValue == $r['form_object'])
  935. $bSelected = true;
  936. $a['bx_repeat:form_objects'][] = [
  937. 'title' => $r['module_title'] . ': ' . $r['form_title'],
  938. 'title_attr' => bx_html_attribute($r['module_title'] . ': ' . $r['form_title']),
  939. 'value' => $r['form_object'],
  940. // 'form_id' => $r['form_id'],
  941. // 'module' => $r['module'],
  942. // 'module_title' => $r['module_title'],
  943. // 'form_title' => $r['form_title'],
  944. 'bx_if:sel' => [
  945. 'condition' => $sValue == $r['form_object'],
  946. 'content' => ['sel' => $sValue == $r['form_object'] ? 'selected' : ''],
  947. ]
  948. ];
  949. }
  950. // add selected form object if not found in form objects
  951. if ($sValue && !$bSelected) {
  952. $a['bx_repeat:form_objects'][] = [
  953. 'title' => $sValue,
  954. 'title_attr' => bx_html_attribute($sValue),
  955. 'value' => $sValue,
  956. 'bx_if:sel' => [
  957. 'condition' => true,
  958. 'content' => ['sel' => 'selected'],
  959. ]
  960. ];
  961. }
  962. return $a;
  963. }
  964. protected function _getFormInputs($sFormObject)
  965. {
  966. $sDisplay = $this->_oDb->getFormDisplay($sFormObject);
  967. $oForm = $sDisplay ? BxDolForm::getObjectInstance($sFormObject, $sDisplay) : null;
  968. $aFormInputs = $oForm ? $oForm->aInputs : [];
  969. if (!$aFormInputs)
  970. return [];
  971. $aRet = [];
  972. foreach ($aFormInputs as $k => $r) {
  973. if ($r['type'] == 'text' || $r['type'] == 'textarea') {
  974. $aRet[$r['name']] = [
  975. 'name' => $r['name'],
  976. 'caption' => $r['caption'],
  977. ];
  978. }
  979. }
  980. return $aRet;
  981. }
  982. protected function _getFormInputValues($sFormObject, $sFormInput)
  983. {
  984. $aFormInputs = $this->_getFormInputs($sFormObject);
  985. // add "Please select" option
  986. $a = [
  987. 'bx_repeat:form_inputs' => [
  988. [
  989. 'title' => _t('_sys_please_select'),
  990. 'title_attr' => _t('_sys_please_select'),
  991. 'value' => '',
  992. 'bx_if:sel' => [
  993. 'condition' => false,
  994. 'content' => ['sel' => '']
  995. ]
  996. ]
  997. ]
  998. ];
  999. // add form inputs
  1000. $bSelected = false;
  1001. if ($aFormInputs) {
  1002. foreach ($aFormInputs as $k => $r) {
  1003. if ($sFormInput == $r['name'])
  1004. $bSelected = true;
  1005. $a['bx_repeat:form_inputs'][] = [
  1006. 'title' => $r['name'] . ' - ' . $r['caption'],
  1007. 'title_attr' => bx_html_attribute($r['name'] . (!empty($r['caption']) ? ' - ' . $r['caption'] : '')),
  1008. 'value' => $r['name'],
  1009. 'bx_if:sel' => [
  1010. 'condition' => $sFormInput == $r['name'],
  1011. 'content' => [
  1012. 'sel' => $sFormInput == $r['name'] ? 'selected' : '',
  1013. ]
  1014. ]
  1015. ];
  1016. }
  1017. }
  1018. // add selected input if not found in form inputs
  1019. if ($sFormInput && !$bSelected) {
  1020. $a['bx_repeat:form_inputs'][] = [
  1021. 'title' => $sFormInput,
  1022. 'title_attr' => bx_html_attribute($sFormInput),
  1023. 'value' => $sFormInput,
  1024. 'bx_if:sel' => [
  1025. 'condition' => true,
  1026. 'content' => ['sel' => 'selected'],
  1027. ]
  1028. ];
  1029. }
  1030. return $a;
  1031. }
  1032. protected function _getUniqName($sName)
  1033. {
  1034. return uriGenerate($sName, 'sys_agents_agents', 'name', ['lowercase' => false]);
  1035. }
  1036. protected function _getMultiField($sField, $aAgent, $sGetValuesMethod, $sJsAddMethod, $sTemplateName, &$aForm)
  1037. {
  1038. if(!isset($aForm['inputs']['tools']))
  1039. return;
  1040. $sJsObject = $this->getPageJsObject();
  1041. $oForm = new BxTemplFormView([]);
  1042. $aValues = ['0' => _t('_sys_please_select')];
  1043. $a = $this->_oDb->$sGetValuesMethod();
  1044. foreach ($a as $k => $v) {
  1045. $aValues[$k] = $v;
  1046. }
  1047. $aTmplVars = [];
  1048. if(!empty($aAgent[$sField])) {
  1049. $a = explode(',', $aAgent[$sField]);
  1050. foreach($a as $v) {
  1051. $aInputSelect = [
  1052. 'type' => 'select',
  1053. 'name' => $sField . '[]',
  1054. 'values' => $aValues,
  1055. 'value' => $v,
  1056. 'attrs' => [
  1057. 'class' => 'bx-def-margin-sec-top-auto'
  1058. ]
  1059. ];
  1060. $sInput = $oForm->genInput($aInputSelect);
  1061. $aInputHidden = [
  1062. 'type' => 'hidden',
  1063. 'name' => $sField . '_ids[]',
  1064. 'value' => $v,
  1065. ];
  1066. $sInput .= $oForm->genInput($aInputHidden);
  1067. $aTmplVars[] = ['js_object' => $sJsObject, 'input_select' => $sInput];
  1068. }
  1069. }
  1070. else {
  1071. $aInputSelect = [
  1072. 'type' => 'select',
  1073. 'name' => $sField . '[]',
  1074. 'values' => $aValues,
  1075. 'value' => '',
  1076. 'attrs' => [
  1077. 'class' => 'bx-def-margin-sec-top-auto'
  1078. ]
  1079. ];
  1080. $aTmplVars = [
  1081. ['js_object' => $sJsObject, 'input_select' => $oForm->genInput($aInputSelect)],
  1082. ];
  1083. }
  1084. $aInputButton = [
  1085. 'type' => 'button',
  1086. 'name' => $sField . '_add',
  1087. 'value' => _t('_adm_nav_btn_items_add'),
  1088. 'attrs' => [
  1089. 'class' => 'bx-def-margin-sec-top',
  1090. 'onclick' => $sJsObject . ".$sJsAddMethod(this, '" . $sField . "');"
  1091. ]
  1092. ];
  1093. $aForm['inputs'][$sField]['content'] = $this->_oTemplate->parseHtmlByName($sTemplateName, [
  1094. "bx_repeat:$sField" => $aTmplVars,
  1095. 'btn_add' => $oForm->genInputButton($aInputButton)
  1096. ]);
  1097. }
  1098. protected function _getActionManual ($sType, $sKey, $a, $isSmall = false, $isDisabled = false, $aRow = array())
  1099. {
  1100. if ($aRow['trigger'] != 'manual' && $aRow['trigger'] != 'scheduler')
  1101. return '';
  1102. return parent::_getActionDefault ($sType, $sKey, $a, $isSmall, $isDisabled, $aRow);
  1103. }
  1104. /**
  1105. * Chat history only makes sense for agents people talk to; event agents get "activity" instead.
  1106. */
  1107. protected function _getActionMessage ($sType, $sKey, $a, $isSmall = false, $isDisabled = false, $aRow = array())
  1108. {
  1109. if (!in_array($aRow['trigger'], ['manual', 'message'], true))
  1110. return '';
  1111. return parent::_getActionDefault ($sType, $sKey, $a, $isSmall, $isDisabled, $aRow);
  1112. }
  1113. protected function _getActionActivity ($sType, $sKey, $a, $isSmall = false, $isDisabled = false, $aRow = array())
  1114. {
  1115. if (in_array($aRow['trigger'], ['manual', 'message'], true))
  1116. return '';
  1117. return parent::_getActionDefault ($sType, $sKey, $a, $isSmall, $isDisabled, $aRow);
  1118. }
  1119. /**
  1120. * What an event-driven agent did: BxDolAiActivity rows, newest first.
  1121. */
  1122. public function performActionActivity()
  1123. {
  1124. $iId = $this->_getId();
  1125. $aAgent = BxDolAiQuery::getAgentObject($iId);
  1126. if (!$aAgent) {
  1127. echoJson(['msg' => _t('_sys_txt_error_occured')]);
  1128. return;
  1129. }
  1130. $aItems = BxDolAiActivity::listForAgent($iId, 0, 200);
  1131. $sTitle = _t('_sys_agents_agents_popup_activity', !empty($aAgent['title']) ? $aAgent['title'] : $aAgent['name']);
  1132. if (strpos($sTitle, '_sys_agents_agents_popup_activity') === 0)
  1133. $sTitle = 'Activity of "' . (!empty($aAgent['title']) ? $aAgent['title'] : $aAgent['name']) . '"';
  1134. $sEmpty = _t('_sys_agents_agents_txt_activity_empty');
  1135. if ($sEmpty === '_sys_agents_agents_txt_activity_empty')
  1136. $sEmpty = 'Nothing yet';
  1137. $sRows = '';
  1138. foreach ($aItems as $aItem) {
  1139. $sText = bx_process_output($aItem['text']);
  1140. if ($aItem['url'] !== '')
  1141. $sText = '<a href="' . bx_html_attribute($aItem['url']) . '" target="_blank">' . $sText . '</a>';
  1142. $sSummary = $aItem['summary'] !== '' ? '<div class="bx-def-font-small" style="opacity:.75;">' . bx_process_output($aItem['summary']) . '</div>' : '';
  1143. $sRows .= '<div class="bx-def-padding-sec-tb" style="border-bottom:1px solid rgba(127,127,127,.2);' . ($aItem['ok'] ? '' : 'color:#c0392b;') . '">'
  1144. . '<div style="display:flex;gap:1rem;justify-content:space-between;">'
  1145. . '<div>' . $sText . '</div>'
  1146. . '<div class="bx-def-font-small" style="white-space:nowrap;opacity:.6;">' . bx_process_output($aItem['added_formatted']) . '</div>'
  1147. . '</div>'
  1148. . $sSummary
  1149. . '</div>';
  1150. }
  1151. if ($sRows === '')
  1152. $sRows = '<div class="bx-def-padding" style="opacity:.6;">' . bx_process_output($sEmpty) . '</div>';
  1153. $sContent = BxTemplStudioFunctions::getInstance()->popupBox('popup_agent_activity_' . $iId, $sTitle,
  1154. '<div class="bx-agents-popup-activity" style="max-height:70vh;overflow:auto;min-width:40rem;">' . $sRows . '</div>'
  1155. );
  1156. echoJson(['popup' => ['html' => $sContent, 'options' => ['closeOnOuterClick' => false]]]);
  1157. }
  1158. protected function _getAgentWithProfile($iProfileId, $iExcludeAgentId = 0)
  1159. {
  1160. $aAgents = BxDolAi::getInstance()->getAgentsByProfileId($iProfileId);
  1161. foreach($aAgents as $aAgent) {
  1162. if($aAgent['id'] != $iExcludeAgentId)
  1163. return $aAgent;
  1164. }
  1165. return null;
  1166. }
  1167. protected function _getModelSelectValues()
  1168. {
  1169. $aParams = ['sample' => 'all_pairs', 'active' => 1];
  1170. $aModels = $this->_oDb->getModelsBy(array_merge($aParams, ['capabilities' => ['chatvlm', 'chatllm']]));
  1171. if(!$aModels || !is_array($aModels))
  1172. $aModels = $this->_oDb->getModelsBy($aParams);
  1173. return ($aModels && is_array($aModels)) ? $aModels : [];
  1174. }
  1175. protected function _getProfileSelectValues($bSelectOne = true, $sSelectOneLangKey = '_Select_one')
  1176. {
  1177. $aProfiles = bx_srv('system', 'get_options_agents_profile', [$bSelectOne, $sSelectOneLangKey], 'TemplServices');
  1178. if($aProfiles && is_array($aProfiles))
  1179. return $aProfiles;
  1180. $aProfiles = bx_srv('system', 'get_options_profile_bot', [], 'TemplServices');
  1181. return ($aProfiles && is_array($aProfiles)) ? $aProfiles : [];
  1182. }
  1183. protected function _addJsCss()
  1184. {
  1185. parent::_addJsCss();
  1186. $this->_oTemplate->addJs(['select2/js/select2.min.js']);
  1187. $this->_oTemplate->addCss([BX_DIRECTORY_PATH_PLUGINS_PUBLIC . 'select2/css/|select2.min.css']);
  1188. }
  1189. }
  1190. /** @} */