From f2afb11e7172409497a4d35dd0d95af44e8ce4c0 Mon Sep 17 00:00:00 2001 From: gavrielc Date: Sat, 31 Jan 2026 19:29:09 +0200 Subject: [PATCH] Include missed messages when catching up the agent When a triggered message comes in, fetch all messages in that chat since the last agent interaction and include them in the prompt. Each message is formatted with timestamp and sender. Co-Authored-By: Claude Opus 4.5 --- src/db.ts | 10 ++++++++++ src/index.ts | 34 ++++++++++++++++++++++++++++------ 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/src/db.ts b/src/db.ts index e0c7882..d7cd7f9 100644 --- a/src/db.ts +++ b/src/db.ts @@ -72,3 +72,13 @@ export function getNewMessages(jids: string[], lastTimestamp: string): { message return { messages: rows, newTimestamp }; } + +export function getMessagesSince(chatJid: string, sinceTimestamp: string): NewMessage[] { + const sql = ` + SELECT id, chat_jid, sender, content, timestamp + FROM messages + WHERE chat_jid = ? AND timestamp > ? + ORDER BY timestamp + `; + return db.prepare(sql).all(chatJid, sinceTimestamp) as NewMessage[]; +} diff --git a/src/index.ts b/src/index.ts index 89d3d27..8c0f367 100644 --- a/src/index.ts +++ b/src/index.ts @@ -20,7 +20,7 @@ import { CLEAR_COMMAND } from './config.js'; import { RegisteredGroup, Session, NewMessage } from './types.js'; -import { initDatabase, storeMessage, getNewMessages } from './db.js'; +import { initDatabase, storeMessage, getNewMessages, getMessagesSince } from './db.js'; const logger = pino({ level: process.env.LOG_LEVEL || 'info', @@ -31,6 +31,7 @@ let sock: WASocket; let lastTimestamp = ''; let sessions: Session = {}; let registeredGroups: Record = {}; +let lastAgentTimestamp: Record = {}; function loadJson(filePath: string, defaultValue: T): T { try { @@ -50,15 +51,16 @@ function saveJson(filePath: string, data: unknown): void { function loadState(): void { const statePath = path.join(DATA_DIR, 'router_state.json'); - const state = loadJson<{ last_timestamp?: string }>(statePath, {}); + const state = loadJson<{ last_timestamp?: string; last_agent_timestamp?: Record }>(statePath, {}); lastTimestamp = state.last_timestamp || ''; + lastAgentTimestamp = state.last_agent_timestamp || {}; sessions = loadJson(path.join(DATA_DIR, 'sessions.json'), {}); registeredGroups = loadJson(path.join(DATA_DIR, 'registered_groups.json'), {}); logger.info({ groupCount: Object.keys(registeredGroups).length }, 'State loaded'); } function saveState(): void { - saveJson(path.join(DATA_DIR, 'router_state.json'), { last_timestamp: lastTimestamp }); + saveJson(path.join(DATA_DIR, 'router_state.json'), { last_timestamp: lastTimestamp, last_agent_timestamp: lastAgentTimestamp }); saveJson(path.join(DATA_DIR, 'sessions.json'), sessions); } @@ -86,11 +88,31 @@ async function processMessage(msg: NewMessage): Promise { if (!TRIGGER_PATTERN.test(content)) return; - const prompt = content.replace(TRIGGER_PATTERN, '').trim(); - if (!prompt) return; + const userMessage = content.replace(TRIGGER_PATTERN, '').trim(); + if (!userMessage) return; - logger.info({ group: group.name, prompt: prompt.slice(0, 50) }, 'Processing message'); + // Get messages since last agent interaction to catch up the session + const sinceTimestamp = lastAgentTimestamp[msg.chat_jid] || ''; + const missedMessages = getMessagesSince(msg.chat_jid, sinceTimestamp); + + // Build prompt with conversation history + let prompt = ''; + for (const m of missedMessages) { + if (m.id === msg.id) continue; // Skip current message, we'll add it at the end + const time = new Date(m.timestamp).toLocaleTimeString(); + const sender = m.sender.split('@')[0]; // Extract phone number or name + prompt += `[${time}] ${sender}: ${m.content}\n`; + } + const time = new Date(msg.timestamp).toLocaleTimeString(); + const sender = msg.sender.split('@')[0]; + prompt += `[${time}] ${sender}: ${userMessage}`; + + logger.info({ group: group.name, messageCount: missedMessages.length }, 'Processing message'); const response = await runAgent(group, prompt); + + // Update last agent timestamp + lastAgentTimestamp[msg.chat_jid] = msg.timestamp; + if (response) { await sendMessage(msg.chat_jid, `${ASSISTANT_NAME}: ${response}`); }