diff --git a/appinfo/routes.php b/appinfo/routes.php index 6f4b83ee..6f8ca95d 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -19,6 +19,18 @@ ['name' => 'assistant#getAssistantStandalonePage', 'url' => '/', 'verb' => 'GET'], ['name' => 'preview#getFileImage', 'url' => '/preview', 'verb' => 'GET'], + ], + 'ocs' => [ + ['name' => 'assistantApi#getAvailableTaskTypes', 'url' => '/api/{apiVersion}/task-types', 'verb' => 'GET', 'requirements' => $requirements], + ['name' => 'assistantApi#getUserTasks', 'url' => '/api/{apiVersion}/tasks', 'verb' => 'GET', 'requirements' => $requirements], + ['name' => 'assistantApi#parseTextFromFile', 'url' => '/api/{apiVersion}/parse-file', 'verb' => 'POST', 'requirements' => $requirements], + ['name' => 'assistantApi#notifyWhenReady', 'url' => '/api/{apiVersion}/task/{ocpTaskId}/notify', 'verb' => 'POST', 'requirements' => $requirements], + ['name' => 'assistantApi#uploadInputFile', 'url' => '/api/{apiVersion}/input-file', 'verb' => 'POST', 'requirements' => $requirements], + ['name' => 'assistantApi#displayUserFile', 'url' => '/api/{apiVersion}/file/{fileId}/display', 'verb' => 'GET', 'requirements' => $requirements], + ['name' => 'assistantApi#getUserFileInfo', 'url' => '/api/{apiVersion}/file/{fileId}/info', 'verb' => 'GET', 'requirements' => $requirements], + ['name' => 'assistantApi#shareOutputFile', 'url' => '/api/{apiVersion}/task/{ocpTaskId}/file/{fileId}/share', 'verb' => 'POST', 'requirements' => $requirements], + ['name' => 'assistantApi#getOutputFilePreview', 'url' => '/api/{apiVersion}/task/{ocpTaskId}/output-file/{fileId}/preview', 'verb' => 'GET', 'requirements' => $requirements], + ['name' => 'assistantApi#getOutputFile', 'url' => '/api/{apiVersion}/task/{ocpTaskId}/output-file/{fileId}/download', 'verb' => 'GET', 'requirements' => $requirements], ['name' => 'chattyLLM#newSession', 'url' => '/chat/new_session', 'verb' => 'PUT'], ['name' => 'chattyLLM#updateSessionTitle', 'url' => '/chat/update_session', 'verb' => 'PATCH'], @@ -34,16 +46,4 @@ ['name' => 'chattyLLM#generateTitle', 'url' => '/chat/generate_title', 'verb' => 'GET'], ['name' => 'chattyLLM#checkTitleGenerationTask', 'url' => '/chat/check_title_generation', 'verb' => 'GET'], ], - 'ocs' => [ - ['name' => 'assistantApi#getAvailableTaskTypes', 'url' => '/api/{apiVersion}/task-types', 'verb' => 'GET', 'requirements' => $requirements], - ['name' => 'assistantApi#getUserTasks', 'url' => '/api/{apiVersion}/tasks', 'verb' => 'GET', 'requirements' => $requirements], - ['name' => 'assistantApi#parseTextFromFile', 'url' => '/api/{apiVersion}/parse-file', 'verb' => 'POST', 'requirements' => $requirements], - ['name' => 'assistantApi#notifyWhenReady', 'url' => '/api/{apiVersion}/task/{ocpTaskId}/notify', 'verb' => 'POST', 'requirements' => $requirements], - ['name' => 'assistantApi#uploadInputFile', 'url' => '/api/{apiVersion}/input-file', 'verb' => 'POST', 'requirements' => $requirements], - ['name' => 'assistantApi#displayUserFile', 'url' => '/api/{apiVersion}/file/{fileId}/display', 'verb' => 'GET', 'requirements' => $requirements], - ['name' => 'assistantApi#getUserFileInfo', 'url' => '/api/{apiVersion}/file/{fileId}/info', 'verb' => 'GET', 'requirements' => $requirements], - ['name' => 'assistantApi#shareOutputFile', 'url' => '/api/{apiVersion}/task/{ocpTaskId}/file/{fileId}/share', 'verb' => 'POST', 'requirements' => $requirements], - ['name' => 'assistantApi#getOutputFilePreview', 'url' => '/api/{apiVersion}/task/{ocpTaskId}/output-file/{fileId}/preview', 'verb' => 'GET', 'requirements' => $requirements], - ['name' => 'assistantApi#getOutputFile', 'url' => '/api/{apiVersion}/task/{ocpTaskId}/output-file/{fileId}/download', 'verb' => 'GET', 'requirements' => $requirements], - ], ]; diff --git a/lib/Controller/ChattyLLMController.php b/lib/Controller/ChattyLLMController.php index 421c2f9e..ef7f1003 100644 --- a/lib/Controller/ChattyLLMController.php +++ b/lib/Controller/ChattyLLMController.php @@ -12,13 +12,14 @@ use OCA\Assistant\Db\ChattyLLM\MessageMapper; use OCA\Assistant\Db\ChattyLLM\Session; use OCA\Assistant\Db\ChattyLLM\SessionMapper; -use OCP\AppFramework\Controller; +use OCA\Assistant\ResponseDefinitions; use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Db\MultipleObjectsReturnedException; use OCP\AppFramework\Http; use OCP\AppFramework\Http\Attribute\NoAdminRequired; use OCP\AppFramework\Http\Attribute\OpenAPI; use OCP\AppFramework\Http\JSONResponse; +use OCP\AppFramework\OCSController; use OCP\Exceptions\AppConfigTypeConflictException; use OCP\IAppConfig; use OCP\IL10N; @@ -34,8 +35,13 @@ use OCP\TaskProcessing\TaskTypes\TextToTextChat; use Psr\Log\LoggerInterface; -#[OpenAPI(scope: OpenAPI::SCOPE_IGNORE)] -class ChattyLLMController extends Controller { +/** + * @psalm-import-type AssistantChatSession from ResponseDefinitions + * @psalm-import-type AssistantChatMessage from ResponseDefinitions + * @psalm-import-type AssistantChatAgencyMessage from ResponseDefinitions + * @psalm-import-type AssistantChatSessionCheck from ResponseDefinitions + */ +class ChattyLLMController extends OCSController { private array $agencyActionData; public function __construct( @@ -98,13 +104,20 @@ private function improveAgencyActionNames(array $actions): array { } /** + * Create chat session + * * Create a new chat session, add a system message with user instructions * - * @param int $timestamp - * @param ?string $title - * @return JSONResponse + * @param int $timestamp The session creation date + * @param ?string $title The session title + * @return JSONResponse|JSONResponse + * @throws AppConfigTypeConflictException + * + * 200: Chat session has been successfully created + * 401: User is either not logged in or not found */ #[NoAdminRequired] + #[OpenAPI(scope: OpenAPI::SCOPE_DEFAULT, tags: ['chat_api'])] public function newSession(int $timestamp, ?string $title = null): JSONResponse { if ($this->userId === null) { return new JSONResponse(['error' => $this->l10n->t('User not logged in')], Http::STATUS_UNAUTHORIZED); @@ -137,7 +150,7 @@ public function newSession(int $timestamp, ?string $title = null): JSONResponse $this->messageMapper->insert($systemMsg); return new JSONResponse([ - 'session' => $session, + 'session' => $session->jsonSerialize(), ]); } catch (\OCP\DB\Exception|\RuntimeException $e) { $this->logger->warning('Failed to create a chat session', ['exception' => $e]); @@ -146,13 +159,19 @@ public function newSession(int $timestamp, ?string $title = null): JSONResponse } /** - * Update the title of the chat session + * Update session title * - * @param integer $sessionId - * @param string $title - * @return JSONResponse + * Update the title of a chat session + * + * @param integer $sessionId The chat session ID + * @param string $title The new chat session title + * @return JSONResponse|JSONResponse + * + * 200: The title has been updated successfully + * 401: Not logged in */ #[NoAdminRequired] + #[OpenAPI(scope: OpenAPI::SCOPE_DEFAULT, tags: ['chat_api'])] public function updateSessionTitle(int $sessionId, string $title): JSONResponse { if ($this->userId === null) { return new JSONResponse(['error' => $this->l10n->t('User not logged in')], Http::STATUS_UNAUTHORIZED); @@ -168,12 +187,18 @@ public function updateSessionTitle(int $sessionId, string $title): JSONResponse } /** + * Delete a chat session + * * Delete a chat session by ID * - * @param integer $sessionId - * @return JSONResponse + * @param integer $sessionId The session ID + * @return JSONResponse|JSONResponse + * + * 200: The session has been deleted successfully + * 401: Not logged in */ #[NoAdminRequired] + #[OpenAPI(scope: OpenAPI::SCOPE_DEFAULT, tags: ['chat_api'])] public function deleteSession(int $sessionId): JSONResponse { if ($this->userId === null) { return new JSONResponse(['error' => $this->l10n->t('User not logged in')], Http::STATUS_UNAUTHORIZED); @@ -190,11 +215,17 @@ public function deleteSession(int $sessionId): JSONResponse { } /** - * Get all chat sessions for the user + * Get chat sessions * - * @return JSONResponse + * Get all chat sessions for the current user + * + * @return JSONResponse, array{}>|JSONResponse + * + * 200: The session list has been obtained successfully + * 401: Not logged in */ #[NoAdminRequired] + #[OpenAPI(scope: OpenAPI::SCOPE_DEFAULT, tags: ['chat_api'])] public function getSessions(): JSONResponse { if ($this->userId === null) { return new JSONResponse(['error' => $this->l10n->t('User not logged in')], Http::STATUS_UNAUTHORIZED); @@ -210,16 +241,24 @@ public function getSessions(): JSONResponse { } /** + * Add a message + * * Add a new chat message to the session * - * @param int $sessionId - * @param string $role - * @param string $content - * @param int $timestamp - * @param bool $firstHumanMessage - * @return JSONResponse + * @param int $sessionId The chat session ID + * @param string $role Role of the message (human, assistant etc...) + * @param string $content Content of the message + * @param int $timestamp Date of the message + * @param bool $firstHumanMessage Is it the first human message of the session? + * @return JSONResponse|JSONResponse + * + * 200: The session list has been obtained successfully + * 401: Not logged in + * 404: Session was not found + * 400: Message is malformed */ #[NoAdminRequired] + #[OpenAPI(scope: OpenAPI::SCOPE_DEFAULT, tags: ['chat_api'])] public function newMessage(int $sessionId, string $role, string $content, int $timestamp, bool $firstHumanMessage = false): JSONResponse { if ($this->userId === null) { return new JSONResponse(['error' => $this->l10n->t('User not logged in')], Http::STATUS_UNAUTHORIZED); @@ -255,7 +294,7 @@ public function newMessage(int $sessionId, string $role, string $content, int $t ); } - return new JSONResponse($message); + return new JSONResponse($message->jsonSerialize()); } catch (\OCP\DB\Exception $e) { $this->logger->warning('Failed to add a chat message', ['exception' => $e]); return new JSONResponse(['error' => $this->l10n->t('Failed to add a chat message')], Http::STATUS_INTERNAL_SERVER_ERROR); @@ -263,14 +302,21 @@ public function newMessage(int $sessionId, string $role, string $content, int $t } /** + * Get session messages + * * Get chat messages for the session without the system message * - * @param int $sessionId - * @param int $limit - * @param int $cursor - * @return JSONResponse + * @param int $sessionId The session ID + * @param int $limit The max number of messages to return + * @param int $cursor The index of the first result to return + * @return JSONResponse, array{}>|JSONResponse + * + * 200: The message list has been successfully obtained + * 401: Not logged in + * 404: The session was not found */ #[NoAdminRequired] + #[OpenAPI(scope: OpenAPI::SCOPE_DEFAULT, tags: ['chat_api'])] public function getMessages(int $sessionId, int $limit = 20, int $cursor = 0): JSONResponse { if ($this->userId === null) { return new JSONResponse(['error' => $this->l10n->t('User not logged in')], Http::STATUS_UNAUTHORIZED); @@ -282,12 +328,13 @@ public function getMessages(int $sessionId, int $limit = 20, int $cursor = 0): J return new JSONResponse(['error' => $this->l10n->t('Session not found')], Http::STATUS_NOT_FOUND); } + /** @var list $messages */ $messages = $this->messageMapper->getMessages($sessionId, $cursor, $limit); if ($messages[0]->getRole() === 'system') { array_shift($messages); } - return new JSONResponse($messages); + return new JSONResponse(array_map(static function (Message $message) { return $message->jsonSerialize(); }, $messages)); } catch (\OCP\DB\Exception $e) { $this->logger->warning('Failed to get chat messages', ['exception' => $e]); return new JSONResponse(['error' => $this->l10n->t('Failed to get chat messages')], Http::STATUS_INTERNAL_SERVER_ERROR); @@ -295,13 +342,20 @@ public function getMessages(int $sessionId, int $limit = 20, int $cursor = 0): J } /** + * Delete a message + * * Delete a chat message by ID * - * @param integer $messageId - * @param integer $sessionId - * @return JSONResponse + * @param integer $messageId The message ID + * @param integer $sessionId The session ID + * @return JSONResponse|JSONResponse + * + * 200: The message has been successfully deleted + * 401: Not logged in + * 404: The session was not found */ #[NoAdminRequired] + #[OpenAPI(scope: OpenAPI::SCOPE_DEFAULT, tags: ['chat_api'])] public function deleteMessage(int $messageId, int $sessionId): JSONResponse { if ($this->userId === null) { return new JSONResponse(['error' => $this->l10n->t('User not logged in')], Http::STATUS_UNAUTHORIZED); @@ -322,17 +376,25 @@ public function deleteMessage(int $messageId, int $sessionId): JSONResponse { } /** - * Schedule a task to generate a new message for the session + * Generate a new assistant message * - * @param integer $sessionId - * @param int $agencyConfirm - * @return JSONResponse + * Schedule a task to generate a new message for a session + * + * @param integer $sessionId The session ID + * @param int $agencyConfirm Potential agency sensitive actions confirmation (1: accept, 0: reject) + * @return JSONResponse|JSONResponse * @throws AppConfigTypeConflictException * @throws DoesNotExistException * @throws MultipleObjectsReturnedException * @throws \OCP\DB\Exception + * + * 200: The task has been successfully scheduled + * 401: Not logged in + * 404: Session was not found + * 400: Task was not scheduled */ #[NoAdminRequired] + #[OpenAPI(scope: OpenAPI::SCOPE_DEFAULT, tags: ['chat_api'])] public function generateForSession(int $sessionId, int $agencyConfirm = 0): JSONResponse { if ($this->userId === null) { return new JSONResponse(['error' => $this->l10n->t('User not logged in')], Http::STATUS_UNAUTHORIZED); @@ -384,18 +446,26 @@ public function generateForSession(int $sessionId, int $agencyConfirm = 0): JSON } /** - * Delete all messages since the given message ID and then - * schedule a task to generate a new message for the session + * Regenerate response for a message * - * @param int $sessionId - * @param int $messageId - * @return JSONResponse + * Delete the message with the given message ID and all following ones, + * then schedule a task to generate a new message for the session + * + * @param int $sessionId The chat session ID + * @param int $messageId The chat message ID + * @return JSONResponse|JSONResponse * @throws AppConfigTypeConflictException * @throws DoesNotExistException * @throws MultipleObjectsReturnedException * @throws \OCP\DB\Exception + * + * 200: The task has been successfully scheduled + * 401: Not logged in + * 404: Session was not found + * 400: Task was not scheduled */ #[NoAdminRequired] + #[OpenAPI(scope: OpenAPI::SCOPE_DEFAULT, tags: ['chat_api'])] public function regenerateForSession(int $sessionId, int $messageId): JSONResponse { if ($this->userId === null) { return new JSONResponse(['error' => $this->l10n->t('User not logged in')], Http::STATUS_UNAUTHORIZED); @@ -421,14 +491,21 @@ public function regenerateForSession(int $sessionId, int $messageId): JSONRespon * * Used by the frontend to poll a generation task status. If the task succeeds, a new message is stored and returned. * - * @param int $taskId - * @param int $sessionId - * @return JSONResponse + * @param int $taskId The message generation task ID + * @param int $sessionId The chat session ID + * @return JSONResponse|JSONResponse|JSONResponse * @throws DoesNotExistException * @throws MultipleObjectsReturnedException * @throws \OCP\DB\Exception + * + * 200: The task was successful, a message has been generated + * 401: Not logged in + * 404: Session was not found + * 400: Task processing failed + * 417: The task is still running or has not been picked up yet */ #[NoAdminRequired] + #[OpenAPI(scope: OpenAPI::SCOPE_DEFAULT, tags: ['chat_api'])] public function checkMessageGenerationTask(int $taskId, int $sessionId): JSONResponse { if ($this->userId === null) { return new JSONResponse(['error' => $this->l10n->t('User not logged in')], Http::STATUS_UNAUTHORIZED); @@ -475,14 +552,20 @@ public function checkMessageGenerationTask(int $taskId, int $sessionId): JSONRes * * Used by the frontend to determine if it should poll a generation task status. * - * @param int $sessionId - * @return JSONResponse + * @param int $sessionId The chat session ID + * @return JSONResponse|JSONResponse * @throws DoesNotExistException * @throws MultipleObjectsReturnedException * @throws \JsonException * @throws \OCP\DB\Exception + * + * 200: The session status has been successfully obtained + * 401: Not logged in + * 404: Session was not found + * 400: Task processing failed, impossible to check the related tasks */ #[NoAdminRequired] + #[OpenAPI(scope: OpenAPI::SCOPE_DEFAULT, tags: ['chat_api'])] public function checkSession(int $sessionId): JSONResponse { if ($this->userId === null) { return new JSONResponse(['error' => $this->l10n->t('User not logged in')], Http::STATUS_UNAUTHORIZED); @@ -511,11 +594,13 @@ public function checkSession(int $sessionId): JSONResponse { $pendingActions = json_decode($pendingActions); $pendingActions = $this->improveAgencyActionNames($pendingActions); } + /** @var ?array $p */ + $p = $pendingActions; $responseData = [ 'messageTaskId' => null, 'titleTaskId' => null, 'sessionTitle' => $session->getTitle(), - 'sessionAgencyPendingActions' => $pendingActions, + 'sessionAgencyPendingActions' => $p, ]; if (!empty($messageTasks)) { $task = array_pop($messageTasks); @@ -529,16 +614,24 @@ public function checkSession(int $sessionId): JSONResponse { } /** - * Schedule a task to generate a title for the chat session + * Generate a session title * - * @param integer $sessionId - * @return JSONResponse + * Schedule a task to generate a title for a chat session + * + * @param integer $sessionId The chat session ID + * @return JSONResponse|JSONResponse * @throws AppConfigTypeConflictException * @throws DoesNotExistException * @throws MultipleObjectsReturnedException * @throws \OCP\DB\Exception + * + * 200: The task has been successfully scheduled + * 401: Not logged in + * 404: Session was not found + * 400: Task was not scheduled */ #[NoAdminRequired] + #[OpenAPI(scope: OpenAPI::SCOPE_DEFAULT, tags: ['chat_api'])] public function generateTitle(int $sessionId): JSONResponse { if ($this->userId === null) { return new JSONResponse(['error' => $this->l10n->t('User not logged in')], Http::STATUS_UNAUTHORIZED); @@ -589,7 +682,25 @@ public function generateTitle(int $sessionId): JSONResponse { } } + /** + * Check the status of a title generation task + * + * Used by the frontend to poll a title generation task status. If the task succeeds, the new title is set and returned. + * + * @param int $taskId The title generation task ID + * @param int $sessionId The chat session ID + * @return JSONResponse|JSONResponse|JSONResponse + * @throws AppConfigTypeConflictException + * @throws \OCP\DB\Exception 200: The task was successful, a message has been generated + * + * 200: Title has been successfully generated + * 401: Not logged in + * 404: Session was not found + * 400: Task processing failed + * 417: The task is still running or has not been picked up yet + */ #[NoAdminRequired] + #[OpenAPI(scope: OpenAPI::SCOPE_DEFAULT, tags: ['chat_api'])] public function checkTitleGenerationTask(int $taskId, int $sessionId): JSONResponse { if ($this->userId === null) { return new JSONResponse(['error' => $this->l10n->t('User not logged in')], Http::STATUS_UNAUTHORIZED); @@ -682,7 +793,7 @@ private function checkIfSessionIsThinking(string $customId): void { * @param array $history * @param int $sessionId * @param bool $isMessage whether we want to generate a message or a session title - * @return int|null + * @return int * @throws Exception * @throws PreConditionNotMetException * @throws UnauthorizedException @@ -690,7 +801,7 @@ private function checkIfSessionIsThinking(string $customId): void { */ private function scheduleLLMChatTask( string $newPrompt, string $systemPrompt, array $history, int $sessionId, bool $isMessage = true, - ): ?int { + ): int { $customId = ($isMessage ? 'chatty-llm:' : 'chatty-title:') . $sessionId; @@ -702,7 +813,7 @@ private function scheduleLLMChatTask( ]; $task = new Task(TextToTextChat::ID, $input, Application::APP_ID . ':chatty-llm', $this->userId, $customId); $this->taskProcessingManager->scheduleTask($task); - return $task->getId(); + return $task->getId() ?? 0; } /** @@ -712,13 +823,13 @@ private function scheduleLLMChatTask( * @param int $confirmation * @param string $conversationToken * @param int $sessionId - * @return int|null + * @return int * @throws Exception * @throws PreConditionNotMetException * @throws UnauthorizedException * @throws ValidationException */ - private function scheduleAgencyTask(string $content, int $confirmation, string $conversationToken, int $sessionId): ?int { + private function scheduleAgencyTask(string $content, int $confirmation, string $conversationToken, int $sessionId): int { $customId = 'chatty-llm:' . $sessionId; $this->checkIfSessionIsThinking($customId); $taskInput = [ @@ -734,6 +845,6 @@ private function scheduleAgencyTask(string $content, int $confirmation, string $ $customId ); $this->taskProcessingManager->scheduleTask($task); - return $task->getId(); + return $task->getId() ?? 0; } } diff --git a/lib/ResponseDefinitions.php b/lib/ResponseDefinitions.php index 0f536cbf..c9470dfd 100644 --- a/lib/ResponseDefinitions.php +++ b/lib/ResponseDefinitions.php @@ -47,6 +47,35 @@ * scheduledAt: int|null, * startedAt: int|null, * } + * + * @psalm-type AssistantChatSession = array{ + * id: int, + * user_id: string, + * title: ?string, + * timestamp: ?int, + * agency_conversation_token: ?string, + * agency_pending_actions: ?string, + * } + * + * @psalm-type AssistantChatMessage = array{ + * id: int, + * session_id: int, + * role: string, + * content: string, + * timestamp: int, + * ocp_task_id: int, + * } + * + * @psalm-type AssistantChatAgencyMessage = AssistantChatMessage&array{ + * sessionAgencyPendingActions: array, + * } + * + * @psalm-type AssistantChatSessionCheck = array{ + * messageTaskId: ?int, + * titleTaskId: ?int, + * sessionTitle: ?string, + * sessionAgencyPendingActions: ?array, + * } */ class ResponseDefinitions { } diff --git a/openapi.json b/openapi.json index b1fc94fc..0a34bb18 100644 --- a/openapi.json +++ b/openapi.json @@ -20,6 +20,131 @@ } }, "schemas": { + "ChatAgencyMessage": { + "allOf": [ + { + "$ref": "#/components/schemas/ChatMessage" + }, + { + "type": "object", + "required": [ + "sessionAgencyPendingActions" + ], + "properties": { + "sessionAgencyPendingActions": { + "type": "object", + "additionalProperties": { + "type": "object" + } + } + } + } + ] + }, + "ChatMessage": { + "type": "object", + "required": [ + "id", + "session_id", + "role", + "content", + "timestamp", + "ocp_task_id" + ], + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "session_id": { + "type": "integer", + "format": "int64" + }, + "role": { + "type": "string" + }, + "content": { + "type": "string" + }, + "timestamp": { + "type": "integer", + "format": "int64" + }, + "ocp_task_id": { + "type": "integer", + "format": "int64" + } + } + }, + "ChatSession": { + "type": "object", + "required": [ + "id", + "user_id", + "title", + "timestamp", + "agency_conversation_token", + "agency_pending_actions" + ], + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "user_id": { + "type": "string" + }, + "title": { + "type": "string", + "nullable": true + }, + "timestamp": { + "type": "integer", + "format": "int64", + "nullable": true + }, + "agency_conversation_token": { + "type": "string", + "nullable": true + }, + "agency_pending_actions": { + "type": "string", + "nullable": true + } + } + }, + "ChatSessionCheck": { + "type": "object", + "required": [ + "messageTaskId", + "titleTaskId", + "sessionTitle", + "sessionAgencyPendingActions" + ], + "properties": { + "messageTaskId": { + "type": "integer", + "format": "int64", + "nullable": true + }, + "titleTaskId": { + "type": "integer", + "format": "int64", + "nullable": true + }, + "sessionTitle": { + "type": "string", + "nullable": true + }, + "sessionAgencyPendingActions": { + "type": "object", + "nullable": true, + "additionalProperties": { + "type": "object" + } + } + } + }, "OCSMeta": { "type": "object", "required": [ @@ -1505,6 +1630,1668 @@ } } } + }, + "/ocs/v2.php/apps/assistant/chat/new_session": { + "put": { + "operationId": "chattyllm-new-session", + "summary": "Create chat session", + "description": "Create a new chat session, add a system message with user instructions", + "tags": [ + "chat_api" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "timestamp" + ], + "properties": { + "timestamp": { + "type": "integer", + "format": "int64", + "description": "The session creation date" + }, + "title": { + "type": "string", + "nullable": true, + "description": "The session title" + } + } + } + } + } + }, + "parameters": [ + { + "name": "OCS-APIRequest", + "in": "header", + "description": "Required to be true for the API request to pass", + "required": true, + "schema": { + "type": "boolean", + "default": true + } + } + ], + "responses": { + "200": { + "description": "Chat session has been successfully created", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "session" + ], + "properties": { + "session": { + "$ref": "#/components/schemas/ChatSession" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } + }, + "text/plain": { + "schema": { + "type": "string" + } + } + } + }, + "401": { + "description": "User is either not logged in or not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/assistant/chat/update_session": { + "patch": { + "operationId": "chattyllm-update-session-title", + "summary": "Update session title", + "description": "Update the title of a chat session", + "tags": [ + "chat_api" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "sessionId", + "title" + ], + "properties": { + "sessionId": { + "type": "integer", + "format": "int64", + "description": "The chat session ID" + }, + "title": { + "type": "string", + "description": "The new chat session title" + } + } + } + } + } + }, + "parameters": [ + { + "name": "OCS-APIRequest", + "in": "header", + "description": "Required to be true for the API request to pass", + "required": true, + "schema": { + "type": "boolean", + "default": true + } + } + ], + "responses": { + "200": { + "description": "The title has been updated successfully", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } + } + } + }, + "401": { + "description": "Not logged in", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/assistant/chat/delete_session": { + "delete": { + "operationId": "chattyllm-delete-session", + "summary": "Delete a chat session", + "description": "Delete a chat session by ID", + "tags": [ + "chat_api" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "sessionId", + "in": "query", + "description": "The session ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "OCS-APIRequest", + "in": "header", + "description": "Required to be true for the API request to pass", + "required": true, + "schema": { + "type": "boolean", + "default": true + } + } + ], + "responses": { + "200": { + "description": "The session has been deleted successfully", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } + } + } + }, + "401": { + "description": "Not logged in", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/assistant/chat/sessions": { + "get": { + "operationId": "chattyllm-get-sessions", + "summary": "Get chat sessions", + "description": "Get all chat sessions for the current user", + "tags": [ + "chat_api" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "OCS-APIRequest", + "in": "header", + "description": "Required to be true for the API request to pass", + "required": true, + "schema": { + "type": "boolean", + "default": true + } + } + ], + "responses": { + "200": { + "description": "The session list has been obtained successfully", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ChatSession" + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } + } + } + }, + "401": { + "description": "Not logged in", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/assistant/chat/new_message": { + "put": { + "operationId": "chattyllm-new-message", + "summary": "Add a message", + "description": "Add a new chat message to the session", + "tags": [ + "chat_api" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "sessionId", + "role", + "content", + "timestamp" + ], + "properties": { + "sessionId": { + "type": "integer", + "format": "int64", + "description": "The chat session ID" + }, + "role": { + "type": "string", + "description": "Role of the message (human, assistant etc...)" + }, + "content": { + "type": "string", + "description": "Content of the message" + }, + "timestamp": { + "type": "integer", + "format": "int64", + "description": "Date of the message" + }, + "firstHumanMessage": { + "type": "boolean", + "default": false, + "description": "Is it the first human message of the session?" + } + } + } + } + } + }, + "parameters": [ + { + "name": "OCS-APIRequest", + "in": "header", + "description": "Required to be true for the API request to pass", + "required": true, + "schema": { + "type": "boolean", + "default": true + } + } + ], + "responses": { + "200": { + "description": "The session list has been obtained successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChatMessage" + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } + } + } + }, + "401": { + "description": "Not logged in", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } + } + } + }, + "400": { + "description": "Message is malformed", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Session was not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/assistant/chat/delete_message": { + "delete": { + "operationId": "chattyllm-delete-message", + "summary": "Delete a message", + "description": "Delete a chat message by ID", + "tags": [ + "chat_api" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "messageId", + "in": "query", + "description": "The message ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "sessionId", + "in": "query", + "description": "The session ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "OCS-APIRequest", + "in": "header", + "description": "Required to be true for the API request to pass", + "required": true, + "schema": { + "type": "boolean", + "default": true + } + } + ], + "responses": { + "200": { + "description": "The message has been successfully deleted", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } + } + } + }, + "401": { + "description": "Not logged in", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "The session was not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/assistant/chat/messages": { + "get": { + "operationId": "chattyllm-get-messages", + "summary": "Get session messages", + "description": "Get chat messages for the session without the system message", + "tags": [ + "chat_api" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "sessionId", + "in": "query", + "description": "The session ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "limit", + "in": "query", + "description": "The max number of messages to return", + "schema": { + "type": "integer", + "format": "int64", + "default": 20 + } + }, + { + "name": "cursor", + "in": "query", + "description": "The index of the first result to return", + "schema": { + "type": "integer", + "format": "int64", + "default": 0 + } + }, + { + "name": "OCS-APIRequest", + "in": "header", + "description": "Required to be true for the API request to pass", + "required": true, + "schema": { + "type": "boolean", + "default": true + } + } + ], + "responses": { + "200": { + "description": "The message list has been successfully obtained", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ChatMessage" + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } + } + } + }, + "401": { + "description": "Not logged in", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "The session was not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/assistant/chat/generate": { + "get": { + "operationId": "chattyllm-generate-for-session", + "summary": "Generate a new assistant message", + "description": "Schedule a task to generate a new message for a session", + "tags": [ + "chat_api" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "sessionId", + "in": "query", + "description": "The session ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "agencyConfirm", + "in": "query", + "description": "Potential agency sensitive actions confirmation (1: accept, 0: reject)", + "schema": { + "type": "integer", + "format": "int64", + "default": 0 + } + }, + { + "name": "OCS-APIRequest", + "in": "header", + "description": "Required to be true for the API request to pass", + "required": true, + "schema": { + "type": "boolean", + "default": true + } + } + ], + "responses": { + "200": { + "description": "The task has been successfully scheduled", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "taskId" + ], + "properties": { + "taskId": { + "type": "integer", + "format": "int64" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } + }, + "text/plain": { + "schema": { + "type": "string" + } + } + } + }, + "401": { + "description": "Not logged in", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } + } + } + }, + "400": { + "description": "Task was not scheduled", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Session was not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/assistant/chat/regenerate": { + "get": { + "operationId": "chattyllm-regenerate-for-session", + "summary": "Regenerate response for a message", + "description": "Delete the message with the given message ID and all following ones, then schedule a task to generate a new message for the session", + "tags": [ + "chat_api" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "sessionId", + "in": "query", + "description": "The chat session ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "messageId", + "in": "query", + "description": "The chat message ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "OCS-APIRequest", + "in": "header", + "description": "Required to be true for the API request to pass", + "required": true, + "schema": { + "type": "boolean", + "default": true + } + } + ], + "responses": { + "200": { + "description": "The task has been successfully scheduled", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "taskId" + ], + "properties": { + "taskId": { + "type": "integer", + "format": "int64" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } + }, + "text/plain": { + "schema": { + "type": "string" + } + } + } + }, + "401": { + "description": "Not logged in", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } + } + } + }, + "400": { + "description": "Task was not scheduled", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Session was not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/assistant/chat/check_session": { + "get": { + "operationId": "chattyllm-check-session", + "summary": "Check the status of a session", + "description": "Used by the frontend to determine if it should poll a generation task status.", + "tags": [ + "chat_api" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "sessionId", + "in": "query", + "description": "The chat session ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "OCS-APIRequest", + "in": "header", + "description": "Required to be true for the API request to pass", + "required": true, + "schema": { + "type": "boolean", + "default": true + } + } + ], + "responses": { + "200": { + "description": "The session status has been successfully obtained", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChatSessionCheck" + } + } + } + }, + "401": { + "description": "Not logged in", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } + } + } + }, + "400": { + "description": "Task processing failed, impossible to check the related tasks", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Session was not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/assistant/chat/check_generation": { + "get": { + "operationId": "chattyllm-check-message-generation-task", + "summary": "Check the status of a generation task", + "description": "Used by the frontend to poll a generation task status. If the task succeeds, a new message is stored and returned.", + "tags": [ + "chat_api" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "taskId", + "in": "query", + "description": "The message generation task ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "sessionId", + "in": "query", + "description": "The chat session ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "OCS-APIRequest", + "in": "header", + "description": "Required to be true for the API request to pass", + "required": true, + "schema": { + "type": "boolean", + "default": true + } + } + ], + "responses": { + "200": { + "description": "The task was successful, a message has been generated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChatAgencyMessage" + } + } + } + }, + "417": { + "description": "The task is still running or has not been picked up yet", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "task_status" + ], + "properties": { + "task_status": { + "type": "integer", + "format": "int64" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } + }, + "text/plain": { + "schema": { + "type": "string" + } + } + } + }, + "401": { + "description": "Not logged in", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } + } + } + }, + "400": { + "description": "Task processing failed", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Session was not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/assistant/chat/generate_title": { + "get": { + "operationId": "chattyllm-generate-title", + "summary": "Generate a session title", + "description": "Schedule a task to generate a title for a chat session", + "tags": [ + "chat_api" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "sessionId", + "in": "query", + "description": "The chat session ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "OCS-APIRequest", + "in": "header", + "description": "Required to be true for the API request to pass", + "required": true, + "schema": { + "type": "boolean", + "default": true + } + } + ], + "responses": { + "200": { + "description": "The task has been successfully scheduled", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "taskId" + ], + "properties": { + "taskId": { + "type": "integer", + "format": "int64" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } + }, + "text/plain": { + "schema": { + "type": "string" + } + } + } + }, + "401": { + "description": "Not logged in", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } + } + } + }, + "400": { + "description": "Task was not scheduled", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Session was not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/assistant/chat/check_title_generation": { + "get": { + "operationId": "chattyllm-check-title-generation-task", + "summary": "Check the status of a title generation task", + "description": "Used by the frontend to poll a title generation task status. If the task succeeds, the new title is set and returned.", + "tags": [ + "chat_api" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "taskId", + "in": "query", + "description": "The title generation task ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "sessionId", + "in": "query", + "description": "The chat session ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "OCS-APIRequest", + "in": "header", + "description": "Required to be true for the API request to pass", + "required": true, + "schema": { + "type": "boolean", + "default": true + } + } + ], + "responses": { + "200": { + "description": "Title has been successfully generated", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "result" + ], + "properties": { + "result": { + "type": "string" + } + } + } + } + } + }, + "417": { + "description": "The task is still running or has not been picked up yet", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "task_status" + ], + "properties": { + "task_status": { + "type": "integer", + "format": "int64" + } + } + } + } + } + }, + "500": { + "description": "200: The task was successful, a message has been generated", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } + }, + "text/plain": { + "schema": { + "type": "string" + } + } + } + }, + "401": { + "description": "Not logged in", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } + } + } + }, + "400": { + "description": "Task processing failed", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Session was not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + } + } + } + } + } + } + } + } } }, "tags": [] diff --git a/src/components/ChattyLLM/ChattyLLMInputForm.vue b/src/components/ChattyLLM/ChattyLLMInputForm.vue index 75d0e4f6..e19c1f97 100644 --- a/src/components/ChattyLLM/ChattyLLMInputForm.vue +++ b/src/components/ChattyLLM/ChattyLLMInputForm.vue @@ -180,12 +180,12 @@ import AgencyConfirmation from './AgencyConfirmation.vue' import axios from '@nextcloud/axios' import { showError } from '@nextcloud/dialogs' -import { generateUrl } from '@nextcloud/router' +import { generateUrl, generateOcsUrl } from '@nextcloud/router' import moment from 'moment' // future: type (text, image, file, etc), attachments, etc support -const getChatURL = (endpoint) => generateUrl('/apps/assistant/chat' + endpoint) +const getChatURL = (endpoint) => generateOcsUrl('/apps/assistant/chat' + endpoint) const Roles = { HUMAN: 'human', ASSISTANT: 'assistant', @@ -288,17 +288,18 @@ export default { try { const sessionId = this.active.id const checkSessionResponse = await axios.get(getChatURL('/check_session'), { params: { sessionId } }) - if (checkSessionResponse.data?.sessionTitle && checkSessionResponse.data?.sessionTitle !== this.active.title) { - this.active.title = checkSessionResponse.data?.sessionTitle + const checkSessionResponseData = checkSessionResponse.data + if (checkSessionResponseData?.sessionTitle && checkSessionResponseData?.sessionTitle !== this.active.title) { + this.active.title = checkSessionResponseData?.sessionTitle console.debug('update session title with check result') } - console.debug('check session response:', checkSessionResponse.data) + console.debug('check session response:', checkSessionResponseData) // update the pending actions when switching conversations - this.active.sessionAgencyPendingActions = checkSessionResponse.data?.sessionAgencyPendingActions + this.active.sessionAgencyPendingActions = checkSessionResponseData?.sessionAgencyPendingActions this.active.agencyAnswered = false - if (checkSessionResponse.data.messageTaskId !== null) { + if (checkSessionResponseData.messageTaskId !== null) { try { - const message = await this.pollGenerationTask(checkSessionResponse.data.messageTaskId, sessionId) + const message = await this.pollGenerationTask(checkSessionResponseData.messageTaskId, sessionId) console.debug('checkTaskPolling result:', message) this.messages.push(message) this.scrollToBottom() @@ -307,17 +308,18 @@ export default { showError(t('assistant', 'Error generating a response')) } } - if (checkSessionResponse.data.titleTaskId !== null) { + if (checkSessionResponseData.titleTaskId !== null) { try { - const titleResponse = await this.pollTitleGenerationTask(checkSessionResponse.data.titleTaskId, sessionId) + const titleResponse = await this.pollTitleGenerationTask(checkSessionResponseData.titleTaskId, sessionId) + const titleResponseData = titleResponse.data console.debug('checkTaskPolling result:', titleResponse) - if (titleResponse?.data?.result == null) { + if (titleResponseData?.result == null) { throw new Error('No title generated, response:', titleResponse) } const session = this.sessions.find(s => s.id === sessionId) if (session) { - session.title = titleResponse?.data?.result + session.title = titleResponseData?.result } } catch (error) { console.error('onCheckSessionTitle error:', error) @@ -446,16 +448,17 @@ export default { try { this.loading.titleGeneration = true const sessionId = this.active.id - const response = await axios.get(getChatURL('/generate_title'), { params: { sessionId } }) - const titleResponse = await this.pollTitleGenerationTask(response.data.taskId, sessionId) - console.debug('checkTaskPolling result:', titleResponse) - if (titleResponse?.data?.result == null) { - throw new Error('No title generated, response:', response) + const titleGenerationResponse = await axios.get(getChatURL('/generate_title'), { params: { sessionId } }) + const titlePollResponse = await this.pollTitleGenerationTask(titleGenerationResponse.data.taskId, sessionId) + const titlePollResponseData = titlePollResponse.data + console.debug('checkTaskPolling result:', titlePollResponseData) + if (titlePollResponseData?.result == null) { + throw new Error('No title generated, response:', titlePollResponse) } const session = this.sessions.find(s => s.id === sessionId) if (session) { - session.title = titleResponse?.data?.result + session.title = titlePollResponseData?.result } } catch (error) { console.error('onGenerateSessionTitle error:', error) @@ -530,7 +533,7 @@ export default { } this.messagesAxiosController = new AbortController() - const response = await axios.get(getChatURL('/messages'), { + const messagesResponse = await axios.get(getChatURL('/messages'), { params: { sessionId: this.active.id, cursor: this.msgCursor, @@ -538,13 +541,14 @@ export default { }, signal: this.messagesAxiosController.signal, }) - console.debug('fetchMessages response:', response.data) + const messagesResponseData = messagesResponse.data + console.debug('fetchMessages response:', messagesResponseData) if (this.messages == null) { this.messages = [] } - this.messages.unshift(...response.data) + this.messages.unshift(...messagesResponseData) - if (response.data.length < this.msgLimit) { + if (messagesResponseData.length < this.msgLimit) { this.allMessagesLoaded = true } @@ -574,19 +578,20 @@ export default { this.loading.newHumanMessage = true const firstHumanMessage = this.messages.length === 1 && this.messages[0].role === Roles.HUMAN - const response = await axios.put(getChatURL('/new_message'), { + const newMessageResponse = await axios.put(getChatURL('/new_message'), { sessionId, role, content, timestamp, firstHumanMessage, }) - console.debug('newMessage response:', response) + const newMessageResponseData = newMessageResponse.data + console.debug('newMessage response:', newMessageResponseData) this.loading.newHumanMessage = false if (replaceLastMessage) { // replace the last message with the response that contains the id - this.messages[this.messages.length - 1] = response.data + this.messages[this.messages.length - 1] = newMessageResponseData } if (firstHumanMessage) { @@ -605,13 +610,14 @@ export default { async newSession(title = null) { try { this.loading.newSession = true - const response = await axios.put(getChatURL('/new_session'), { + const newSessionResponse = await axios.put(getChatURL('/new_session'), { timestamp: +new Date() / 1000 | 0, title, }) - console.debug('newSession response:', response) + const newSessionResponseData = newSessionResponse.data + console.debug('newSession response:', newSessionResponseData) - const session = response.data?.session ?? null + const session = newSessionResponseData?.session ?? null if (session == null) { throw new Error(t('assistant', 'Invalid response received for a new conversation request')) } @@ -636,9 +642,10 @@ export default { params.agencyConfirm = agencyConfirm ? 1 : 0 } this.saveLastSelectedTaskType('chatty-llm') - const response = await axios.get(getChatURL('/generate'), { params }) - console.debug('scheduleGenerationTask response:', response) - const message = await this.pollGenerationTask(response.data.taskId, sessionId) + const generationResponse = await axios.get(getChatURL('/generate'), { params }) + const generationResponseData = generationResponse.data + console.debug('scheduleGenerationTask response:', generationResponseData) + const message = await this.pollGenerationTask(generationResponseData.taskId, sessionId) console.debug('checkTaskPolling result:', message) this.messages.push(message) this.scrollToBottom() @@ -654,9 +661,10 @@ export default { try { const sessionId = this.active.id this.loading.llmGeneration = true - const response = await axios.get(getChatURL('/regenerate'), { params: { messageId, sessionId } }) - console.debug('scheduleRegenerationTask response:', response) - const message = await this.pollGenerationTask(response.data.taskId, sessionId) + const regenerationResponse = await axios.get(getChatURL('/regenerate'), { params: { messageId, sessionId } }) + const regenerationResponseData = regenerationResponse.data + console.debug('scheduleRegenerationTask response:', regenerationResponse) + const message = await this.pollGenerationTask(regenerationResponseData.taskId, sessionId) console.debug('checkTaskPolling result:', message) this.messages[this.messages.length - 1] = message this.scrollToBottom() @@ -680,11 +688,12 @@ export default { getChatURL('/check_generation'), { params: { taskId, sessionId } }, ).then(response => { + const responseData = response.data clearInterval(this.pollMessageGenerationTimerId) if (sessionId === this.active.id) { - this.active.sessionAgencyPendingActions = response.data.sessionAgencyPendingActions + this.active.sessionAgencyPendingActions = responseData.sessionAgencyPendingActions this.active.agencyAnswered = false - resolve(response.data) + resolve(responseData) } else { console.debug('Ignoring received message for session ' + sessionId + ' that is not selected anymore') // should we reject here? @@ -760,7 +769,7 @@ export default { } const url = generateUrl('/apps/assistant/config') return axios.put(url, req) - } + }, }, }