_sUrlPage = BX_DOL_URL_STUDIO . 'agents.php?page=agents';
$this->_sFieldName = 'name';
}
public function getPageJsObject()
{
return 'oBxDolStudioPageAgents';
}
public function performActionGetAlert()
{
$aAlert = $this->_getAlertPayload(bx_get('alert'));
echoJson([
'code' => $aAlert ? 200 : 404,
'desc' => $aAlert ? $this->_oDb->getAlertDesc(bx_get('alert')) : '',
'payload' => $aAlert,
]);
}
public function performActionGetFormInputs()
{
$aFormInputs = $this->_getFormInputs(bx_get('form_object'));
if (!$aFormInputs) {
echoJson(['code' => 404, 'msg' => _t('_sys_not_available')]);
return;
}
echoJson([
'code' => $aFormInputs ? 200 : 404,
'form_inputs' => $aFormInputs,
]);
}
public function performActionManual()
{
$iId = $this->_getId();
$aAgent = BxDolAiQuery::getAgentObject($iId);
if (!$aAgent) {
echoJson(['msg' => _t('_sys_txt_error_occured')]);
return;
}
if (!$aAgent['active']) {
echoJson(['msg' => _t('_sys_txt_agent_inactive')]);
return;
}
$oAi = BxDolAi::getInstance();
try {
$sResponse = $oAi->callAgent('manual', $aAgent);
} catch (Throwable $o) {
echoJson(['msg' => $o->getMessage()]);
return;
}
$oParsedown = new Parsedown();
$oParsedown->setSafeMode(true);
$sMessageHtml = $oParsedown->text($sResponse);
$oTemplate = BxDolStudioTemplate::getInstance();
$sHtml = $oTemplate->parseHtmlByName('agents_manual_response.html', [
'response' => $sMessageHtml
]);
echoJson(['msg' => $sHtml]);
}
public function performActionWipeChatHistory()
{
$iId = $this->_getId();
$aAgent = BxDolAiQuery::getAgentObject($iId);
if (!$aAgent) {
echoJson(['msg' => _t('_sys_txt_error_occured')]);
return;
}
$oDb = new BxDolAiQuery();
$oDb->wipeAgentChatHistory($aAgent);
$aRes = ['grid' => $this->getCode(false), 'blink' => $iId];
echoJson($aRes);
}
public function performActionAdd()
{
$sAction = 'add';
$oTemplate = BxDolStudioTemplate::getInstance();
$oAI = BxDolAi::getInstance();
$aForm = $this->_getForm($sAction);
$oForm = new BxTemplFormView($aForm);
$oForm->initChecker();
if ($oForm->isSubmitted() && $oForm->getCleanValue('trigger') == 'message') {
$aAgent = $this->_getAgentWithProfile($oForm->getCleanValue('profile_id'));
if ($aAgent) {
$oForm->aInputs['profile_id']['error'] = _t('_sys_agents_form_field_err_profile_has_agent', $aAgent['name']);
$oForm->setValid(false);
}
}
if($oForm->isSubmittedAndValid()) {
$aValsToAdd = [
'added' => time()
];
$sName = $oForm->getCleanValue($this->_sFieldName);
$sName = $this->_getUniqName($sName);
BxDolForm::setSubmittedValue($this->_sFieldName, $sName, $oForm->aFormAttrs['method']);
$iProfileId = $oForm->getCleanValue('profile_id');
if(empty($iProfileId)) {
$iProfileId = (int)getParam('sys_profile_bot');
if(empty($iProfileId))
$iProfileId = current(bx_srv('system', 'get_options_agents_profile', [false], 'TemplServices'))['key'];
$aValsToAdd['profile_id'] = $iProfileId;
}
$iModel = $oForm->getCleanValue('model_id');
$sTrigger = $oForm->getCleanValue('trigger');
$sTools = is_array($oForm->getCleanValue('tools')) ? implode(',', $oForm->getCleanValue('tools')) : '';
$aValsToAdd['tools'] = $sTools;
$aValsToAdd['acl_levels'] = (int)$oForm->getCleanValue('acl_levels');
$bIsValid = true;
if($bIsValid) {
if(($iId = $oForm->insert($aValsToAdd)) !== false) {
$this->_oDb->cleanCache('sys_agents_with_alert');
$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_agents_popup_add'), $this->_oTemplate->parseHtmlByName('agents_agents_form.html', [
'form_id' => $sFormId,
'form' => $oForm->getCode(true),
'object' => $this->_sObject,
'action' => $sAction
]));
return echoJson(['popup' => ['html' => $sContent, 'options' => ['closeOnOuterClick' => false]]]);
}
public function performActionEdit()
{
$sAction = 'edit';
$oTemplate = BxDolStudioTemplate::getInstance();
$oAI = BxDolAi::getInstance();
$iId = $this->_getId();
$aAgent = BxDolAiQuery::getAgentObject($iId);
$aForm = $this->_getFormEdit($sAction, $aAgent);
$oForm = new BxTemplFormView($aForm);
$oForm->initChecker();
if ($oForm->isSubmitted() && $oForm->getCleanValue('trigger') == 'message') {
$aAgent = $this->_getAgentWithProfile($oForm->getCleanValue('profile_id'), $iId);
if ($aAgent) {
$oForm->aInputs['profile_id']['error'] = _t('_sys_agents_form_field_err_profile_has_agent', $aAgent['name']);
$oForm->setValid(false);
}
}
if($oForm->isSubmittedAndValid()) {
$aValsToAdd = [];
$sName = $oForm->getCleanValue($this->_sFieldName);
$sName = $this->_getUniqName($sName);
BxDolForm::setSubmittedValue($this->_sFieldName, $sName, $oForm->aFormAttrs['method']);
$iProfileId = $oForm->getCleanValue('profile_id');
if(empty($iProfileId)) {
$iProfileId = (int)getParam('sys_profile_bot');
if(empty($iProfileId))
$iProfileId = current(bx_srv('system', 'get_options_agents_profile', [false], 'TemplServices'))['key'];
$aValsToAdd['profile_id'] = $iProfileId;
}
$iModel = $oForm->getCleanValue('model_id');
$sTrigger = $oForm->getCleanValue('trigger');
$sTools = is_array($oForm->getCleanValue('tools')) ? implode(',', $oForm->getCleanValue('tools')) : '';
$aValsToAdd['tools'] = $sTools;
$aValsToAdd['acl_levels'] = (int)$oForm->getCleanValue('acl_levels');
$bIsValid = true;
if($bIsValid) {
if(($iId = $oForm->update($iId, $aValsToAdd)) !== false) {
$this->_oDb->cleanCache('sys_agents_with_alert');
$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_agents_popup_edit', $aAgent['name']), $this->_oTemplate->parseHtmlByName('agents_agents_form.html', [
'form_id' => $sFormId,
'form' => $oForm->getCode(true),
'object' => $this->_sObject,
'action' => $sAction
]));
return echoJson(['popup' => ['html' => $sContent, 'options' => ['closeOnOuterClick' => false]]]);
}
public function performActionLogs()
{
$iId = $this->_getId();
$aAgent = BxDolAiQuery::getAgentObject($iId);
if (!$aAgent) {
echoJson(['msg' => _t('_sys_txt_error_occured')]);
return;
}
$oGrid = BxDolGrid::getObjectInstance('sys_studio_agents_logs');
$oGrid->addMarkers(['agent_id' => $iId]);
$oGrid->setBrowseParams(['agent_id' => $iId]);
$sGrid = $oGrid->getCode();
$sContent = BxTemplStudioFunctions::getInstance()->popupBox('popup_files_' . $iId, _t('_sys_agents_logs_popup', $aAgent['name']), $this->_oTemplate->parseHtmlByName('agents_popup_grid.html', [
'grid' => $sGrid,
]));
return echoJson(['popup' => ['html' => $sContent, 'options' => ['closeOnOuterClick' => false]]]);
}
public function performActionMessage()
{
$iId = $this->_getId();
$aAgent = BxDolAiQuery::getAgentObject($iId);
if (!$aAgent) {
echoJson(['msg' => _t('_sys_txt_error_occured')]);
return;
}
if (!$aAgent['active']) {
echoJson(['msg' => _t('_sys_txt_agent_inactive')]);
return;
}
$sChatId = 'bx-ai-chat-' . $iId;
$sName = !empty($aAgent['title']) ? $aAgent['title'] : $aAgent['name'];
$aThreadsTpl = [];
$oChat = BxDolAiChat::getInstance();
$aThreads = $oChat->listAgentChatThreads($aAgent);
foreach ($aThreads as $aThread) {
$aThreadsTpl[] = [
'thread_id' => bx_html_attribute($aThread['thread_id']),
'writable' => (int)$aThread['writable'],
'context_pid' => (int)$aThread['context_pid'],
'title' => bx_process_output($aThread['title']),
'meta' => bx_process_output($aThread['meta']),
'class_mine' => $aThread['class_mine'],
];
}
$sContent = BxTemplStudioFunctions::getInstance()->popupBox('popup_agent_chat_' . $iId, _t('_sys_agents_agents_popup_message', $sName), $this->_oTemplate->parseHtmlByName('agents_popup_chat.html', [
'chat_id' => $sChatId,
'agent_id' => (int)$iId,
'txt_readonly' => _t('_sys_agents_agents_txt_readonly'),
'txt_chats' => _t('_sys_agents_agents_txt_chats'),
'txt_search' => bx_html_attribute(_t('_sys_agents_agents_txt_search')),
'txt_search_empty' => _t('_sys_agents_agents_txt_search_empty'),
'bx_repeat:threads' => $aThreadsTpl,
]));
$aThreadsJs = [];
foreach ($aThreads as $aThread)
$aThreadsJs[] = $this->_agentChatThreadJs($aThread);
$sThreadsJson = json_encode($aThreadsJs, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT);
if ($sThreadsJson === false)
$sThreadsJson = '[]';
$sJsObject = $this->getPageJsObject();
return echoJson(['popup' => [
'html' => $sContent,
'options' => [
'closeOnOuterClick' => false,
'onShow' => $sJsObject . ".initAgentChat('#" . $sChatId . "', " . (int)$iId . ", " . $sThreadsJson . ");",
'onHide' => $sJsObject . ".destroyAgentChat();",
]
]]);
}
public function performActionGetChatThreads()
{
$iId = $this->_getId();
$aAgent = BxDolAiQuery::getAgentObject($iId);
if (!$aAgent) {
echoJson(['code' => 404, 'threads' => []]);
return;
}
$aThreadsJs = [];
$aThreads = BxDolAiChat::getInstance()->listAgentChatThreads($aAgent);
foreach ($aThreads as $aThread)
$aThreadsJs[] = $this->_agentChatThreadJs($aThread);
echoJson(['code' => 200, 'threads' => $aThreadsJs]);
}
public function performActionGetChatThread()
{
$iId = $this->_getId();
$aAgent = BxDolAiQuery::getAgentObject($iId);
if (!$aAgent) {
echoJson(['code' => 404, 'msg' => _t('_sys_txt_error_occured'), 'messages' => []]);
return;
}
$sThreadId = trim((string)bx_get('thread_id'));
$oChat = BxDolAiChat::getInstance();
$aMessages = $oChat->getChatHistoryUiMessagesByThread($aAgent, $sThreadId);
if ($aMessages === false) {
echoJson(['code' => 404, 'msg' => _t('_sys_txt_error_occured'), 'messages' => []]);
return;
}
echoJson([
'code' => 200,
'messages' => $aMessages,
'writable' => $oChat->isOwnAgentChatThread($aAgent, $sThreadId) ? 1 : 0,
'artifacts' => $oChat->getChatHistoryArtifactsByThread($aAgent, $sThreadId),
]);
}
protected function _agentChatThreadJs($aThread)
{
$aArtifacts = [];
if (!empty($aThread['artifacts']) && is_array($aThread['artifacts'])) {
foreach ($aThread['artifacts'] as $aItem) {
if (!is_array($aItem))
continue;
$aArtifacts[] = [
'field_name' => (string)($aItem['field_name'] ?? ''),
'field_value' => (string)($aItem['field_value'] ?? ''),
];
}
}
return [
'thread_id' => (string)$aThread['thread_id'],
'writable' => (int)$aThread['writable'],
'context_pid' => (int)$aThread['context_pid'],
'title' => (string)$aThread['title'],
'meta' => (string)$aThread['meta'],
'status' => (string)($aThread['status'] ?? 'opened'),
'created_at' => (string)($aThread['created_at'] ?? ''),
'updated_at' => (string)($aThread['updated_at'] ?? ''),
'artifacts' => $aArtifacts,
'messages' => (!empty($aThread['messages']) && is_array($aThread['messages'])) ? array_values($aThread['messages']) : [],
];
}
protected function _getCellProfileId($mixedValue, $sKey, $aField, $aRow)
{
$mixedValue = BxDolProfile::getInstanceMagic($mixedValue)->getUnit(0, ['template' => 'unit_wo_info']);
return parent::_getCellDefault($mixedValue, $sKey, $aField, $aRow);
}
protected function _getCellIcon($mixedValue, $sKey, $aField, $aRow)
{
$sIcon = '';
if($mixedValue) {
list($sIcon, $sIconUrl, $sIconA, $sIconHtml, $sIconFontWithHtml) = $this->_oTemplate->getTemplateFunctions()->getIcon($mixedValue, ['class' => 'sys-colored']);
if($sIcon)
$sIcon = $this->_oTemplate->parseIcon(BxDolIconset::getObjectInstance()->getIcon($sIcon));
else if($sIconHtml)
$sIcon = $sIconHtml;
else if($sIconUrl)
$sIcon = '';
else if($sIconFontWithHtml)
$sIcon = $sIconFontWithHtml;
}
if (!$sIcon)
$sIcon = '';
return parent::_getCellDefault($sIcon, $sKey, $aField, $aRow);
}
protected function _getCellModelId($mixedValue, $sKey, $aField, $aRow)
{
$aModel = $this->_oDb->getModelsBy(['sample' => 'id', 'id' => $mixedValue]);
if(!empty($aModel) && is_array($aModel)) {
$mixedValue = $aModel['icon'];
if (strpos($mixedValue, '.svg') !== false)
$mixedValue = $this->_oTemplate->getIconContent($mixedValue);
} else {
$mixedValue = '';
}
return parent::_getCellDefault($mixedValue, $sKey, $aField, $aRow);
}
protected function _getCellTrigger($mixedValue, $sKey, $aField, $aRow)
{
$mixedValue = $this->_oTemplate->getIconContent('agt-trg-' . $mixedValue . '.svg');
return parent::_getCellDefault($mixedValue, $sKey, $aField, $aRow);
}
protected function _getCellName($mixedValue, $sKey, $aField, $aRow)
{
if (!empty($aRow['title']))
$mixedValue = $aRow['title'];
return parent::_getCellDefault($mixedValue, $sKey, $aField, $aRow);
}
protected function _delete ($mixedId)
{
$mixedResult = parent::_delete($mixedId);
$this->_oDb->cleanCache('sys_agents_with_alert');
if ($mixedResult)
BxDolAiActivity::deleteForAgent((int)$mixedId);
return $mixedResult;
}
protected function _getFormEdit($sAction, $aAgent = [])
{
$aForm = $this->_getForm($sAction, $aAgent);
$aForm['form_attrs']['action'] .= '&id=' . $aAgent['id'];
unset($aForm['inputs']['name']);
return $aForm;
}
protected function _getForm($sAction, $aAgent = [])
{
$sJsObject = $this->getPageJsObject();
$aForm = array(
'form_attrs' => array(
'id' => 'bx_std_agents_' . $sAction,
'action' => BX_DOL_URL_ROOT . 'grid.php?o=sys_studio_agents_agents&a=' . $sAction,
'method' => 'post',
),
'params' => array (
'db' => array(
'table' => 'sys_agents_agents',
'key' => 'id',
'submit_name' => 'do_submit',
),
),
'inputs' => array(
'title' => [
'type' => 'text',
'name' => 'title',
'caption' => _t('_sys_agents_field_title'),
'info' => _t('_sys_agents_field_title_info'),
'value' => $aAgent['title'] ?? '',
'required' => '1',
'checker' => [
'func' => 'Avail',
'error' => _t('_sys_agents_form_field_err_enter'),
],
'db' => [
'pass' => 'Xss',
],
],
'name' => [
'type' => 'text',
'name' => 'name',
'caption' => _t('_sys_agents_field_name'),
'info' => _t('_sys_agents_field_name_info'),
'value' => isset($aAgent['name']) ? $aAgent['name'] : '',
'required' => '1',
'checker' => [
'func' => 'Avail',
'error' => _t('_sys_agents_form_field_err_enter'),
],
'db' => [
'pass' => 'Xss',
],
],
'description' => [
'type' => 'textarea',
'name' => 'description',
'caption' => _t('_sys_agents_field_description'),
'info' => _t('_sys_agents_field_description_info'),
'value' => $aAgent['description'] ?? '',
'db' => [
'pass' => 'Xss',
],
],
'icon' => [
'type' => 'textarea',
'name' => 'icon',
'caption' => _t('_sys_agents_field_icon'),
'info' => _t('_sys_agents_field_icon_info'),
'value' => $aAgent['icon'] ?? '',
'code' => 1,
'db' => [
'pass' => 'Xss',
],
],
'model_id' => [
'type' => 'select',
'name' => 'model_id',
'caption' => _t('_sys_agents_field_model_id'),
'info' => _t('_sys_agents_field_model_id_info'),
'value' => isset($aAgent['model_id']) ? $aAgent['model_id'] : 0,
'values' => $this->_getModelSelectValues(),
'required' => '1',
'checker' => [
'func' => 'Avail',
'error' => _t('_sys_agents_form_field_err_select'),
],
'db' => [
'pass' => 'Int',
],
],
'profile_id' => [
'type' => 'select',
'name' => 'profile_id',
'caption' => _t('_sys_agents_field_profile_id'),
'info' => _t('_sys_agents_field_profile_id_inf'),
'value' => isset($aAgent['profile_id']) ? $aAgent['profile_id'] : 0,
'values' => $this->_getProfileSelectValues(),
'required' => '1',
'required' => '1',
'checker' => [
'func' => 'Avail',
'error' => _t('_sys_agents_form_field_err_select'),
],
'db' => [
'pass' => 'Int',
]
],
'acl_levels' => [
'type' => 'checkbox_set',
'name' => 'acl_levels',
'caption' => _t('_sys_agents_field_acl_levels'),
'info' => _t('_sys_agents_field_acl_levels_info'),
'value' => [],
'values' => [],
'db' => [
'pass' => 'Set',
]
],
'trigger' => [
'type' => 'select',
'name' => 'trigger',
'caption' => _t('_sys_agents_field_trigger'),
'info' => _t('_sys_agents_field_trigger_info'),
'value' => isset($aAgent['trigger']) ? $aAgent['trigger'] : 0,
'values' => [
'alert' => _t('_sys_agents_field_trigger_alert'),
'scheduler' => _t('_sys_agents_field_trigger_scheduler'),
'webhook' => _t('_sys_agents_field_trigger_webhook'),
'manual' => _t('_sys_agents_field_trigger_manual'),
'agent' => _t('_sys_agents_field_trigger_agent'),
'message' => _t('_sys_agents_field_trigger_message'),
'form-input' => _t('_sys_agents_field_trigger_form_input'),
],
// 'attrs' => [
// 'onchange' => $this->getPageJsObject() . '.onChangeAgentTrigger(this)',
// ],
'required' => '1',
'db' => [
'pass' => 'Xss',
]
],
'async' => [
'type' => 'checkbox',
'name' => 'async',
'caption' => _t('_sys_agents_field_async'),
'info' => _t('_sys_agents_field_async_inf'),
'value' => 1,
'checked' => isset($aAgent['async']) ? $aAgent['async'] : 0,
'db' => [
'pass' => 'Int',
]
],
'alert_section' => [
'type' => 'block_header',
'caption' => _t('_sys_agents_block_header_alert'),
'collapsable' => true,
'collapsed' => true,
],
'alert_sample' => [
'type' => 'custom',
'name' => 'alert_sample',
'caption' => _t('_sys_agents_field_alert_sample'),
'content' => $this->_oTemplate->parseHtmlByName('agents_agents_alerts_payload.html', [
'text-visibility' => empty($aAgent['alert']) ? 'block' : 'none',
'text' => _t('_sys_agents_waiting_for_sample_data_alert'),
'payload-visibility' => !empty($aAgent['alert']) ? 'block' : 'none',
'desc' => $aAgent ? $this->_oDb->getAlertDesc($aAgent['alert']) : '',
'payload' => !empty($aAgent['alert']) ? json_encode($this->_getAlertPayload($aAgent['alert']), JSON_PRETTY_PRINT) : '',
]),
],
'alert' => [
'type' => 'custom',
'name' => 'alert',
'caption' => _t('_sys_agents_field_alert'),
'info' => _t('_sys_agents_field_alert_info'),
'content' => $this->_oTemplate->parseHtmlByName('agents_agents_alerts_select.html', $this->_getAlertValues(isset($aAgent['alert']) ? $aAgent['alert'] : '')),
'db' => [
'pass' => 'Xss',
],
],
'alert_section_end' => [
'type' => 'block_end',
],
'scheduler_section' => [
'type' => 'block_header',
'caption' => _t('_sys_agents_block_header_scheduler'),
'collapsable' => true,
'collapsed' => true,
],
'scheduler_cron' => [
'type' => 'text',
'name' => 'scheduler_cron',
'caption' => _t('_sys_agents_field_scheduler_cron'),
'info' => _t('_sys_agents_field_scheduler_cron_info'),
'value' => isset($aAgent['scheduler_cron']) ? $aAgent['scheduler_cron'] : '',
'db' => [
'pass' => 'Xss',
],
],
'scheduler_section_end' => [
'type' => 'block_end',
],
'webhook_section' => [
'type' => 'block_header',
'caption' => _t('_sys_agents_block_header_webhook'),
'collapsable' => true,
'collapsed' => true,
],
'webhook_sample' => [
'type' => 'custom',
'name' => 'webhook_sample',
'caption' => _t('_sys_agents_field_webhook_sample'),
'content' => isset($aAgent['webhook_sample']) ? $aAgent['webhook_sample'] : _t('_sys_agents_waiting_for_sample_data_webhook'),
],
'webhook_key' => [
'type' => 'text',
'name' => 'webhook_key',
'caption' => _t('_sys_agents_field_webhook_key'),
'info' => _t('_sys_agents_field_webhook_key_info'),
'value' => isset($aAgent['webhook_key']) ? $aAgent['webhook_key'] : '',
'db' => [
'pass' => 'Xss',
],
],
'webhook_section_end' => [
'type' => 'block_end',
],
'message_section' => [
'type' => 'block_header',
'caption' => _t('_sys_agents_block_header_message'),
'collapsable' => true,
'collapsed' => true,
],
'message_profile_id' => [
'type' => 'select',
'name' => 'message_profile_id',
'caption' => _t('_sys_agents_field_message_profile'),
'info' => _t('_sys_agents_field_message_profile_info'),
'value' => isset($aAgent['message_profile_id']) ? $aAgent['message_profile_id'] : '',
'values' => $this->_getProfileSelectValues(true, '_adm_nav_txt_items_visible_for_all'),
'db' => [
'pass' => 'Xss',
],
],
'message_section_end' => [
'type' => 'block_end',
],
'form_field_section' => [
'type' => 'block_header',
'caption' => _t('_sys_agents_block_header_form_input'),
'collapsable' => true,
'collapsed' => true,
],
'form_object' => [
'type' => 'custom',
'name' => 'form_object',
'caption' => _t('_sys_agents_form_object'),
'info' => _t('_sys_agents_form_object_info'),
'content' => $this->_oTemplate->parseHtmlByName('agents_agents_form_object_select.html', $this->_getFormObjectValues(isset($aAgent['form_object']) ? $aAgent['form_object'] : '')),
'db' => [
'pass' => 'Xss',
],
],
'form_input' => [
'type' => 'custom',
'name' => 'form_input',
'caption' => _t('_sys_agents_form_input'),
'info' => _t('_sys_agents_form_input_info'),
'content' => $this->_oTemplate->parseHtmlByName('agents_agents_form_input_select.html', $this->_getFormInputValues(isset($aAgent['form_object']) ? $aAgent['form_object'] : '', isset($aAgent['form_input']) ? $aAgent['form_input'] : '')),
'db' => [
'pass' => 'Xss',
],
],
'form_field_section_end' => array(
'type' => 'block_end',
),
'manual_section' => [
'type' => 'block_header',
'caption' => _t('_sys_agents_block_header_manual'),
'collapsable' => true,
'collapsed' => true,
],
'max_turns' => [
'type' => 'text',
'name' => 'max_turns',
'caption' => _t('_sys_agents_field_manual_max_turns'),
'info' => _t('_sys_agents_field_manual_max_turns_info'),
'value' => $aAgent['max_turns'] ?? 0,
'required' => '1',
'db' => [
'pass' => 'Int',
],
],
'chat_ttl_min' => [
'type' => 'text',
'name' => 'chat_ttl_min',
'caption' => _t('_sys_agents_field_manual_chat_ttl_min'),
'info' => _t('_sys_agents_field_manual_chat_ttl_min_info'),
'value' => $aAgent['chat_ttl_min'] ?? 0,
'required' => '1',
'db' => [
'pass' => 'Int',
],
],
'limit_message' => [
'type' => 'textarea',
'name' => 'limit_message',
'caption' => _t('_sys_agents_field_manual_limit_message'),
'info' => _t('_sys_agents_field_manual_limit_message_info'),
'value' => $aAgent['limit_message'] ?? '',
'db' => [
'pass' => 'Xss',
],
],
'max_input_chars' => [
'type' => 'text',
'name' => 'max_input_chars',
'caption' => _t('_sys_agents_field_manual_max_input_chars'),
'info' => _t('_sys_agents_field_manual_max_input_chars_info'),
'value' => $aAgent['max_input_chars'] ?? 0,
'required' => '1',
'db' => [
'pass' => 'Int',
],
],
'max_tokens' => [
'type' => 'text',
'name' => 'max_tokens',
'caption' => _t('_sys_agents_field_manual_max_tokens'),
'info' => _t('_sys_agents_field_manual_max_tokens_info'),
'value' => $aAgent['max_tokens'] ?? 0,
'required' => '1',
'db' => [
'pass' => 'Int',
],
],
'max_sessions_per_hour' => [
'type' => 'text',
'name' => 'max_sessions_per_hour',
'caption' => _t('_sys_agents_field_manual_max_sessions_per_hour'),
'info' => _t('_sys_agents_field_manual_max_sessions_per_hour_info'),
'value' => $aAgent['max_sessions_per_hour'] ?? 3,
'required' => '1',
'db' => [
'pass' => 'Int',
],
],
'max_sessions_per_day' => [
'type' => 'text',
'name' => 'max_sessions_per_day',
'caption' => _t('_sys_agents_field_manual_max_sessions_per_day'),
'info' => _t('_sys_agents_field_manual_max_sessions_per_day_info'),
'value' => $aAgent['max_sessions_per_day'] ?? 10,
'required' => '1',
'db' => [
'pass' => 'Int',
],
],
'hidden_first_message' => [
'type' => 'text',
'name' => 'hidden_first_message',
'caption' => _t('_sys_agents_field_manual_hidden_first_message'),
'info' => _t('_sys_agents_field_manual_hidden_first_message_info'),
'value' => $aAgent['hidden_first_message'] ?? '',
'attrs' => ['maxlength' => 64],
'db' => [
'pass' => 'Xss',
],
],
'manual_section_end' => [
'type' => 'block_end',
],
'vector_store_id' => [
'type' => 'select',
'name' => 'vector_store_id',
'caption' => _t('_sys_agents_field_vector_store_id'),
'info' => _t('_sys_agents_field_vector_store_id_info'),
'value' => isset($aAgent['vector_store_id']) ? $aAgent['vector_store_id'] : 0,
'values' => $this->_oDb->getVectorStores(),
'required' => '1',
'checker' => [
'func' => 'Avail',
'error' => _t('_sys_agents_form_field_err_select'),
],
'db' => [
'pass' => 'Xss',
],
],
'chat_history_context' => [
'type' => 'text',
'name' => 'chat_history_context',
'caption' => _t('_sys_agents_field_chat_history_context'),
'info' => _t('_sys_agents_field_chat_history_context_info'),
'value' => isset($aAgent['chat_history_context']) ? $aAgent['chat_history_context'] : 50000,
'db' => [
'pass' => 'Int',
],
],
'tools' => [
'type' => 'custom',
'name' => 'tools',
'caption' => _t('_sys_agents_field_tools'),
'info' => _t('_sys_agents_field_tools_info'),
'value' => '',
],
'tools_max_run' => [
'type' => 'text',
'name' => 'tools_max_run',
'caption' => _t('_sys_agents_field_tools_max_run'),
'info' => _t('_sys_agents_field_tools_max_run_info'),
'value' => isset($aAgent['tools_max_run']) ? $aAgent['tools_max_run'] : '10',
'required' => '1',
'db' => [
'pass' => 'Int',
],
],
'prompt_system' => [
'type' => 'textarea',
'name' => 'prompt_system',
'caption' => _t('_sys_agents_field_prompt_system'),
'info' => _t('_sys_agents_field_prompt_system_info'),
'value' => isset($aAgent['prompt_system']) ? $aAgent['prompt_system'] : '',
'db' => [
'pass' => 'Xss',
],
],
'prompts_section' => array(
'type' => 'block_header',
'caption' => 'Other prompts',
'collapsable' => true,
'collapsed' => true,
),
'prompt_steps' => [
'type' => 'textarea',
'name' => 'prompt_steps',
'caption' => _t('_sys_agents_field_prompt_steps'),
'info' => _t('_sys_agents_field_prompt_steps_info'),
'value' => isset($aAgent['prompt_steps']) ? $aAgent['prompt_steps'] : '',
'db' => [
'pass' => 'Xss',
],
],
'prompt_output' => [
'type' => 'textarea',
'name' => 'prompt_output',
'caption' => _t('_sys_agents_field_prompt_output'),
'info' => _t('_sys_agents_field_prompt_output_info'),
'value' => isset($aAgent['prompt_output']) ? $aAgent['prompt_output'] : '',
'db' => [
'pass' => 'Xss',
],
],
'prompt_tools' => [
'type' => 'textarea',
'name' => 'prompt_tools',
'caption' => _t('_sys_agents_field_prompt_tools'),
'info' => _t('_sys_agents_field_prompt_tools_info'),
'value' => isset($aAgent['prompt_tools']) ? $aAgent['prompt_tools'] : '',
'db' => [
'pass' => 'Xss',
],
],
'prompts_section_end' => array(
'type' => 'block_end',
),
'submit' => $this->_getFormControls(),
),
);
if(($sFldTitle = 'title') && ($sFldName = 'name') && isset($aForm['inputs'][$sFldTitle], $aForm['inputs'][$sFldName])) {
$aMask = array('mask' => "javascript:%s.agentCheckName(this, '%s', '%s');", $sJsObject, 'title', 'name');
if($sAction == 'edit' && ($iAgentId = $aAgent['id'] ?? false)) {
$aMask['mask'] = "javascript:%s.agentCheckName(this, '%s', '%s', %d);";
$aMask[] = (int)$iAgentId;
}
$sOnBlur = call_user_func_array('sprintf', array_values($aMask));
$aForm['inputs'][$sFldTitle]['attrs']['onblur'] = $sOnBlur;
$aForm['inputs'][$sFldName]['attrs']['onblur'] = $sOnBlur;
}
$this->_getMultiField('tools', $aAgent, 'getTools', 'toolAdd', 'agents_agents_form_tools.html', $aForm);
BxDolStudioUtils::getVisibilityValues(0, $aForm['inputs']['acl_levels']['values'], $aForm['inputs']['acl_levels']['value']);
$aForm['inputs']['acl_levels']['value'] = (int)($aAgent['acl_levels'] ?? 0);
return $aForm;
}
protected function _getAlertPayload($s)
{
$aAlert = $this->_oDb->getAlert($s);
if (!$aAlert)
return '';
return [
'object_id' => $aAlert['object'],
'sender_profile_id' => $aAlert['sender'],
'extra' => json_decode($aAlert['extra'], true),
'extra_modifiable_keys' => json_decode($aAlert['extra_refs'], true),
];
}
protected function _getAlertValues($sValue)
{
$aAlerts = $this->_oDb->getAlerts();
$a = [
'sys_stat_not_available' => _t('_sys_not_available'),
'grid_object' => $this->_sObject,
'bx_repeat:alerts' => [
[
'name' => _t('_sys_please_select'),
'value' => '',
'desc' => '',
'count' => 0,
'count_per_req' => 0,
'bx_if:sel' => [
'condition' => false,
'content' => ['sel' => '']
]
]
]
];
foreach ($aAlerts as $k => $r) {
$a['bx_repeat:alerts'][] = [
'name' => $r['name'],
'value' => $r['key'],
'desc' => bx_html_attribute($r['desc']),
'count' => bx_html_attribute(_t('_sys_agents_count_today', $r['counter_24h'])),
'count_per_req' => bx_html_attribute(_t('_sys_agents_count_per_req', $r['counter_per_request'])),
'bx_if:sel' => [
'condition' => $sValue == $r['key'],
'content' => [
'sel' => $sValue == $r['key'] ? 'selected' : '',
]
]
];
}
return $a;
}
protected function _getFormObjectValues($sValue)
{
$aFormObjects = $this->_oDb->getFormObjects();
// add "Please select" option
$a = [
'sys_stat_not_available' => _t('_sys_not_available'),
'grid_object' => $this->_sObject,
'bx_repeat:form_objects' => [
[
'title' => _t('_sys_please_select'),
'title_attr' => _t('_sys_please_select'),
'value' => '',
'bx_if:sel' => [
'condition' => false,
'content' => ['sel' => '']
]
]
]
];
// add form objects
$bSelected = false;
foreach ($aFormObjects as $k => $r) {
if ($sValue == $r['form_object'])
$bSelected = true;
$a['bx_repeat:form_objects'][] = [
'title' => $r['module_title'] . ': ' . $r['form_title'],
'title_attr' => bx_html_attribute($r['module_title'] . ': ' . $r['form_title']),
'value' => $r['form_object'],
// 'form_id' => $r['form_id'],
// 'module' => $r['module'],
// 'module_title' => $r['module_title'],
// 'form_title' => $r['form_title'],
'bx_if:sel' => [
'condition' => $sValue == $r['form_object'],
'content' => ['sel' => $sValue == $r['form_object'] ? 'selected' : ''],
]
];
}
// add selected form object if not found in form objects
if ($sValue && !$bSelected) {
$a['bx_repeat:form_objects'][] = [
'title' => $sValue,
'title_attr' => bx_html_attribute($sValue),
'value' => $sValue,
'bx_if:sel' => [
'condition' => true,
'content' => ['sel' => 'selected'],
]
];
}
return $a;
}
protected function _getFormInputs($sFormObject)
{
$sDisplay = $this->_oDb->getFormDisplay($sFormObject);
$oForm = $sDisplay ? BxDolForm::getObjectInstance($sFormObject, $sDisplay) : null;
$aFormInputs = $oForm ? $oForm->aInputs : [];
if (!$aFormInputs)
return [];
$aRet = [];
foreach ($aFormInputs as $k => $r) {
if ($r['type'] == 'text' || $r['type'] == 'textarea') {
$aRet[$r['name']] = [
'name' => $r['name'],
'caption' => $r['caption'],
];
}
}
return $aRet;
}
protected function _getFormInputValues($sFormObject, $sFormInput)
{
$aFormInputs = $this->_getFormInputs($sFormObject);
// add "Please select" option
$a = [
'bx_repeat:form_inputs' => [
[
'title' => _t('_sys_please_select'),
'title_attr' => _t('_sys_please_select'),
'value' => '',
'bx_if:sel' => [
'condition' => false,
'content' => ['sel' => '']
]
]
]
];
// add form inputs
$bSelected = false;
if ($aFormInputs) {
foreach ($aFormInputs as $k => $r) {
if ($sFormInput == $r['name'])
$bSelected = true;
$a['bx_repeat:form_inputs'][] = [
'title' => $r['name'] . ' - ' . $r['caption'],
'title_attr' => bx_html_attribute($r['name'] . (!empty($r['caption']) ? ' - ' . $r['caption'] : '')),
'value' => $r['name'],
'bx_if:sel' => [
'condition' => $sFormInput == $r['name'],
'content' => [
'sel' => $sFormInput == $r['name'] ? 'selected' : '',
]
]
];
}
}
// add selected input if not found in form inputs
if ($sFormInput && !$bSelected) {
$a['bx_repeat:form_inputs'][] = [
'title' => $sFormInput,
'title_attr' => bx_html_attribute($sFormInput),
'value' => $sFormInput,
'bx_if:sel' => [
'condition' => true,
'content' => ['sel' => 'selected'],
]
];
}
return $a;
}
protected function _getUniqName($sName)
{
return uriGenerate($sName, 'sys_agents_agents', 'name', ['lowercase' => false]);
}
protected function _getMultiField($sField, $aAgent, $sGetValuesMethod, $sJsAddMethod, $sTemplateName, &$aForm)
{
if(!isset($aForm['inputs']['tools']))
return;
$sJsObject = $this->getPageJsObject();
$oForm = new BxTemplFormView([]);
$aValues = ['0' => _t('_sys_please_select')];
$a = $this->_oDb->$sGetValuesMethod();
foreach ($a as $k => $v) {
$aValues[$k] = $v;
}
$aTmplVars = [];
if(!empty($aAgent[$sField])) {
$a = explode(',', $aAgent[$sField]);
foreach($a as $v) {
$aInputSelect = [
'type' => 'select',
'name' => $sField . '[]',
'values' => $aValues,
'value' => $v,
'attrs' => [
'class' => 'bx-def-margin-sec-top-auto'
]
];
$sInput = $oForm->genInput($aInputSelect);
$aInputHidden = [
'type' => 'hidden',
'name' => $sField . '_ids[]',
'value' => $v,
];
$sInput .= $oForm->genInput($aInputHidden);
$aTmplVars[] = ['js_object' => $sJsObject, 'input_select' => $sInput];
}
}
else {
$aInputSelect = [
'type' => 'select',
'name' => $sField . '[]',
'values' => $aValues,
'value' => '',
'attrs' => [
'class' => 'bx-def-margin-sec-top-auto'
]
];
$aTmplVars = [
['js_object' => $sJsObject, 'input_select' => $oForm->genInput($aInputSelect)],
];
}
$aInputButton = [
'type' => 'button',
'name' => $sField . '_add',
'value' => _t('_adm_nav_btn_items_add'),
'attrs' => [
'class' => 'bx-def-margin-sec-top',
'onclick' => $sJsObject . ".$sJsAddMethod(this, '" . $sField . "');"
]
];
$aForm['inputs'][$sField]['content'] = $this->_oTemplate->parseHtmlByName($sTemplateName, [
"bx_repeat:$sField" => $aTmplVars,
'btn_add' => $oForm->genInputButton($aInputButton)
]);
}
protected function _getActionManual ($sType, $sKey, $a, $isSmall = false, $isDisabled = false, $aRow = array())
{
if ($aRow['trigger'] != 'manual' && $aRow['trigger'] != 'scheduler')
return '';
return parent::_getActionDefault ($sType, $sKey, $a, $isSmall, $isDisabled, $aRow);
}
/**
* Chat history only makes sense for agents people talk to; event agents get "activity" instead.
*/
protected function _getActionMessage ($sType, $sKey, $a, $isSmall = false, $isDisabled = false, $aRow = array())
{
if (!in_array($aRow['trigger'], ['manual', 'message'], true))
return '';
return parent::_getActionDefault ($sType, $sKey, $a, $isSmall, $isDisabled, $aRow);
}
protected function _getActionActivity ($sType, $sKey, $a, $isSmall = false, $isDisabled = false, $aRow = array())
{
if (in_array($aRow['trigger'], ['manual', 'message'], true))
return '';
return parent::_getActionDefault ($sType, $sKey, $a, $isSmall, $isDisabled, $aRow);
}
/**
* What an event-driven agent did: BxDolAiActivity rows, newest first.
*/
public function performActionActivity()
{
$iId = $this->_getId();
$aAgent = BxDolAiQuery::getAgentObject($iId);
if (!$aAgent) {
echoJson(['msg' => _t('_sys_txt_error_occured')]);
return;
}
$aItems = BxDolAiActivity::listForAgent($iId, 0, 200);
$sTitle = _t('_sys_agents_agents_popup_activity', !empty($aAgent['title']) ? $aAgent['title'] : $aAgent['name']);
if (strpos($sTitle, '_sys_agents_agents_popup_activity') === 0)
$sTitle = 'Activity of "' . (!empty($aAgent['title']) ? $aAgent['title'] : $aAgent['name']) . '"';
$sEmpty = _t('_sys_agents_agents_txt_activity_empty');
if ($sEmpty === '_sys_agents_agents_txt_activity_empty')
$sEmpty = 'Nothing yet';
$sRows = '';
foreach ($aItems as $aItem) {
$sText = bx_process_output($aItem['text']);
if ($aItem['url'] !== '')
$sText = '' . $sText . '';
$sSummary = $aItem['summary'] !== '' ? '