mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-17 08:00:59 +00:00
mom: add [SILENT] response marker for periodic events
When mom responds with just [SILENT], the status message is deleted and nothing is posted to Slack. Useful for periodic events that check for activity but find nothing to report.
This commit is contained in:
parent
d6809328da
commit
8ba6aa6627
5 changed files with 36 additions and 1 deletions
|
|
@ -9,6 +9,7 @@
|
||||||
- One-shot events: trigger at specific time (for reminders)
|
- One-shot events: trigger at specific time (for reminders)
|
||||||
- Periodic events: trigger on cron schedule (for recurring tasks)
|
- Periodic events: trigger on cron schedule (for recurring tasks)
|
||||||
- `SlackBot.enqueueEvent()` for queueing events (max 5 per channel)
|
- `SlackBot.enqueueEvent()` for queueing events (max 5 per channel)
|
||||||
|
- `[SILENT]` response marker: deletes status message, posts nothing to Slack (for periodic events with nothing to report)
|
||||||
- Events documentation in `docs/events.md`
|
- Events documentation in `docs/events.md`
|
||||||
- System prompt section explaining events to mom
|
- System prompt section explaining events to mom
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -130,9 +130,16 @@ When an event is dequeued and executes:
|
||||||
- For one-shot: `[EVENT:dentist.json:one-shot:2025-12-15T09:00:00+01:00] Remind Mario`
|
- For one-shot: `[EVENT:dentist.json:one-shot:2025-12-15T09:00:00+01:00] Remind Mario`
|
||||||
- For periodic: `[EVENT:daily-inbox.json:periodic:0 9 * * 1-5] Check inbox`
|
- For periodic: `[EVENT:daily-inbox.json:periodic:0 9 * * 1-5] Check inbox`
|
||||||
3. After execution:
|
3. After execution:
|
||||||
|
- If response is `[SILENT]`: delete status message, post nothing to Slack
|
||||||
- Immediate and one-shot: delete the event file
|
- Immediate and one-shot: delete the event file
|
||||||
- Periodic: keep the file, event will trigger again on schedule
|
- Periodic: keep the file, event will trigger again on schedule
|
||||||
|
|
||||||
|
## Silent Completion
|
||||||
|
|
||||||
|
For periodic events that check for activity (inbox, notifications, etc.), mom may find nothing to report. To avoid spamming the channel, mom can respond with just `[SILENT]`. This deletes the "Starting event..." status message and posts nothing to Slack.
|
||||||
|
|
||||||
|
Example: A periodic event checks for new emails every 15 minutes. If there are no new emails, mom responds `[SILENT]`. If there are new emails, mom posts a summary.
|
||||||
|
|
||||||
## File Naming
|
## File Naming
|
||||||
|
|
||||||
Event files should have descriptive names ending in `.json`:
|
Event files should have descriptive names ending in `.json`:
|
||||||
|
|
|
||||||
|
|
@ -211,6 +211,9 @@ You receive a message like:
|
||||||
\`\`\`
|
\`\`\`
|
||||||
Immediate and one-shot events auto-delete after triggering. Periodic events persist until you delete them.
|
Immediate and one-shot events auto-delete after triggering. Periodic events persist until you delete them.
|
||||||
|
|
||||||
|
### Silent Completion
|
||||||
|
For periodic events where there's nothing to report, respond with just \`[SILENT]\` (no other text). This deletes the status message and posts nothing to Slack. Use this to avoid spamming the channel when periodic checks find nothing actionable.
|
||||||
|
|
||||||
### Debouncing
|
### Debouncing
|
||||||
When writing programs that create immediate events (email watchers, webhook handlers, etc.), always debounce. If 50 emails arrive in a minute, don't create 50 immediate events. Instead collect events over a window and create ONE immediate event summarizing what happened, or just signal "new activity, check inbox" rather than per-item events. Or simpler: use a periodic event to check for new items every N minutes instead of immediate events.
|
When writing programs that create immediate events (email watchers, webhook handlers, etc.), always debounce. If 50 emails arrive in a minute, don't create 50 immediate events. Instead collect events over a window and create ONE immediate event summarizing what happened, or just signal "new activity, check inbox" rather than per-item events. Or simpler: use a periodic event to check for new items every N minutes instead of immediate events.
|
||||||
|
|
||||||
|
|
@ -687,7 +690,16 @@ function createRunner(sandboxConfig: SandboxConfig, channelId: string, channelDi
|
||||||
.map((c) => c.text)
|
.map((c) => c.text)
|
||||||
.join("\n") || "";
|
.join("\n") || "";
|
||||||
|
|
||||||
if (finalText.trim()) {
|
// Check for [SILENT] marker - delete message instead of posting
|
||||||
|
if (finalText.trim() === "[SILENT]" || finalText.trim().startsWith("[SILENT]")) {
|
||||||
|
try {
|
||||||
|
await ctx.deleteMessage();
|
||||||
|
log.logInfo("Silent response - deleted status message");
|
||||||
|
} catch (err) {
|
||||||
|
const errMsg = err instanceof Error ? err.message : String(err);
|
||||||
|
log.logWarning("Failed to delete message for silent response", errMsg);
|
||||||
|
}
|
||||||
|
} else if (finalText.trim()) {
|
||||||
try {
|
try {
|
||||||
const mainText =
|
const mainText =
|
||||||
finalText.length > SLACK_MAX_LENGTH
|
finalText.length > SLACK_MAX_LENGTH
|
||||||
|
|
|
||||||
|
|
@ -207,6 +207,16 @@ function createSlackContext(event: SlackEvent, slack: SlackBot, state: ChannelSt
|
||||||
});
|
});
|
||||||
await updatePromise;
|
await updatePromise;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
deleteMessage: async () => {
|
||||||
|
updatePromise = updatePromise.then(async () => {
|
||||||
|
if (messageTs) {
|
||||||
|
await slack.deleteMessage(event.channel, messageTs);
|
||||||
|
messageTs = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
await updatePromise;
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,7 @@ export interface SlackContext {
|
||||||
setTyping: (isTyping: boolean) => Promise<void>;
|
setTyping: (isTyping: boolean) => Promise<void>;
|
||||||
uploadFile: (filePath: string, title?: string) => Promise<void>;
|
uploadFile: (filePath: string, title?: string) => Promise<void>;
|
||||||
setWorking: (working: boolean) => Promise<void>;
|
setWorking: (working: boolean) => Promise<void>;
|
||||||
|
deleteMessage: () => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MomHandler {
|
export interface MomHandler {
|
||||||
|
|
@ -192,6 +193,10 @@ export class SlackBot {
|
||||||
await this.webClient.chat.update({ channel, ts, text });
|
await this.webClient.chat.update({ channel, ts, text });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async deleteMessage(channel: string, ts: string): Promise<void> {
|
||||||
|
await this.webClient.chat.delete({ channel, ts });
|
||||||
|
}
|
||||||
|
|
||||||
async postInThread(channel: string, threadTs: string, text: string): Promise<void> {
|
async postInThread(channel: string, threadTs: string, text: string): Promise<void> {
|
||||||
await this.webClient.chat.postMessage({ channel, thread_ts: threadTs, text });
|
await this.webClient.chat.postMessage({ channel, thread_ts: threadTs, text });
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue