@@ -297,7 +297,11 @@ public function generateForSession(int $sessionId): JSONResponse {
297
297
. PHP_EOL
298
298
. 'assistant: ' ;
299
299
300
- $ taskId = $ this ->scheduleLLMTask ($ stichedPrompt );
300
+ try {
301
+ $ taskId = $ this ->scheduleLLMTask ($ stichedPrompt , $ sessionId );
302
+ } catch (\Exception $ e ) {
303
+ return new JSONResponse (['error ' => $ e ->getMessage ()], Http::STATUS_BAD_REQUEST );
304
+ }
301
305
302
306
return new JSONResponse (['taskId ' => $ taskId ]);
303
307
}
@@ -374,7 +378,7 @@ public function checkMessageGenerationTask(int $taskId, int $sessionId): JSONRes
374
378
$ message ->setRole ('assistant ' );
375
379
$ message ->setContent (trim ($ task ->getOutput ()['output ' ] ?? '' ));
376
380
$ message ->setTimestamp (time ());
377
- $ this -> messageMapper -> insert ( $ message );
381
+ // do not insert here, it is done by the listener
378
382
return new JSONResponse ($ message );
379
383
} catch (\OCP \DB \Exception $ e ) {
380
384
$ this ->logger ->warning ('Failed to add a chat message into DB ' , ['exception ' => $ e ]);
@@ -388,6 +392,56 @@ public function checkMessageGenerationTask(int $taskId, int $sessionId): JSONRes
388
392
return new JSONResponse (['error ' => 'unknown_error ' , 'task_status ' => $ task ->getstatus ()], Http::STATUS_BAD_REQUEST );
389
393
}
390
394
395
+ /**
396
+ * Check the status of a session
397
+ *
398
+ * Used by the frontend to determine if it should poll a generation task status.
399
+ *
400
+ * @param int $sessionId
401
+ * @return JSONResponse
402
+ * @throws \JsonException
403
+ * @throws \OCP\DB\Exception
404
+ */
405
+ #[NoAdminRequired]
406
+ public function checkSession (int $ sessionId ): JSONResponse {
407
+ if ($ this ->userId === null ) {
408
+ return new JSONResponse (['error ' => $ this ->l10n ->t ('User not logged in ' )], Http::STATUS_UNAUTHORIZED );
409
+ }
410
+
411
+ $ sessionExists = $ this ->sessionMapper ->exists ($ this ->userId , $ sessionId );
412
+ if (!$ sessionExists ) {
413
+ return new JSONResponse (['error ' => $ this ->l10n ->t ('Session not found ' )], Http::STATUS_NOT_FOUND );
414
+ }
415
+
416
+ try {
417
+ $ messageTasks = $ this ->taskProcessingManager ->getUserTasksByApp ($ this ->userId , Application::APP_ID . ':chatty-llm ' , 'chatty-llm: ' . $ sessionId );
418
+ $ titleTasks = $ this ->taskProcessingManager ->getUserTasksByApp ($ this ->userId , Application::APP_ID . ':chatty-llm ' , 'chatty-title: ' . $ sessionId );
419
+ } catch (\OCP \TaskProcessing \Exception \Exception $ e ) {
420
+ return new JSONResponse (['error ' => 'task_query_failed ' ], Http::STATUS_BAD_REQUEST );
421
+ }
422
+ $ messageTasks = array_filter ($ messageTasks , static function (Task $ task ) {
423
+ return $ task ->getStatus () === Task::STATUS_RUNNING || $ task ->getStatus () === Task::STATUS_SCHEDULED ;
424
+ });
425
+ $ titleTasks = array_filter ($ titleTasks , static function (Task $ task ) {
426
+ return $ task ->getStatus () === Task::STATUS_RUNNING || $ task ->getStatus () === Task::STATUS_SCHEDULED ;
427
+ });
428
+ $ session = $ this ->sessionMapper ->getUserSession ($ this ->userId , $ sessionId );
429
+ $ responseData = [
430
+ 'messageTaskId ' => null ,
431
+ 'titleTaskId ' => null ,
432
+ 'sessionTitle ' => $ session ->getTitle (),
433
+ ];
434
+ if (!empty ($ messageTasks )) {
435
+ $ task = array_pop ($ messageTasks );
436
+ $ responseData ['messageTaskId ' ] = $ task ->getId ();
437
+ }
438
+ if (!empty ($ titleTasks )) {
439
+ $ task = array_pop ($ titleTasks );
440
+ $ responseData ['titleTaskId ' ] = $ task ->getId ();
441
+ }
442
+ return new JSONResponse ($ responseData );
443
+ }
444
+
391
445
/**
392
446
* Schedule a task to generate a title for the chat session
393
447
*
@@ -430,7 +484,11 @@ public function generateTitle(int $sessionId): JSONResponse {
430
484
. PHP_EOL . PHP_EOL
431
485
. $ userInstructions ;
432
486
433
- $ taskId = $ this ->scheduleLLMTask ($ stichedPrompt );
487
+ try {
488
+ $ taskId = $ this ->scheduleLLMTask ($ stichedPrompt , $ sessionId , false );
489
+ } catch (\Exception $ e ) {
490
+ return new JSONResponse (['error ' => $ e ->getMessage ()], Http::STATUS_BAD_REQUEST );
491
+ }
434
492
return new JSONResponse (['taskId ' => $ taskId ]);
435
493
} catch (\OCP \DB \Exception $ e ) {
436
494
$ this ->logger ->warning ('Failed to generate a title for the chat session ' , ['exception ' => $ e ]);
@@ -475,8 +533,7 @@ public function checkTitleGenerationTask(int $taskId, int $sessionId): JSONRespo
475
533
$ title = str_replace ('" ' , '' , $ title );
476
534
$ title = explode (PHP_EOL , $ title )[0 ];
477
535
$ title = trim ($ title );
478
-
479
- $ this ->sessionMapper ->updateSessionTitle ($ this ->userId , $ sessionId , $ title );
536
+ // do not write the title here since it's done in the listener
480
537
481
538
return new JSONResponse (['result ' => $ title ]);
482
539
} catch (\OCP \DB \Exception $ e ) {
@@ -525,14 +582,32 @@ private function getStichedMessages(int $sessionId): string {
525
582
* Schedule the LLM task
526
583
*
527
584
* @param string $content
585
+ * @param int $sessionId
586
+ * @param bool $isMessage
528
587
* @return int|null
529
588
* @throws Exception
530
589
* @throws PreConditionNotMetException
531
590
* @throws UnauthorizedException
532
591
* @throws ValidationException
592
+ * @throws \JsonException
533
593
*/
534
- private function scheduleLLMTask (string $ content ): ?int {
535
- $ task = new Task (TextToText::ID , ['input ' => $ content ], Application::APP_ID . ':chatty-llm ' , $ this ->userId );
594
+ private function scheduleLLMTask (string $ content , int $ sessionId , bool $ isMessage = true ): ?int {
595
+ $ customId = ($ isMessage
596
+ ? 'chatty-llm: '
597
+ : 'chatty-title: ' ) . $ sessionId ;
598
+ try {
599
+ $ tasks = $ this ->taskProcessingManager ->getUserTasksByApp ($ this ->userId , Application::APP_ID . ':chatty-llm ' , $ customId );
600
+ } catch (\OCP \TaskProcessing \Exception \Exception $ e ) {
601
+ throw new \Exception ('task_query_failed ' );
602
+ }
603
+ $ tasks = array_filter ($ tasks , static function (Task $ task ) {
604
+ return $ task ->getStatus () === Task::STATUS_RUNNING || $ task ->getStatus () === Task::STATUS_SCHEDULED ;
605
+ });
606
+ // prevent scheduling multiple llm tasks simultaneously for one session
607
+ if (!empty ($ tasks )) {
608
+ throw new \Exception ('session_already_thinking ' );
609
+ }
610
+ $ task = new Task (TextToText::ID , ['input ' => $ content ], Application::APP_ID . ':chatty-llm ' , $ this ->userId , $ customId );
536
611
$ this ->taskProcessingManager ->scheduleTask ($ task );
537
612
return $ task ->getId ();
538
613
}
0 commit comments