UNPKG

naisys

Version:

NAISYS - Autonomous AI agent runner with built-in context management and cost tracking

111 lines 4.29 kB
/** Derive a notification's kind from which payload field is populated. */ export function getNotificationKind(n) { if (n.contextCommands !== undefined) return "contextCommand"; if (n.debugCommands !== undefined) return "debugCommand"; return "nonCommand"; } export function createPromptNotificationService() { /** Per-user notification queues keyed by userId */ const pending = new Map(); /** Single global notification — new one overwrites old */ let globalNotification = null; /** Tracks which userIds have seen the current global notification */ const globalNotifiedUserIds = new Set(); function notify(notification) { if (!notification.userId) { // Global notification: overwrite previous, reset seen set globalNotification = notification; globalNotifiedUserIds.clear(); return; } const userId = notification.userId; if (!pending.has(userId)) { pending.set(userId, []); } pending.get(userId).push(notification); } function shouldWake(wake, wakeOnMessage) { return wake === "always" || (wake === "yes" && wakeOnMessage); } function matchesKind(notification, kind) { return kind === undefined || getNotificationKind(notification) === kind; } function hasPending(userId, wakeOnMessage, kind) { const userQueue = pending.get(userId) || []; // Check user's own queue if (userQueue.some((n) => matchesKind(n, kind) && shouldWake(n.wake, wakeOnMessage))) { return true; } // Check unseen global notification if (globalNotification && !globalNotifiedUserIds.has(userId) && matchesKind(globalNotification, kind) && shouldWake(globalNotification.wake, wakeOnMessage)) { return true; } return false; } function collectNotification(notification, result) { if (notification.contextOutput) { for (const text of notification.contextOutput) { result.output.push({ type: "context", text }); } } if (notification.commentOutput) { for (const text of notification.commentOutput) { result.output.push({ type: "comment", text }); } } if (notification.errorOutput) { for (const text of notification.errorOutput) { result.output.push({ type: "error", text }); } } if (notification.contextCommands) { result.contextCommands.push(...notification.contextCommands); } if (notification.debugCommands) { result.debugCommands.push(...notification.debugCommands); } } /** Drains notifications matching `kind` (or all if omitted); others stay * queued for the path that owns that kind. */ async function processPending(userId, kind) { const result = { output: [], contextCommands: [], debugCommands: [], drained: false, }; // Process user-specific notifications const userQueue = pending.get(userId); if (userQueue) { const keep = []; while (userQueue.length > 0) { const notification = userQueue.shift(); if (!matchesKind(notification, kind)) { keep.push(notification); continue; } collectNotification(notification, result); result.drained = true; await notification.processed?.(); } userQueue.push(...keep); } // Process global notification if unseen and matches kind filter if (globalNotification && !globalNotifiedUserIds.has(userId) && matchesKind(globalNotification, kind)) { globalNotifiedUserIds.add(userId); collectNotification(globalNotification, result); result.drained = true; await globalNotification.processed?.(); } return result; } return { notify, hasPending, processPending }; } //# sourceMappingURL=promptNotificationService.js.map