watch_messages
Wait for a message to arrive for your terminal. Returns immediately upon receipt or when the timeout expires.
Instructions
Block and wait for a message to arrive for this terminal. Returns as soon as a message is received or timeout is reached.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| terminal_name | Yes | Your terminal name | |
| timeout | No | Max seconds to wait | |
| interval | No | Poll interval in seconds |
Implementation Reference
- src/tools.js:141-163 (handler)The handler function for watch_messages. Polls for messages using list() from messages.js. Deletes messages after reading (deleteAfterRead: true). Loops until a message arrives or timeout is reached, sleeping interval seconds between polls.
async ({ terminal_name, timeout, interval }) => { const deadline = Date.now() + timeout * 1000; while (Date.now() < deadline) { const messages = list(terminal_name, { deleteAfterRead: true }); if (messages.length > 0) { return { content: [ { type: "text", text: renderMessages(terminal_name, messages) }, ], }; } await sleep(interval * 1000); } return { content: [ { type: "text", text: `Watch timed out after ${timeout}s. No messages received for "${terminal_name}".`, }, ], }; }, ); - src/tools.js:124-140 (schema)Input schema for watch_messages: terminal_name (required), timeout (default 300s, max 3600s), interval (default 2s, max 60s). Uses Zod for validation.
{ terminal_name: nameSchema.describe("Your terminal name"), timeout: z .number() .int() .min(1) .max(3600) .default(300) .describe("Max seconds to wait"), interval: z .number() .int() .min(1) .max(60) .default(2) .describe("Poll interval in seconds"), }, - src/tools.js:121-163 (registration)The watch_messages tool is registered via server.tool() in the registerTools function (src/tools.js). It is registered alongside other tools (register, list_terminals, send_message, get_messages).
server.tool( "watch_messages", "Block and wait for a message to arrive for this terminal. Returns as soon as a message is received or timeout is reached.", { terminal_name: nameSchema.describe("Your terminal name"), timeout: z .number() .int() .min(1) .max(3600) .default(300) .describe("Max seconds to wait"), interval: z .number() .int() .min(1) .max(60) .default(2) .describe("Poll interval in seconds"), }, async ({ terminal_name, timeout, interval }) => { const deadline = Date.now() + timeout * 1000; while (Date.now() < deadline) { const messages = list(terminal_name, { deleteAfterRead: true }); if (messages.length > 0) { return { content: [ { type: "text", text: renderMessages(terminal_name, messages) }, ], }; } await sleep(interval * 1000); } return { content: [ { type: "text", text: `Watch timed out after ${timeout}s. No messages received for "${terminal_name}".`, }, ], }; }, ); - src/messages.js:63-105 (helper)The list() function from messages.js, called by watch_messages to poll for messages. It reads JSON message files for the given recipient, filters stale ones, and optionally deletes them after reading.
export function list(to, { deleteAfterRead = false } = {}, now = Date.now) { assertValidName(to); ensureDirs(); const prefix = filePrefix(to); let entries; try { entries = readdirSync(messagesDir()).filter( (f) => f.startsWith(prefix) && f.endsWith(".json"), ); } catch { return []; } entries.sort(); const out = []; const cutoff = now() - MESSAGE_TTL_MS; for (const file of entries) { const path = join(messagesDir(), file); const data = /** @type {{from?: string, sentAt?: string, summary?: string, content?: string} | null} */ ( readJsonSafe(path) ); if (!data) { tryUnlink(path); continue; } const sentMs = data.sentAt ? Date.parse(data.sentAt) : NaN; if (Number.isFinite(sentMs) && sentMs < cutoff) { tryUnlink(path); continue; } out.push({ file, ...data }); } if (deleteAfterRead) { for (const m of out) { tryUnlink(join(messagesDir(), m.file)); } } return out; } - src/tools.js:188-190 (helper)Helper sleep function used by watch_messages to wait between poll intervals.
function sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); }