feat(Assignments)#522
Open
marcelklehr wants to merge 22 commits intomainfrom
Open
Conversation
some stuff still missing Signed-off-by: Marcel Klehr <mklehr@gmx.net>
Move business logic from CHattyLLMController to ChatServiec Signed-off-by: Marcel Klehr <mklehr@gmx.net>
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
efc9c06 to
046cdac
Compare
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
ce836de to
dec32dc
Compare
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
There was a problem hiding this comment.
Pull request overview
This PR introduces an “Assignments” backend for the Assistant app and refactors the existing chat controller by moving business logic into a dedicated ChatService. It adds persistence (DB + migration), an OCS API for CRUD operations, and a background job to execute recurring assignments using RRULEs.
Changes:
- Refactor: extract chat/session/message/task scheduling logic from
ChattyLLMControllerintolib/Service/ChatService.php. - Feature: add Assignments domain (DB entity + mapper, OCS controller, service layer, OpenAPI schema) plus RRULE-based “due” evaluation.
- Operations: add a timed background job to run due assignments per user; add
simshaun/recurrdependency.
Reviewed changes
Copilot reviewed 22 out of 23 changed files in this pull request and generated 15 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/psalm-baseline.xml | Adds Psalm baseline suppressions for logger('assistant') usage in the new Assignment entity. |
| openapi.json | Adds Assignment schema and CRUD-ish assignment endpoints under /ocs/v2.php/apps/assistant/assignments. |
| lib/Service/UnauthorizedException.php | New service-layer exception type for auth failures. |
| lib/Service/NotFoundException.php | New service-layer exception type for missing resources. |
| lib/Service/InternalException.php | New service-layer exception type for internal failures. |
| lib/Service/BadRequestException.php | New service-layer exception type for validation/user input issues. |
| lib/Service/ChatService.php | New service encapsulating chat session/message logic and task scheduling. |
| lib/Service/AssignmentsService.php | Implements assignment creation and due-run scheduling (including chat session linkage). |
| lib/ResponseDefinitions.php | Adds Psalm type AssistantAssignment used for response typing/OpenAPI extraction. |
| lib/Migration/Version030500Date20260430083738.php | Creates assistant_assignments table and adds assignment_id column/index to chat sessions. |
| lib/Listener/ChattyLLMTaskListener.php | Uses new Message::ROLE_ASSISTANT constant instead of raw string. |
| lib/Db/ChattyLLM/SessionMapper.php | Adds getUserSessionForAssignment() lookup by assignment_id. |
| lib/Db/ChattyLLM/Session.php | Adds assignmentId field and serializes assignment_id. |
| lib/Db/ChattyLLM/MessageMapper.php | Uses Message::ROLE_HUMAN constant; updates return typing docblock. |
| lib/Db/ChattyLLM/Message.php | Introduces ROLE_HUMAN / ROLE_ASSISTANT constants. |
| lib/Db/AssignmentMapper.php | New mapper to load assignments and enumerate due assignments. |
| lib/Db/Assignment.php | New Assignment entity with RRULE validation and “due to run” logic. |
| lib/Controller/ChattyLLMController.php | Refactors controller to delegate to ChatService and map service exceptions to HTTP responses. |
| lib/Controller/AssignmentsApiController.php | New OCS controller implementing assignment endpoints. |
| lib/BackgroundJob/RunAssignmentsJob.php | New timed background job to run due assignments for a user. |
| composer.lock | Locks new dependencies pulled in by RRULE library. |
| composer.json | Adds simshaun/recurr dependency. |
| appinfo/info.xml | Bumps app version to 3.5.0-dev.1. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
julien-nc
requested changes
May 6, 2026
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Signed-off-by: Marcel Klehr <mklehr@gmx.net>
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Signed-off-by: Marcel Klehr <mklehr@gmx.net>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Signed-off-by: Marcel Klehr <mklehr@gmx.net>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Signed-off-by: Marcel Klehr <mklehr@gmx.net>
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
Comment on lines
+58
to
+62
| public function createUserAssignment(string $prompt, int $startsAt, string $recurrence): DataResponse { | ||
| try { | ||
| $assignment = $this->assignmentsService->createAssignment($this->userId, $prompt, $startsAt, $recurrence); | ||
| $serializedAssignment = $assignment->jsonSerialize(); | ||
| return new DataResponse(['assignment' => $serializedAssignment]); |
Comment on lines
+122
to
+125
| } catch (Exception $e) { | ||
| $this->logger->error('Error while fetching assignment for user ' . $this->userId, ['exception' => $e]); | ||
| return new DataResponse('', Http::STATUS_FORBIDDEN); | ||
| } catch (DoesNotExistException|MultipleObjectsReturnedException) { |
Comment on lines
+200
to
+202
| } catch (Exception $e) { | ||
| $this->logger->error('Error while fetching assignment for user ' . $this->userId, ['exception' => $e]); | ||
| return new DataResponse('', Http::STATUS_FORBIDDEN); |
Comment on lines
+64
to
+68
| $session = $this->chatService->createChatSession($userId, $this->timeFactory->now()->getTimestamp(), 'Assignment ' . $assignment->getId()); // TODO: Add a proper title here | ||
| $session->setAssignmentId($assignment->getId()); | ||
| try { | ||
| $this->sessionMapper->update($session); | ||
| } catch (Exception $e) { |
Comment on lines
+49
to
+51
| $assignment->setPrompt($prompt); | ||
| $assignment->setStartsAt($startsAt); | ||
| $assignment->setLastRunAt(0); |
| if ($user === null) { | ||
| throw new UnauthorizedException($this->l10n->t('User not found')); | ||
| } | ||
|
|
Comment on lines
+249
to
+253
| public function getSessionMessages(?string $userId, int $sessionId, $limit = 20, int $cursor = 0): array { | ||
| if ($userId === null) { | ||
| throw new UnauthorizedException($this->l10n->t('Unauthorized')); | ||
| } | ||
|
|
Comment on lines
+425
to
+430
| $history = array_map(static function (Message $message) { | ||
| return json_encode([ | ||
| 'role' => $message->getRole(), | ||
| 'content' => $message->getContent(), | ||
| ]); | ||
| }, $history); |
Comment on lines
+323
to
325
| /** @var list<AssistantChatSession> $sessions */ | ||
| $sessions = $this->chatService->getSessionsForUser($this->userId); | ||
| return new JSONResponse($sessions); |
Comment on lines
+128
to
+132
| logger('assistant')->debug('Next recurrence of assignment ' . $this->getId() . ' of user ' . $this->getUserId() . ': ' . $nextRecurrence->getStart()->format('Y-m-d H:i:s') . ' - isDue: ' . ($isDue ? 'true' : 'false')); | ||
| return $isDue; | ||
| } catch (InvalidRRule|\Exception|NotFoundExceptionInterface|ContainerExceptionInterface $e) { | ||
| // this should not happen, as we validate the rule on setRecurrence, but just in case, we catch the exception and log it | ||
| logger('assistant')->error($e->getMessage(), ['exception' => $e]); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Todo:
Use the assignment tools in nextcloud/context_agent#162 to schedule assignments from the UI, or use curl :)