diff --git a/container/agent-runner/src/ipc-mcp.ts b/container/agent-runner/src/ipc-mcp.ts index 4b98216..dd42078 100644 --- a/container/agent-runner/src/ipc-mcp.ts +++ b/container/agent-runner/src/ipc-mcp.ts @@ -70,14 +70,25 @@ export function createIpcMcp(ctx: IpcMcpContext) { 'schedule_task', `Schedule a recurring or one-time task. The task will run as a full agent with access to all tools. -IMPORTANT - schedule_value format depends on schedule_type: +CONTEXT MODE - Choose based on task type: +• "group" (recommended for most tasks): Task runs in the group's conversation context, with access to chat history and memory. Use for tasks that need context about ongoing discussions, user preferences, or previous interactions. +• "isolated": Task runs in a fresh session with no conversation history. Use for independent tasks that don't need prior context. When using isolated mode, include all necessary context in the prompt itself. + +If unsure which mode to use, ask the user. Examples: +- "Remind me about our discussion" → group (needs conversation context) +- "Check the weather every morning" → isolated (self-contained task) +- "Follow up on my request" → group (needs to know what was requested) +- "Generate a daily report" → isolated (just needs instructions in prompt) + +SCHEDULE VALUE FORMAT: • cron: Standard cron expression (e.g., "*/5 * * * *" for every 5 minutes, "0 9 * * *" for daily at 9am) • interval: Milliseconds between runs (e.g., "300000" for 5 minutes, "3600000" for 1 hour) • once: ISO 8601 timestamp (e.g., "2026-02-01T15:30:00.000Z"). Calculate this from current time.`, { - prompt: z.string().describe('What the agent should do when the task runs'), + prompt: z.string().describe('What the agent should do when the task runs. For isolated mode, include all necessary context here.'), schedule_type: z.enum(['cron', 'interval', 'once']).describe('cron=recurring at specific times, interval=recurring every N ms, once=run once at specific time'), schedule_value: z.string().describe('cron: "*/5 * * * *" | interval: milliseconds like "300000" | once: ISO timestamp like "2026-02-01T15:30:00.000Z"'), + context_mode: z.enum(['group', 'isolated']).default('group').describe('group=runs with chat history and memory, isolated=fresh session (include context in prompt)'), target_group: z.string().optional().describe('Target group folder (main only, defaults to current group)') }, async (args) => { @@ -117,6 +128,7 @@ IMPORTANT - schedule_value format depends on schedule_type: prompt: args.prompt, schedule_type: args.schedule_type, schedule_value: args.schedule_value, + context_mode: args.context_mode || 'group', groupFolder: targetGroup, chatJid, createdBy: groupFolder, diff --git a/src/db.ts b/src/db.ts index 76984e2..6571250 100644 --- a/src/db.ts +++ b/src/db.ts @@ -64,6 +64,11 @@ export function initDatabase(): void { try { db.exec(`ALTER TABLE messages ADD COLUMN sender_name TEXT`); } catch { /* column already exists */ } + + // Add context_mode column if it doesn't exist (migration for existing DBs) + try { + db.exec(`ALTER TABLE scheduled_tasks ADD COLUMN context_mode TEXT DEFAULT 'isolated'`); + } catch { /* column already exists */ } } /** @@ -131,8 +136,8 @@ export function getMessagesSince(chatJid: string, sinceTimestamp: string): NewMe export function createTask(task: Omit): void { db.prepare(` - INSERT INTO scheduled_tasks (id, group_folder, chat_jid, prompt, schedule_type, schedule_value, next_run, status, created_at) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) + INSERT INTO scheduled_tasks (id, group_folder, chat_jid, prompt, schedule_type, schedule_value, context_mode, next_run, status, created_at) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) `).run( task.id, task.group_folder, @@ -140,6 +145,7 @@ export function createTask(task: Omit task.prompt, task.schedule_type, task.schedule_value, + task.context_mode || 'isolated', task.next_run, task.status, task.created_at diff --git a/src/index.ts b/src/index.ts index 211d572..467b512 100644 --- a/src/index.ts +++ b/src/index.ts @@ -237,6 +237,7 @@ async function processTaskIpc( prompt?: string; schedule_type?: string; schedule_value?: string; + context_mode?: string; groupFolder?: string; chatJid?: string; }, @@ -295,6 +296,9 @@ async function processTaskIpc( } const taskId = `task-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`; + const contextMode = (data.context_mode === 'group' || data.context_mode === 'isolated') + ? data.context_mode + : 'isolated'; createTask({ id: taskId, group_folder: targetGroup, @@ -302,11 +306,12 @@ async function processTaskIpc( prompt: data.prompt, schedule_type: scheduleType, schedule_value: data.schedule_value, + context_mode: contextMode, next_run: nextRun, status: 'active', created_at: new Date().toISOString() }); - logger.info({ taskId, sourceGroup, targetGroup }, 'Task created via IPC'); + logger.info({ taskId, sourceGroup, targetGroup, contextMode }, 'Task created via IPC'); } break; @@ -388,7 +393,11 @@ async function connectWhatsApp(): Promise { } } else if (connection === 'open') { logger.info('Connected to WhatsApp'); - startSchedulerLoop({ sendMessage, registeredGroups: () => registeredGroups }); + startSchedulerLoop({ + sendMessage, + registeredGroups: () => registeredGroups, + getSessions: () => sessions + }); startIpcWatcher(); startMessageLoop(); } diff --git a/src/task-scheduler.ts b/src/task-scheduler.ts index 918b51d..65c353d 100644 --- a/src/task-scheduler.ts +++ b/src/task-scheduler.ts @@ -15,6 +15,7 @@ const logger = pino({ export interface SchedulerDependencies { sendMessage: (jid: string, text: string) => Promise; registeredGroups: () => Record; + getSessions: () => Record; } async function runTask(task: ScheduledTask, deps: SchedulerDependencies): Promise { @@ -56,9 +57,14 @@ async function runTask(task: ScheduledTask, deps: SchedulerDependencies): Promis let result: string | null = null; let error: string | null = null; + // For group context mode, use the group's current session + const sessions = deps.getSessions(); + const sessionId = task.context_mode === 'group' ? sessions[task.group_folder] : undefined; + try { const output = await runContainerAgent(group, { prompt: task.prompt, + sessionId, groupFolder: task.group_folder, chatJid: task.chat_jid, isMain, diff --git a/src/types.ts b/src/types.ts index 3f5fa62..869bd8f 100644 --- a/src/types.ts +++ b/src/types.ts @@ -38,6 +38,7 @@ export interface ScheduledTask { prompt: string; schedule_type: 'cron' | 'interval' | 'once'; schedule_value: string; + context_mode: 'group' | 'isolated'; next_run: string | null; last_run: string | null; last_result: string | null;