Skip to content

feat(Assignments)#522

Open
marcelklehr wants to merge 22 commits intomainfrom
feat/assignments
Open

feat(Assignments)#522
marcelklehr wants to merge 22 commits intomainfrom
feat/assignments

Conversation

@marcelklehr
Copy link
Copy Markdown
Member

@marcelklehr marcelklehr commented May 5, 2026

Todo:

  • Refactored ChattyLLMController to factor out business logic into a service
  • Implemented Assignments backend logic (db, APIController, Service, BgJob)
  • Implemented RRule checking
  • Implement front-end
    • Small header for assignment sessions to indicate what's going on
    • Maybe disable the chat input for assignment sessions?
    • Maybe a small icon for the chat session overview for assignment sessions
    • Query the session list regularly and for assignment sessions we need to check for new generations regularly
  • Implement better session titles for assignment sessions
  • Implement notification for mid-assignment approvals

Use the assignment tools in nextcloud/context_agent#162 to schedule assignments from the UI, or use curl :)

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>
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>
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 ChattyLLMController into lib/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/recurr dependency.

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.

Comment thread lib/Controller/AssignmentsApiController.php Outdated
Comment thread lib/Controller/AssignmentsApiController.php
Comment thread lib/Controller/AssignmentsApiController.php Outdated
Comment thread lib/Service/AssignmentsService.php Outdated
Comment thread lib/Service/AssignmentsService.php
Comment thread lib/Controller/ChattyLLMController.php Outdated
Comment thread lib/ResponseDefinitions.php Outdated
Comment thread openapi.json
Comment thread openapi.json Outdated
Comment thread lib/Db/ChattyLLM/Session.php
Copy link
Copy Markdown
Member

@julien-nc julien-nc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐘

Comment thread lib/Migration/Version030500Date20260430083738.php Outdated
Comment thread lib/Migration/Version030500Date20260430083738.php
Comment thread lib/Service/ChatService.php Outdated
Comment thread lib/Service/ChatService.php Outdated
marcelklehr and others added 2 commits May 7, 2026 07:37
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>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 24 changed files in this pull request and generated 23 comments.

Comment thread lib/Controller/AssignmentsApiController.php
Comment thread lib/Controller/AssignmentsApiController.php
Comment thread lib/Controller/AssignmentsApiController.php Outdated
Comment thread lib/Controller/AssignmentsApiController.php
Comment thread lib/Controller/AssignmentsApiController.php
Comment thread lib/Service/ChatService.php Outdated
Comment thread lib/Service/ChatService.php Outdated
Comment thread openapi.json
Comment thread openapi.json
Comment thread tests/psalm-baseline.xml
marcelklehr and others added 4 commits May 7, 2026 08:36
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>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 24 changed files in this pull request and generated 8 comments.

Comment thread lib/Controller/AssignmentsApiController.php Outdated
Comment thread lib/Controller/AssignmentsApiController.php Outdated
Comment thread lib/Service/AssignmentsService.php
Comment thread lib/Service/AssignmentsService.php
Comment thread lib/Db/Assignment.php
Comment thread lib/Db/Assignment.php
Comment thread lib/Service/ChatService.php
Comment thread lib/Service/ChatService.php
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 24 changed files in this pull request and generated 11 comments.

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 thread lib/Db/Assignment.php
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]);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants