import { applyQueueDropPolicy, shouldSkipQueueItem } from "../../../utils/queue-helpers.js"; import { FOLLOWUP_QUEUES, getFollowupQueue } from "./state.js"; import type { FollowupRun, QueueDedupeMode, QueueSettings } from "./types.js"; function isRunAlreadyQueued( run: FollowupRun, items: FollowupRun[], allowPromptFallback = false, ): boolean { const hasSameRouting = (item: FollowupRun) => item.originatingChannel === run.originatingChannel && item.originatingTo === run.originatingTo && item.originatingAccountId === run.originatingAccountId && item.originatingThreadId === run.originatingThreadId; const messageId = run.messageId?.trim(); if (messageId) { return items.some((item) => item.messageId?.trim() === messageId && hasSameRouting(item)); } if (!allowPromptFallback) return false; return items.some((item) => item.prompt === run.prompt && hasSameRouting(item)); } export function enqueueFollowupRun( key: string, run: FollowupRun, settings: QueueSettings, dedupeMode: QueueDedupeMode = "message-id", ): boolean { const queue = getFollowupQueue(key, settings); const dedupe = dedupeMode === "none" ? undefined : (item: FollowupRun, items: FollowupRun[]) => isRunAlreadyQueued(item, items, dedupeMode === "prompt"); // Deduplicate: skip if the same message is already queued. if (shouldSkipQueueItem({ item: run, items: queue.items, dedupe })) return false; queue.lastEnqueuedAt = Date.now(); queue.lastRun = run.run; const shouldEnqueue = applyQueueDropPolicy({ queue, summarize: (item) => item.summaryLine?.trim() || item.prompt.trim(), }); if (!shouldEnqueue) return false; queue.items.push(run); return true; } export function getFollowupQueueDepth(key: string): number { const cleaned = key.trim(); if (!cleaned) return 0; const queue = FOLLOWUP_QUEUES.get(cleaned); if (!queue) return 0; return queue.items.length; }