diff --git a/src/index.ts b/src/index.ts index 5bc9de9..752a486 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,6 +7,7 @@ import { DATA_DIR, IDLE_TIMEOUT, POLL_INTERVAL, + REVIEWER_AGENT_TYPE, SERVICE_ID, SERVICE_AGENT_TYPE, isSessionCommandSenderAllowed, @@ -46,6 +47,7 @@ import { resolveGroupFolderPath, resolveGroupIpcPath } from './group-folder.js'; import { startIpcWatcher } from './ipc.js'; import { findChannel, + findChannelByName, formatOutbound, normalizeMessageForDedupe, } from './router.js'; @@ -437,6 +439,15 @@ async function main(): Promise { } // Start subsystems (independently of connection handler) + // Resolve the reviewer channel so cron output in paired rooms is posted + // via the reviewer bot — the owner then treats it as a peer request. + const reviewerChannelName = + REVIEWER_AGENT_TYPE === 'claude-code' ? 'discord' : 'discord-review'; + const reviewerChannelForCron = findChannelByName( + channels, + reviewerChannelName, + ); + startSchedulerLoop({ registeredGroups: () => registeredGroups, getSessions: () => sessions, @@ -445,6 +456,12 @@ async function main(): Promise { queue.registerProcess(groupJid, proc, processName, ipcDir), sendMessage: (jid, rawText) => sendFormattedChannelMessage(channels, jid, rawText), + sendMessageViaReviewerBot: reviewerChannelForCron + ? async (jid, rawText) => { + const text = formatOutbound(rawText); + if (text) await reviewerChannelForCron.sendMessage(jid, text); + } + : undefined, sendTrackedMessage: (jid, rawText) => sendFormattedTrackedChannelMessage(channels, jid, rawText), editTrackedMessage: (jid, messageId, rawText) => diff --git a/src/task-scheduler.ts b/src/task-scheduler.ts index 54833c1..7cbad9a 100644 --- a/src/task-scheduler.ts +++ b/src/task-scheduler.ts @@ -20,6 +20,7 @@ import { deleteTask, getDueTasks, getTaskById, + isPairedRoomJid, logTaskRun, updateTask, updateTaskAfterRun, @@ -161,6 +162,8 @@ export interface SchedulerDependencies { ipcDir: string, ) => void; sendMessage: (jid: string, text: string) => Promise; + /** Send a message via the reviewer bot identity so the owner treats it as a peer request. */ + sendMessageViaReviewerBot?: (jid: string, text: string) => Promise; sendTrackedMessage?: (jid: string, text: string) => Promise; editTrackedMessage?: ( jid: string, @@ -402,7 +405,13 @@ async function runTask( const outputText = getAgentOutputText(streamedOutput); if (outputText) { attemptResult = outputText; - await deps.sendMessage(task.chat_jid, outputText); + // In paired rooms, post cron output via reviewer bot so the + // owner treats it as a peer request and acts on it. + const send = + isPairedRoomJid(task.chat_jid) && deps.sendMessageViaReviewerBot + ? deps.sendMessageViaReviewerBot + : deps.sendMessage; + await send(task.chat_jid, outputText); } if (streamedOutput.status === 'error') {