mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-21 20:04:55 +00:00
mom: add events system for scheduled wake-ups
- Three event types: immediate, one-shot, periodic (cron) - Events are JSON files in workspace/events/ - EventsWatcher with fs.watch, 100ms debounce - Queue integration via SlackBot.enqueueEvent() (max 5) - Fix setTyping race condition causing duplicate messages - System prompt documents events for mom - Design doc in docs/events.md - Add croner dependency for cron scheduling
This commit is contained in:
parent
03c404c15f
commit
d6809328da
9 changed files with 847 additions and 7 deletions
|
|
@ -4,6 +4,7 @@ import { join, resolve } from "path";
|
|||
import { type AgentRunner, getOrCreateRunner } from "./agent.js";
|
||||
import { syncLogToContext } from "./context.js";
|
||||
import { downloadChannel } from "./download.js";
|
||||
import { createEventsWatcher } from "./events.js";
|
||||
import * as log from "./log.js";
|
||||
import { parseSandboxArg, type SandboxConfig, validateSandbox } from "./sandbox.js";
|
||||
import { type MomHandler, type SlackBot, SlackBot as SlackBotClass, type SlackEvent } from "./slack.js";
|
||||
|
|
@ -113,7 +114,7 @@ function getState(channelId: string): ChannelState {
|
|||
// Create SlackContext adapter
|
||||
// ============================================================================
|
||||
|
||||
function createSlackContext(event: SlackEvent, slack: SlackBot, state: ChannelState) {
|
||||
function createSlackContext(event: SlackEvent, slack: SlackBot, state: ChannelState, isEvent?: boolean) {
|
||||
let messageTs: string | null = null;
|
||||
let accumulatedText = "";
|
||||
let isWorking = true;
|
||||
|
|
@ -122,6 +123,9 @@ function createSlackContext(event: SlackEvent, slack: SlackBot, state: ChannelSt
|
|||
|
||||
const user = slack.getUser(event.user);
|
||||
|
||||
// Extract event filename for status message
|
||||
const eventFilename = isEvent ? event.text.match(/^\[EVENT:([^:]+):/)?.[1] : undefined;
|
||||
|
||||
return {
|
||||
message: {
|
||||
text: event.text,
|
||||
|
|
@ -179,8 +183,13 @@ function createSlackContext(event: SlackEvent, slack: SlackBot, state: ChannelSt
|
|||
|
||||
setTyping: async (isTyping: boolean) => {
|
||||
if (isTyping && !messageTs) {
|
||||
accumulatedText = "_Thinking_";
|
||||
messageTs = await slack.postMessage(event.channel, accumulatedText + workingIndicator);
|
||||
updatePromise = updatePromise.then(async () => {
|
||||
if (!messageTs) {
|
||||
accumulatedText = eventFilename ? `_Starting event: ${eventFilename}_` : "_Thinking_";
|
||||
messageTs = await slack.postMessage(event.channel, accumulatedText + workingIndicator);
|
||||
}
|
||||
});
|
||||
await updatePromise;
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -223,7 +232,7 @@ const handler: MomHandler = {
|
|||
}
|
||||
},
|
||||
|
||||
async handleEvent(event: SlackEvent, slack: SlackBot): Promise<void> {
|
||||
async handleEvent(event: SlackEvent, slack: SlackBot, isEvent?: boolean): Promise<void> {
|
||||
const state = getState(event.channel);
|
||||
const channelDir = join(workingDir, event.channel);
|
||||
|
||||
|
|
@ -243,7 +252,7 @@ const handler: MomHandler = {
|
|||
}
|
||||
|
||||
// Create context adapter
|
||||
const ctx = createSlackContext(event, slack, state);
|
||||
const ctx = createSlackContext(event, slack, state, isEvent);
|
||||
|
||||
// Run the agent
|
||||
await ctx.setTyping(true);
|
||||
|
|
@ -283,4 +292,21 @@ const bot = new SlackBotClass(handler, {
|
|||
store: sharedStore,
|
||||
});
|
||||
|
||||
// Start events watcher
|
||||
const eventsWatcher = createEventsWatcher(workingDir, bot);
|
||||
eventsWatcher.start();
|
||||
|
||||
// Handle shutdown
|
||||
process.on("SIGINT", () => {
|
||||
log.logInfo("Shutting down...");
|
||||
eventsWatcher.stop();
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
process.on("SIGTERM", () => {
|
||||
log.logInfo("Shutting down...");
|
||||
eventsWatcher.stop();
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
bot.start();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue