@@ -385,6 +385,13 @@ public function scheduleMessageGeneration(?string $userId, int $sessionId, int $
385385 // audio agency
386386 $ fileId = $ audioAttachment ['file_id ' ];
387387 $ taskId = $ this ->scheduleAgencyAudioTask ($ userId , $ fileId , $ agencyConfirm , $ lastConversationToken , $ sessionId , $ lastUserMessage ->getId ());
388+ } elseif ($ this ->isMultimodalContextAgentAvailable ()) {
389+ // multimodal agency
390+ $ prompt = $ lastUserMessage ->getContent ();
391+ $ inputAttachments = array_map (static function (array $ attachment ) {
392+ return $ attachment ['file_id ' ];
393+ }, $ lastAttachments );
394+ $ taskId = $ this ->scheduleAgencyMultimodalTask ($ userId , $ prompt , $ agencyConfirm , $ lastConversationToken , $ sessionId , $ inputAttachments );
388395 } else {
389396 // classic agency
390397 $ prompt = $ lastUserMessage ->getContent ();
@@ -434,19 +441,15 @@ public function scheduleMessageGeneration(?string $userId, int $sessionId, int $
434441 } else {
435442 if ($ this ->isMultimodalChatAvailable ()) {
436443 // for a multimodal chat also attachments need to be added to the history
437- $ assistantService = $ this ->assistantService ;
438- $ historyMessages = array_map (static function (Message $ message ) use ($ userId , $ assistantService ) {
444+ $ historyMessages = array_map (static function (Message $ message ) {
439445 $ attachments = $ message ->jsonSerialize ()['attachments ' ];
440446 // Attachments that were generated need to be saved in the user's files so they are accessible to provider
441- $ content = array_map (static function (array $ attachment ) use ($ userId , $ assistantService , $ message ) {
442- if ($ message ->getRole () === Message::ROLE_ASSISTANT ) {
443- $ info = $ assistantService ->saveOutputFile ($ userId , $ message ->getOcpTaskId (), $ attachment ['file_id ' ]);
444- return [
445- 'type ' => 'file ' ,
446- 'file_id ' => $ info ['fileId ' ],
447- ];
447+ $ content = array_map (static function (array $ attachment ) {
448+ $ newAttachment = ['type ' => 'file ' , 'file_id ' => $ attachment ['file_id ' ]];
449+ if (isset ($ attachment ['ocp_task_id ' ])) {
450+ $ newAttachment ['ocp_task_id ' ] = $ attachment ['ocp_task_id ' ];
448451 }
449- return [ ' type ' => ' file ' , ' file_id ' => $ attachment [ ' file_id ' ]] ;
452+ return $ newAttachment ;
450453 }, $ attachments );
451454 $ content [] = [
452455 'type ' => 'text ' ,
@@ -591,6 +594,13 @@ public function isMultimodalChatAvailable(): bool {
591594 return in_array (\OCP \TaskProcessing \TaskTypes \MultimodalChatWithTools::ID , $ this ->taskProcessingManager ->getAvailableTaskTypeIds ());
592595 }
593596
597+ public function isMultimodalContextAgentAvailable (): bool {
598+ if (!class_exists ('OCP \\TaskProcessing \\TaskTypes \\MultimodalContextAgentInteraction ' )) {
599+ return false ;
600+ }
601+ return in_array (\OCP \TaskProcessing \TaskTypes \MultimodalContextAgentInteraction::ID , $ this ->taskProcessingManager ->getAvailableTaskTypeIds ());
602+ }
603+
594604
595605 private function getAudioHistory (array $ history ): array {
596606 // history is a list of JSON strings
@@ -799,6 +809,58 @@ private function scheduleAgencyTask(
799809 return $ task ->getId () ?? 0 ;
800810 }
801811
812+ /**
813+ * Schedule a multimodal agency chat task
814+ *
815+ * @param list<int> $inputAttachments
816+ * @throws BadRequestException
817+ * @throws InternalException
818+ */
819+ private function scheduleAgencyMultimodalTask (
820+ ?string $ userId ,
821+ string $ content ,
822+ int $ confirmation ,
823+ string $ conversationToken ,
824+ int $ sessionId ,
825+ array $ inputAttachments ,
826+ ): int {
827+ $ customId = 'chatty-llm: ' . $ sessionId ;
828+ $ this ->checkIfSessionIsThinking ($ userId , $ customId );
829+ $ taskInput = [
830+ 'input ' => $ content ,
831+ 'input_attachments ' => $ inputAttachments ,
832+ 'confirmation ' => $ confirmation ,
833+ 'conversation_token ' => $ conversationToken ,
834+ ];
835+ /** @psalm-suppress UndefinedClass */
836+ if (isset ($ this ->taskProcessingManager ->getAvailableTaskTypes ()[\OCP \TaskProcessing \TaskTypes \MultimodalContextAgentInteraction::ID ]['optionalInputShape ' ]['memories ' ])) {
837+ $ taskInput ['memories ' ] = $ this ->sessionSummaryService ->getMemories ($ userId );
838+ }
839+ /** @psalm-suppress UndefinedClass */
840+ $ task = new Task (
841+ \OCP \TaskProcessing \TaskTypes \MultimodalContextAgentInteraction::ID ,
842+ $ taskInput ,
843+ Application::APP_ID . ':chatty-llm ' ,
844+ $ userId ,
845+ $ customId
846+ );
847+ /** @psalm-suppress UndefinedMethod */
848+ $ task ->setPreferStreaming (true );
849+ try {
850+ $ this ->taskProcessingManager ->scheduleTask ($ task );
851+ } catch (PreConditionNotMetException $ e ) {
852+ throw new BadRequestException ('pre_condition_not_met ' , previous: $ e );
853+ } catch (\OCP \TaskProcessing \Exception \UnauthorizedException $ e ) {
854+ throw new BadRequestException ('unauthorized ' , previous: $ e );
855+ } catch (ValidationException $ e ) {
856+ throw new BadRequestException ('validation_failed ' , previous: $ e );
857+ } catch (\OCP \TaskProcessing \Exception \Exception $ e ) {
858+ $ this ->logger ->error ($ e ->getMessage (), ['exception ' => $ e ]);
859+ throw new InternalException (previous: $ e );
860+ }
861+ return $ task ->getId () ?? 0 ;
862+ }
863+
802864 /**
803865 * Schedule an audio chat task
804866 * @throws BadRequestException
0 commit comments