feat: add reply/quoted message context support

Add generic reply context fields to NewMessage (reply_to_message_id,
reply_to_message_content, reply_to_sender_name) so any channel can
pass quoted message context to the agent.

- Add thread_id and reply_to_* fields to NewMessage interface
- Add DB migration for reply context columns on messages table
- Update storeMessage/getMessagesSince/getNewMessages to persist and
  retrieve reply fields
- Render reply context as <quoted_message> XML in formatMessages
- Add DB and formatting tests

Co-Authored-By: Alfred-the-buttler <leon.alfred.bot@gmail.com>
Co-Authored-By: moktamd <moktamd@users.noreply.github.com>
Co-Authored-By: gurixs-carson <gurixs-carson@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
exe.dev user
2026-04-02 17:05:24 +00:00
parent 7b337a7a07
commit ee599b9f0c
5 changed files with 171 additions and 4 deletions

View File

@@ -146,6 +146,21 @@ function createSchema(database: Database.Database): void {
} catch {
/* columns already exist */
}
// Add reply context columns if they don't exist (migration for existing DBs)
try {
database.exec(
`ALTER TABLE messages ADD COLUMN reply_to_message_id TEXT`,
);
database.exec(
`ALTER TABLE messages ADD COLUMN reply_to_message_content TEXT`,
);
database.exec(
`ALTER TABLE messages ADD COLUMN reply_to_sender_name TEXT`,
);
} catch {
/* columns already exist */
}
}
export function initDatabase(): void {
@@ -274,7 +289,7 @@ export function setLastGroupSync(): void {
*/
export function storeMessage(msg: NewMessage): void {
db.prepare(
`INSERT OR REPLACE INTO messages (id, chat_jid, sender, sender_name, content, timestamp, is_from_me, is_bot_message) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
`INSERT OR REPLACE INTO messages (id, chat_jid, sender, sender_name, content, timestamp, is_from_me, is_bot_message, reply_to_message_id, reply_to_message_content, reply_to_sender_name) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
).run(
msg.id,
msg.chat_jid,
@@ -284,6 +299,9 @@ export function storeMessage(msg: NewMessage): void {
msg.timestamp,
msg.is_from_me ? 1 : 0,
msg.is_bot_message ? 1 : 0,
msg.reply_to_message_id ?? null,
msg.reply_to_message_content ?? null,
msg.reply_to_sender_name ?? null,
);
}
@@ -328,7 +346,8 @@ export function getNewMessages(
// Subquery takes the N most recent, outer query re-sorts chronologically.
const sql = `
SELECT * FROM (
SELECT id, chat_jid, sender, sender_name, content, timestamp, is_from_me
SELECT id, chat_jid, sender, sender_name, content, timestamp, is_from_me,
reply_to_message_id, reply_to_message_content, reply_to_sender_name
FROM messages
WHERE timestamp > ? AND chat_jid IN (${placeholders})
AND is_bot_message = 0 AND content NOT LIKE ?
@@ -361,7 +380,8 @@ export function getMessagesSince(
// Subquery takes the N most recent, outer query re-sorts chronologically.
const sql = `
SELECT * FROM (
SELECT id, chat_jid, sender, sender_name, content, timestamp, is_from_me
SELECT id, chat_jid, sender, sender_name, content, timestamp, is_from_me,
reply_to_message_id, reply_to_message_content, reply_to_sender_name
FROM messages
WHERE chat_jid = ? AND timestamp > ?
AND is_bot_message = 0 AND content NOT LIKE ?