* @package ai * @link https://www.zentao.net */ class ai extends control { /** * AI model. * * @var aiModel * @access public */ public $ai; /** * User model. * * @var userModel * @access public */ public $user; public function __construct($module = '', $method = '') { parent::__construct($module, $method); $this->loadModel('user'); } /** * Check for user's privs and model configs, redirect to most relevant page. * * @access public * @return void */ public function adminIndex() { /* Redirect to model edit ifuser has priv and model is unconfigured. */ if(commonModel::hasPriv('ai', 'models') && !$this->ai->hasModelsAvailable()) return $this->locate($this->createLink('ai', 'models')); /* Redirect to prompts ifuser has priv. */ if(commonModel::hasPriv('ai', 'prompts')) return $this->locate($this->createLink('ai', 'prompts')); /* Redirect to miniPrograms ifuser has priv. */ if(commonModel::hasPriv('ai', 'miniPrograms')) return $this->locate($this->createLink('ai', 'miniPrograms')); /* Redirect to models ifuser has priv. */ if(commonModel::hasPriv('ai', 'models')) return $this->locate($this->createLink('ai', 'models')); /* Redirect to assistants ifuser has priv. */ if(commonModel::hasPriv('ai', 'assistants')) return $this->locate($this->createLink('ai', 'assistants')); /* User has no priv, deny access. */ return $this->send(array('result' => 'fail', 'message' => $this->lang->error->accessDenied, 'locate' => 'back')); } /** * List mini programs. * * @access public * @return void */ public function miniPrograms($category = '', $status = '', $orderBy = 'createdDate_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) { $this->lang->aiapp->menu->generalAgent['subModule'] = 'ai'; $this->app->loadClass('pager', true); $pager = new pager($recTotal, $recPerPage, $pageID); $order = common::appendOrder($orderBy); $categoryList = array_merge($this->lang->ai->miniPrograms->categoryList, $this->ai->getCustomCategories()); $programs = $this->ai->getMiniPrograms($category, $status, $order, $pager); foreach($programs as $program) { $program->canPublish = empty($program->published) && $this->ai->canPublishMiniProgram($program); $program->createdByLabel = $program->createdBy === 'system' ? $this->lang->admin->system : $this->loadModel('user')->getById($program->createdBy, 'account')->realname; $program->categoryLabel = $categoryList[$program->category]; $program->publishedLabel = $program->published == '1' ? $this->lang->ai->miniPrograms->statuses['active'] : $this->lang->ai->miniPrograms->statuses['draft']; } $this->app->loadLang('aiapp'); $this->view->title = $this->lang->aiapp->manageGeneralAgent; $this->view->miniPrograms = $programs; $this->view->category = $category; $this->view->categoryList = $categoryList; $this->view->status = $status; $this->view->orderBy = $orderBy; $this->view->pager = $pager; $this->display(); } /** * Edit mini program category. * * @access public * @return void */ public function editMiniProgramCategory() { $this->lang->aiapp->menu->generalAgent['subModule'] = 'ai'; if(!empty($_POST)) { $_POST = array_filter($_POST, function($key) { return strpos($key, 'custom') === 0; }, ARRAY_FILTER_USE_KEY); if($this->ai->checkDuplicatedCategory()) return $this->sendError($this->lang->ai->maintenanceGroupDuplicated); $this->ai->updateCustomCategories(); return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'load' => true)); } $this->view->usedCustomCategories = $this->ai->getUsedCustomCategories(); $this->view->categoryList = $this->ai->getCustomCategories(); $this->view->title = $this->lang->ai->miniPrograms->common; $this->display(); } /** * Publish a mini program. * * @param string $appID * @access public * @return void */ public function publishMiniProgram($appID) { $result = $this->ai->publishMiniProgram($appID, '1'); if($result) return $this->send(array('result' => 'success', 'load' => true, 'message' => $this->lang->ai->publishSuccess)); $this->sendError(dao::getError()); } /** * Unpublish a mini program. * * @param string $appID * @access public * @return void */ public function unpublishMiniProgram($appID) { $result = $this->ai->publishMiniProgram($appID, '0'); if($result) return $this->send(array('result' => 'success', 'load' => true, 'message' => $this->lang->ai->unpublishSuccess)); $this->sendError(dao::getError()); } /** * Import mini program from zip file. * * @access public * @return void */ public function importMiniProgram() { if(empty($_FILES)) return $this->sendError(array('file' => sprintf($this->lang->error->notempty, $this->lang->ai->installPackage))); $failResponse = array('result' => 'fail', 'message' => $this->lang->ai->saveFail, 'locate' => $this->createLink('ai', 'miniprograms')); if(empty($_POST)) return $this->send($failResponse); $errors = $this->ai->verifyRequiredFields(array('category' => $this->lang->ai->miniPrograms->category, 'published' => $this->lang->ai->toPublish)); if($errors !== false) return $this->sendError($errors); $file = $_FILES['file']; $filePath = $file['tmp_name']; $result = $this->ai->extractZtAppZip($filePath); if(!is_array($result)) return $this->send($failResponse); $info = $result[0]; $fileName = $info['filename']; if(!is_file($fileName)) return $this->send($failResponse); $content = file_get_contents($fileName); unlink($fileName); if(empty($content)) return $this->send($failResponse); $ztApp = json_decode($content); if(!is_object($ztApp)) return $this->send($failResponse); $ztApp->name = $this->ai->getUniqueAppName($ztApp->name); $ztApp->published = $_POST['published']; $ztApp->category = $_POST['category']; $this->ai->createMiniProgram($ztApp); return $this->sendSuccess(array('message' => $this->lang->saveSuccess, 'load' => true, 'closeModal' => true)); } /** * List prompts. * * @param string $module * @param string $status * @access public * @return void */ public function prompts($module = '', $status = '', $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) { $this->loadModel('user'); $users = $this->user->getPairs('noletter'); $userList = $this->user->getList('nodeleted'); /* Set pager and order. */ $this->app->loadClass('pager', $static = true); $pager = new pager($recTotal, $recPerPage, $pageID); $order = common::appendOrder($orderBy); $this->view->prompts = $this->ai->getPrompts($module, $status, $order, $pager); $this->view->module = $module; $this->view->status = $status; $this->view->orderBy = $orderBy; $this->view->pager = $pager; $this->view->title = $this->lang->aiapp->zentaoAgent; $this->view->users = $users; $this->view->userList = $userList; if($this->config->edition == 'open') { $this->view->promptModules = array_map(function ($prompt) { return $prompt->module; }, $this->ai->getPrompts()); } $this->display(); } /** * View prompt details. * * @param int $id * @access public * @return void */ public function promptView($id) { $prompt = $this->ai->getPromptById($id); $this->view->prompt = $prompt; $this->view->preAndNext = $this->loadModel('common')->getPreAndNextObject('prompt', $id); $this->view->actions = $this->loadModel('action')->getList('prompt', $id); $this->view->dataPreview = $this->ai->generateDemoDataPrompt($prompt->module, $prompt->source); $this->view->users = $this->loadModel('user')->getPairs('noletter'); $this->view->title = "{$this->lang->aiapp->zentaoAgent}#{$prompt->id} $prompt->name"; $this->view->fieldConfig = $this->ai->getPromptFields($id); $this->display(); } /** * Create a prompt. * * @access public * @return void */ public function createPrompt() { if($_POST) { $prompt = form::data($this->config->ai->form->createPrompt)->get(); $promptID = $this->ai->createPrompt($prompt); if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); $url = commonModel::hasPriv('ai', 'designPrompt') ? $this->createLink('ai', 'promptassignrole', "prompt=$promptID") : $this->createLink('ai', 'promptview', "id=$promptID"); return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'load' => $url)); } $this->view->title = $this->lang->ai->prompts->create; $this->display(); } /** * Edit a prompt. * * @param int $id * @access public * @return void */ public function promptEdit($id) { $prompt = $this->ai->getPromptByID($id); if($_POST) { $data = form::data($this->config->ai->form->createPrompt)->get(); $prompt->name = $data->name; $prompt->desc = $data->desc; $this->ai->updatePrompt($prompt); if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'load' => $this->inlink('promptView', "id={$prompt->id}"))); } $this->view->prompt = $prompt; $this->view->title = $this->lang->ai->prompts->edit; $this->display(); } /** * Delete a prompt. * * @param int $prompt * @access public * @return void */ public function promptDelete($prompt) { $result = $this->ai->deletePrompt($prompt); if(dao::isError() || $result === false) return $this->send(array('result' => 'fail', 'message' => dao::getError())); return $this->send(array('result' => 'success', 'message' => $this->lang->ai->prompts->action->deleteSuccess, 'load' => $this->inlink('prompts'))); } /** * Edit role of prompt, prompt editing step 2. * * @param int $promptID * @access public * @return void */ public function promptAssignRole($promptID) { if(!common::hasPriv('ai', 'designPrompt')) $this->loadModel('common')->deny('ai', 'designPrompt', false); $prompt = $this->ai->getPromptByID($promptID); if($_POST) { $data = fixer::input('post')->get(); $originalPrompt = clone $prompt; $prompt->model = $data->model; $prompt->role = $data->role; $prompt->characterization = $data->characterization; if(!empty($data->saveTemplate) && $data->saveTemplate == 'save') { $this->ai->createRoleTemplate($prompt->role, $prompt->characterization); } $this->ai->updatePrompt($prompt, $originalPrompt); if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); if(!empty($data->jumpToNext)) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->inlink('promptSelectDataSource', "promptID=$promptID"))); return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->inlink('promptAssignRole', "promptID=$promptID"))); } $this->view->prompt = $prompt; $this->view->promptID = $promptID; $this->view->lastActiveStep = $this->ai->getLastActiveStep($prompt); $this->view->title = "{$this->lang->ai->prompts->common}#{$prompt->id} $prompt->name {$this->lang->hyphen} " . $this->lang->ai->prompts->assignRole . " {$this->lang->hyphen} " . $this->lang->ai->prompts->common; $this->view->roleTemplates = $this->ai->getRoleTemplates(); $this->display(); } /** * Set data source of prompt, prompt editing step 3. * * @param int $promptID * @access public * @return void */ public function promptSelectDataSource($promptID) { if(!common::hasPriv('ai', 'designPrompt')) $this->loadModel('common')->deny('ai', 'designPrompt', false); $prompt = $this->ai->getPromptByID($promptID); if($_POST) { $data = fixer::input('post')->get(); $originalPrompt = clone $prompt; $prompt->module = $data->datagroup; $prompt->source = ",$data->datasource,"; $this->ai->updatePrompt($prompt, $originalPrompt); if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); if(!empty($data->jumpToNext)) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->inlink('promptSetPurpose', "promptID=$promptID"))); return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->inlink('promptSelectDataSource', "promptID=$promptID"))); } $this->view->activeDataSource = empty($prompt->module) ? current(array_keys($this->config->ai->dataSource)) : $prompt->module; $this->view->dataSource = $this->config->ai->dataSource; $this->view->prompt = $prompt; $this->view->promptID = $promptID; $this->view->lastActiveStep = $this->ai->getLastActiveStep($prompt); $this->view->title = "{$this->lang->ai->prompts->common}#{$prompt->id} $prompt->name {$this->lang->hyphen} " . $this->lang->ai->prompts->selectDataSource . " {$this->lang->hyphen} " . $this->lang->ai->prompts->common; $this->display(); } /** * Edit purpose and purpose elaboration of prompt, prompt editing step 4. * * @param int $promptID * @access public * @return void */ public function promptSetPurpose($promptID) { if(!common::hasPriv('ai', 'designPrompt')) $this->loadModel('common')->deny('ai', 'designPrompt', false); $prompt = $this->ai->getPromptByID($promptID); if($_SERVER['REQUEST_METHOD'] === 'POST') { if(!empty($_POST)) { $data = fixer::input('post')->get(); } else { $input = file_get_contents('php://input'); $data = json_decode($input); if(json_last_error() !== JSON_ERROR_NONE) { return $this->send(array('result' => 'fail', 'message' => 'JSON解析失败:' . json_last_error_msg())); } } if(!is_object($data)) $data = new stdClass(); $originalPrompt = clone $prompt; $prompt->purpose = isset($data->purpose) ? $data->purpose : ''; $prompt->elaboration = ''; $prompt->knowledgeLib = $data->knowledgeLib ?? ''; if(isset($data->fields)) { $fields = is_array($data->fields) ? $data->fields : array(); $this->ai->savePromptFields($promptID, $fields); if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); } $this->ai->updatePrompt($prompt, $originalPrompt); if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); if(!empty($data->jumpToNext)) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->inlink('promptSetTargetForm', "promptID=$promptID"))); return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->inlink('promptSetPurpose', "promptID=$promptID"))); } $knowledgeLibIds = []; if(!empty($prompt->knowledgeLib)) $knowledgeLibIds = explode(',', $prompt->knowledgeLib); $knowledgeLibs = (empty($knowledgeLibIds)) ? [] : $this->ai->getKnowledgeLibsByIDs($knowledgeLibIds); $currentPrompt = $prompt->purpose; if(!empty($prompt->elaboration)) $currentPrompt .= "\n\n" . $prompt->elaboration; $this->view->dataPreview = $this->ai->generateDemoDataPrompt($prompt->module, $prompt->source); $this->view->prompt = $prompt; $this->view->promptID = $promptID; $this->view->currentFields = $this->ai->getPromptFields($promptID); $this->view->currentPrompt = $currentPrompt; $this->view->knowledgeLibs = $knowledgeLibs; $this->view->lastActiveStep = $this->ai->getLastActiveStep($prompt); $this->view->title = "{$this->lang->ai->prompts->common}#{$prompt->id} $prompt->name {$this->lang->hyphen} " . $this->lang->ai->prompts->setPurpose . " {$this->lang->hyphen} " . $this->lang->ai->prompts->common; $this->display(); } /** * Set target form of prompt, prompt editing step 5. * * @param int $promptID * @access public * @return void */ public function promptSetTargetForm($promptID) { if(!common::hasPriv('ai', 'designPrompt')) $this->loadModel('common')->deny('ai', 'designPrompt', false); $prompt = $this->ai->getPromptByID($promptID); if($_POST) { $data = fixer::input('post')->get(); $originalPrompt = clone $prompt; $prompt->targetForm = $data->targetForm; $this->ai->updatePrompt($prompt, $originalPrompt); if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); if(!empty($data->goTesting)) // Go to testing object view. { $location = $this->ai->getTestingLocation($prompt); return $this->send(empty($location) ? array('result' => 'fail', 'target' => '#go-test-btn', 'message' => $this->lang->ai->prompts->goingTestingFail) : array('result' => 'success', 'target' => '#go-test-btn', 'msg' => $this->lang->ai->prompts->goingTesting, 'locate' => $location)); } if(!empty($data->jumpToNext)) $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->inlink('promptFinalize', "promptID=$promptID"))); return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->inlink('promptSetTargetForm', "promptID=$promptID"))); } $this->view->dataPreview = $this->ai->generateDemoDataPrompt($prompt->module, $prompt->source); $this->view->prompt = $prompt; $this->view->promptID = $promptID; $this->view->lastActiveStep = $this->ai->getLastActiveStep($prompt); $this->view->title = "{$this->lang->ai->prompts->common}#{$prompt->id} $prompt->name {$this->lang->hyphen} " . $this->lang->ai->prompts->setTargetForm . " {$this->lang->hyphen} " . $this->lang->ai->prompts->common; $this->display(); } /** * Edit additional information of prompt, final prompt editing step. * * @param int $promptID * @access public * @return void */ public function promptFinalize($promptID) { if(!common::hasPriv('ai', 'designPrompt')) $this->loadModel('common')->deny('ai', 'designPrompt', false); $prompt = $this->ai->getPromptByID($promptID); if($_POST) { $data = fixer::input('post')->get(); $originalPrompt = clone $prompt; $prompt->name = $data->name; $prompt->desc = $data->desc; $this->ai->updatePrompt($prompt, $originalPrompt); if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); if(!empty($data->jumpToNext)) $this->ai->togglePromptStatus($prompt, 'active'); if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); if(!empty($data->jumpToNext)) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->inlink('prompts'))); return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->inlink('promptFinalize', "promptID=$promptID"))); } $this->view->prompt = $prompt; $this->view->promptID = $promptID; $this->view->lastActiveStep = $this->ai->getLastActiveStep($prompt); $this->view->title = "{$this->lang->ai->prompts->common}#{$prompt->id} $prompt->name {$this->lang->hyphen} " . $this->lang->ai->prompts->finalize . " {$this->lang->hyphen} " . $this->lang->ai->prompts->common; $this->display(); } /** * Execute prompt on obejct, and redirect to target form page. * * @param int $promptId * @param int $objectId * @param string $mode Execution mode, 'testing' or 'normal'. * @access public * @return void */ public function promptExecute(int $promptId, int $objectId, string $mode = 'testing') { $prompt = $this->ai->getPromptByID($promptId); if(empty($prompt)) return $this->send(array('result' => 'fail', 'message' => sprintf($this->lang->ai->execute->failFormat, $this->lang->ai->execute->failReasons['noPrompt']))); $object = $this->ai->getObjectForPromptById($prompt, $objectId); if(empty($object)) return $this->send(array('result' => 'fail', 'message' => sprintf($this->lang->ai->execute->failFormat, $this->lang->ai->execute->failReasons['noObjectData']))); list($objectData, $rawObject) = $object; list($location, $stop) = $this->ai->getTargetFormLocation($prompt, $rawObject); if(!empty($stop)) return header("location: $location", true, 302); /* Execute prompt and catch exceptions. */ try { $response = $this->ai->executePrompt($prompt, $object); } catch (AIResponseException $e) { $output = array('result' => 'fail', 'message' => sprintf($this->lang->ai->execute->failFormat, $e->getMessage())); /* Audition shall quit on such exception. */ if(isset($_SESSION['auditPrompt']) && time() - $_SESSION['auditPrompt']['time'] < 10 * 60) { $output['locate'] = $this->inlink('promptAudit', "promptID=$promptId&objectId=$objectId&exit=true"); } return $this->send($output); } if(is_int($response)) return $this->send(array('result' => 'fail', 'message' => sprintf($this->lang->ai->execute->failFormat, $this->lang->ai->execute->executeErrors["$response"]) . (empty($this->ai->errors) ? '' : implode(', ', $this->ai->errors)))); if(empty($response)) return $this->send(array('result' => 'fail', 'message' => sprintf($this->lang->ai->execute->failFormat, $this->lang->ai->execute->failReasons['noResponse']))); if(!empty($prompt->targetForm)) { $targetFormPaths = explode('.', $prompt->targetForm); $response['targetFormName'] = $this->lang->ai->targetForm[$targetFormPaths[0]][$targetFormPaths[1]]; $response['dataPropNames'] = $this->lang->ai->dataSource[$prompt->module]; } $fields = array_values($this->ai->getPromptFields($promptId)); if($fields) { $response['fields'] = $fields; $response['formConfig'] = []; $response['formConfig']['title'] = $this->lang->ai->prompts->formDefaultTitle; $response['formConfig']['submitBtnText'] = $this->lang->ai->prompts->formSubmitBtnText; } $response['objectID'] = $objectId; $response['objectType'] = $prompt->module; $response['knowledgeLib'] = $prompt->knowledgeLib; $response['object'] = $objectData; $response['formLocation'] = $location; $response['model'] = $prompt->model; return $this->send(array('result' => 'success', 'callback' => array('name' => 'parent.executeZentaoPrompt', 'params' => array($response, $mode === 'testing')))); } /** * Reset prompt execution. * * @param bool $failed Whether the execution failed, triggers error message. * @access public * @return void */ public function promptExecutionReset($failed = false) { /* Reset session. */ unset($_SESSION['aiPrompt']); unset($_SESSION['auditPrompt']); if($failed) return $this->send(array('result' => 'fail', 'message' => sprintf($this->lang->ai->execute->failFormat, $this->lang->ai->execute->failReasons['noTargetForm']), 'locate' => isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '')); return $this->send(array('result' => 'success')); } /** * Audit prompt modal. * * @param int $promptId * @param int $objectId * @param bool $exit * @access public * @return void|int */ public function promptAudit(int $promptId, int $objectId, bool $exit = false) { if(!common::hasPriv('ai', 'designPrompt')) $this->loadModel('common')->deny('ai', 'designPrompt', false); if(!empty($exit)) { unset($_SESSION['auditPrompt']); return $this->send(array('result' => 'success', 'load' => $this->inlink('promptview', "promptID=$promptId"))); } $prompt = $this->ai->getPromptByID($promptId); if($_POST) { $data = fixer::input('post')->get(); $originalPrompt = clone $prompt; $prompt->role = $data->role; $prompt->characterization = $data->characterization; $prompt->purpose = $data->purpose; $prompt->elaboration = ''; $this->ai->updatePrompt($prompt, $originalPrompt); if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); if(empty($data->backLocation)) { $response = array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true); } else { $response = array('result' => 'success', 'message' => $this->lang->saveSuccess, 'callback' => array('name' => 'getTestingLocation', 'params' => array($promptId))); } $this->sendSuccess($response); } $objectForPrompt = $this->ai->getObjectForPromptById($prompt, $objectId); if(empty($objectForPrompt)) return $this->send(array('result' => 'fail', 'message' => $this->lang->ai->execute->fail)); list($objectData, $object) = $objectForPrompt; $currentPrompt = $prompt->purpose; if(!empty($prompt->elaboration)) $currentPrompt .= "\n\n" . $prompt->elaboration; $this->view->prompt = $prompt; $this->view->currentPrompt = $currentPrompt; $this->view->object = $object; $this->view->dataPrompt = $this->ai->serializeDataToPrompt($prompt->module, $prompt->source, $objectData); $this->display(); } /** * Publish prompt, set status to active. * * @param int $id * @param bool $backToTestingLocation * @access public * @return void */ public function promptPublish($id, $backToTestingLocation = false) { unset($_SESSION['auditPrompt']); $this->ai->togglePromptStatus($id, 'active'); if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); if($backToTestingLocation) { return $this->send(array('result' => 'success', 'message' => $this->lang->ai->prompts->action->publishSuccess, 'load' => $this->inlink('promptview', "id=$id"))); } return $this->send(array('result' => 'success', 'load' => true, 'message' => $this->lang->ai->prompts->action->publishSuccess)); } /** * Unpublish prompt, set status to draft. * * @param int $id * @access public * @return void */ public function promptUnpublish($id) { $this->ai->togglePromptStatus($id, 'draft'); if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); return $this->send(array('result' => 'success', 'message' => $this->lang->ai->prompts->action->unpublishSuccess, 'load' => true)); } /** * Get testing location. * * @param int $promptID * @param string $module * @param string $targetForm * @access public * @return void */ public function ajaxTestPrompt($promptID) { $prompt = $this->ai->getPromptByID($promptID); if(empty($prompt)) return $this->send(array('result' => 'fail', 'message' => sprintf($this->lang->ai->execute->failFormat, $this->lang->ai->execute->failReasons['noPrompt']))); $object = $this->ai->getTestPromptData($prompt); list($objectData, $showText) = $object; /* Execute prompt and catch exceptions. */ try { $response = $this->ai->executePrompt($prompt, $object); } catch (AIResponseException $e) { $output = array('result' => 'fail', 'message' => sprintf($this->lang->ai->execute->failFormat, $e->getMessage())); /* Audition shall quit on such exception. */ if(isset($_SESSION['auditPrompt']) && time() - $_SESSION['auditPrompt']['time'] < 10 * 60) { $output['locate'] = $this->inlink('promptAudit', "promptID=$promptID&objectId=0&exit=true"); } return $this->send($output); } if(is_int($response)) return $this->send(array('result' => 'fail', 'message' => sprintf($this->lang->ai->execute->failFormat, $this->lang->ai->execute->executeErrors["$response"]) . (empty($this->ai->errors) ? '' : implode(', ', $this->ai->errors)))); if(empty($response)) return $this->send(array('result' => 'fail', 'message' => sprintf($this->lang->ai->execute->failFormat, $this->lang->ai->execute->failReasons['noResponse']))); if(!empty($prompt->targetForm) && $prompt->targetForm != 'empty') { $targetFormPaths = explode('.', $prompt->targetForm); $response['targetFormName'] = $this->lang->ai->targetForm[$targetFormPaths[0]][$targetFormPaths[1]]; $response['dataPropNames'] = $this->lang->ai->dataSource[$prompt->module]; } $response['objectType'] = $prompt->module; $response['object'] = $objectData; $response['formLocation'] = ''; $response['model'] = $prompt->model; $response['promptAudit'] = $this->ai->isClickable($prompt, 'promptaudit'); $response['content'] = $showText; return $this->send(array('result' => 'success', 'data' => $response)); } /** * Return html element for the role template list. * This is used in prompt designing step 2. * Return html will deserialize in the front end js and replace the original role template list. * * @access public * @return void */ public function roleTemplates() { if($_POST) { $data = fixer::input('post')->get(); $method = $data->method; $result = false; $message = ''; switch ($method) { case 'create': $result = $this->ai->createRoleTemplate($data->role, $data->characterization); $message = $result ? $this->lang->saveSuccess : $this->lang->ai->saveFail; break; case 'delete': $result = $this->ai->deleteRoleTemplate($data->id); $message = $result ? $this->lang->ai->prompts->roleDelSuccess : $this->lang->ai->saveFail; break; case 'edit': $result = $this->ai->updateRoleTemplate($data->id, $data->role, $data->characterization); $message = $result ? $this->lang->saveSuccess : $this->lang->ai->saveFail; break; } $roleTemplates = $this->ai->getRoleTemplates(); $roleTemplatesArray = array_values((array)$roleTemplates); return $this->send(array( 'result' => $result ? 'success' : 'fail', 'message' => $message, 'data' => array( 'roleTemplates' => $roleTemplatesArray, 'method' => $method ) )); } } }