fix(mom): private channel messages not being logged

- Add message.groups to required bot events in README
- Add groups:history and groups:read to required scopes in README
- app_mention handler now logs messages directly instead of relying on message event
- Add deduplication in ChannelStore.logMessage() to prevent double-logging
- Remove redundant current message append in agent.ts (already in log)
This commit is contained in:
Mario Zechner 2025-12-04 12:24:29 +01:00
parent db6d655ee9
commit 706554a5d3
6 changed files with 67 additions and 11 deletions

View file

@ -364,15 +364,7 @@ export function createAgentRunner(sandboxConfig: SandboxConfig): AgentRunner {
const channelId = ctx.message.channel;
const workspacePath = executor.getWorkspacePath(channelDir.replace(`/${channelId}`, ""));
const recentMessagesFromLog = getRecentMessages(channelDir, 50);
// Append the current message (may not be in log yet due to race condition
// between app_mention and message events)
const currentMsgDate = new Date(parseFloat(ctx.message.ts) * 1000).toISOString().substring(0, 19);
const currentMsgUser = ctx.message.userName || ctx.message.user;
const currentMsgAttachments = ctx.message.attachments.map((a) => a.local).join(",");
const currentMsgLine = `${currentMsgDate}\t${currentMsgUser}\t${ctx.message.rawText}\t${currentMsgAttachments}`;
const recentMessages = recentMessagesFromLog + "\n" + currentMsgLine;
const recentMessages = getRecentMessages(channelDir, 50);
const memory = getMemory(channelDir);
const systemPrompt = buildSystemPrompt(

View file

@ -208,7 +208,6 @@ export class MomBot {
private setupEventHandlers(): void {
// Handle @mentions in channels
// Note: We don't log here - the message event handler logs all messages
this.socketClient.on("app_mention", async ({ event, ack }) => {
await ack();
@ -220,6 +219,15 @@ export class MomBot {
files?: Array<{ name: string; url_private_download?: string; url_private?: string }>;
};
// Log the mention message (message event may not fire for all channel types)
await this.logMessage({
text: slackEvent.text,
channel: slackEvent.channel,
user: slackEvent.user,
ts: slackEvent.ts,
files: slackEvent.files,
});
const ctx = await this.createContext(slackEvent);
await this.handler.onChannelMention(ctx);
});

View file

@ -35,6 +35,9 @@ export class ChannelStore {
private botToken: string;
private pendingDownloads: PendingDownload[] = [];
private isDownloading = false;
// Track recently logged message timestamps to prevent duplicates
// Key: "channelId:ts", automatically cleaned up after 60 seconds
private recentlyLogged = new Map<string, number>();
constructor(config: ChannelStoreConfig) {
this.workingDir = config.workingDir;
@ -107,8 +110,19 @@ export class ChannelStore {
/**
* Log a message to the channel's log.jsonl
* Returns false if message was already logged (duplicate)
*/
async logMessage(channelId: string, message: LoggedMessage): Promise<void> {
async logMessage(channelId: string, message: LoggedMessage): Promise<boolean> {
// Check for duplicate (same channel + timestamp)
const dedupeKey = `${channelId}:${message.ts}`;
if (this.recentlyLogged.has(dedupeKey)) {
return false; // Already logged
}
// Mark as logged and schedule cleanup after 60 seconds
this.recentlyLogged.set(dedupeKey, Date.now());
setTimeout(() => this.recentlyLogged.delete(dedupeKey), 60000);
const logPath = join(this.getChannelDir(channelId), "log.jsonl");
// Ensure message has a date field
@ -127,6 +141,7 @@ export class ChannelStore {
const line = JSON.stringify(message) + "\n";
await appendFile(logPath, line, "utf-8");
return true;
}
/**