openclaw/src/auto-reply/reply/queue/enqueue.ts
Peter Steinberger c7ae5100fa refactor: share queue helpers
Co-authored-by: adam91holt <adam91holt@users.noreply.github.com>
2026-01-17 06:02:27 +00:00

73 lines
2.3 KiB
TypeScript

import { buildQueueSummaryLine } 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);
// Deduplicate: skip if the same message is already queued.
if (dedupeMode !== "none") {
if (dedupeMode === "message-id" && isRunAlreadyQueued(run, queue.items)) {
return false;
}
if (dedupeMode === "prompt" && isRunAlreadyQueued(run, queue.items, true)) {
return false;
}
}
queue.lastEnqueuedAt = Date.now();
queue.lastRun = run.run;
const cap = queue.cap;
if (cap > 0 && queue.items.length >= cap) {
if (queue.dropPolicy === "new") {
return false;
}
const dropCount = queue.items.length - cap + 1;
const dropped = queue.items.splice(0, dropCount);
if (queue.dropPolicy === "summarize") {
for (const item of dropped) {
queue.droppedCount += 1;
const base = item.summaryLine?.trim() || item.prompt.trim();
queue.summaryLines.push(buildQueueSummaryLine(base));
}
while (queue.summaryLines.length > cap) queue.summaryLines.shift();
}
}
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;
}