Skip to content

Fix: correctly order messages when getting the system prompt one - #633

Merged
julien-nc merged 1 commit into
mainfrom
fix/625/message-order
Aug 26, 2026
Merged

Fix: correctly order messages when getting the system prompt one#633
julien-nc merged 1 commit into
mainfrom
fix/625/message-order

Conversation

@julien-nc

Copy link
Copy Markdown
Member

closes #625

And improve the related query by applying a role filter.

🤖 AI (if applicable)

  • The content of this PR was partly or fully generated using AI

…rove the query by applying a role filter

Signed-off-by: Julien Veyssier <julien-nc@posteo.net>
@coderabbitai

coderabbitai Bot commented Aug 26, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The message mapper now accepts an optional role filter for getFirstNMessages and applies it through a parameterized query condition. Classic chat requests the first system message directly. If no system message exists, the service logs the condition and uses an empty prompt. Other mapper errors remain internal errors.

Merge Risk: 🟡 Moderate · up to fb35e

This change can return messages in the wrong order and may select the wrong system message when timestamps are shared or caller-provided. Merge should wait until ordering uses the persisted message ID.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The pull request explicitly selects the system-role message and prevents an empty prompt when other messages are returned first. However, the summary does not show that getFirstNMessages now orders by… Add deterministic ascending ID ordering to getFirstNMessages before applying the result limit. Retain the role filter and direct system-role lookup in ChatService.php. [#625]
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title addresses message ordering during system prompt retrieval, which is directly related to the pull request changes.
Description check ✅ Passed The description identifies issue #625 and the related role-filter query improvement, matching the changeset.
Out of Scope Changes check ✅ Passed The role filter and ChatService changes are directly related to preventing loss of the system prompt and fulfilling issue #625. No unrelated changes are identified.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 2 files.
Full details: Linked Issues check

Explanation

The pull request explicitly selects the system-role message and prevents an empty prompt when other messages are returned first. However, the summary does not show that getFirstNMessages now orders by ID as required by issue #625; it retains ascending timestamp ordering instead.

  • Fix all pre-merge checks with AI

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 08792957-f3c5-4d67-960d-d4416f09ef23

📥 Commits

Reviewing files that changed from the base of the PR and between ad30559 and fb35e92.

📒 Files selected for processing (2)
  • lib/Db/ChattyLLM/MessageMapper.php
  • lib/Service/ChatService.php

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.

Comment on lines +42 to +45
if ($role !== null) {
$qb->andWhere($qb->expr()->eq('role', $qb->createPositionalParameter($role, IQueryBuilder::PARAM_STR)));
}
$qb->orderBy('timestamp', 'ASC')

@coderabbitai coderabbitai Bot Aug 26, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Order the filtered messages by ID.

getFirstNMessages() must return the first persisted message deterministically. timestamp can be caller-provided or shared by multiple messages, so ORDER BY timestamp ASC can select the wrong system message or produce database-dependent results. Use ORDER BY id ASC, consistent with the other message-history queries.

Proposed fix
-		$qb->orderBy('timestamp', 'ASC')
+		$qb->orderBy('id', 'ASC')
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if ($role !== null) {
$qb->andWhere($qb->expr()->eq('role', $qb->createPositionalParameter($role, IQueryBuilder::PARAM_STR)));
}
$qb->orderBy('timestamp', 'ASC')
if ($role !== null) {
$qb->andWhere($qb->expr()->eq('role', $qb->createPositionalParameter($role, IQueryBuilder::PARAM_STR)));
}
$qb->orderBy('id', 'ASC')

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

mmh, Id is not guaratneed to be sequential

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '== Candidate schema and migration files =='
fd -t f . | rg -i '(^|/)(migration|schema|message).*\.(php|xml|json|sql)$' | head -n 200

printf '%s\n' '== assistant_chat_msgs declarations and inserts =='
rg -n -C 4 --glob '*.php' --glob '*.xml' --glob '*.sql' \
  '(assistant_chat_msgs|createTable\(.assistant_chat_msgs.|INSERT\s+INTO\s+.*assistant_chat_msgs|insert\(.assistant_chat_msgs.)' .

printf '%s\n' '== Message entity structure and persistence call sites =='
fd -t f 'Message.php' . -x sh -c 'echo "== $1 =="; ast-grep outline "$1" --items all --view expanded; sed -n "1,260p" "$1"' sh {} \
  | head -n 500
rg -n -C 4 --glob '*.php' '(insert\(\$message\)|insert\(\$[A-Za-z_]+Message\)|new Message\()' lib

Length of output: 14146


@marcelklehr, correct. The IDs do not need to be sequential.

ORDER BY id ASC selects the lowest persisted auto-increment ID. Gaps from deleted rows or rolled-back inserts do not change that order. The migration defines assistant_chat_msgs.id as an auto-increment column, and the insert path does not set the ID.

The issue with timestamp remains. Callers can provide the same timestamp for multiple messages, or a timestamp that does not match insertion order. I recommend ORDER BY id ASC for a deterministic persisted-message order.

You are interacting with an AI system.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We can add the id to the orderBy but I don't think we should remve the timestamp. We might soon move away from autoincrement IDs

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@marcelklehr, agreed. timestamp should remain the primary ordering field.

Add id only as a deterministic tie-breaker:

$qb->orderBy('timestamp', 'ASC')
	->addOrderBy('id', 'ASC')

This does not require sequential IDs. It only requires that id has a stable order when two messages have the same timestamp. The primary behavior remains compatible with a future non-auto-increment ID scheme.


✏️ Learnings added
Learnt from: marcelklehr
Repo: nextcloud/assistant PR: 633
File: lib/Db/ChattyLLM/MessageMapper.php:42-45
Timestamp: 2026-08-26T12:00:59.687Z
Learning: In `lib/Db/ChattyLLM/MessageMapper.php`, `MessageMapper::getFirstNMessages()` must preserve `timestamp ASC` as the primary message order. Add `id ASC` only as a deterministic tie-breaker for equal timestamps. The application may replace auto-increment message IDs in the future.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

You are interacting with an AI system.

@julien-nc
julien-nc merged commit 7213ecb into main Aug 26, 2026
15 checks passed
@julien-nc
julien-nc deleted the fix/625/message-order branch August 26, 2026 22:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Chat system prompt gets lost: getFirstNMessages() has no ORDER BY

2 participants