diff --git a/src/utils/queue-helpers.ts b/src/utils/queue-helpers.ts index c7bf35331b5e..37677a7c8d33 100644 --- a/src/utils/queue-helpers.ts +++ b/src/utils/queue-helpers.ts @@ -30,11 +30,20 @@ export function previewQueueSummaryPrompt(params: { noun: string; title?: string; }): string | undefined { - return buildQueueSummaryPrompt({ - state: params.state, - noun: params.noun, - title: params.title, - }); + if (params.state.droppedCount <= 0) { + return undefined; + } + const title = + params.title ?? + `[Queue overflow] Dropped ${params.state.droppedCount} ${params.noun}${params.state.droppedCount === 1 ? "" : "s"} due to cap.`; + const lines = [title]; + if (params.state.summaryLines.length > 0) { + lines.push("Summary:"); + for (const line of params.state.summaryLines) { + lines.push(`- ${line}`); + } + } + return lines.join("\n"); } /** Apply runtime queue settings while preserving previous values for omitted fields. */ @@ -64,18 +73,12 @@ export function applyQueueRuntimeSettings(params: { params.target.dropPolicy = params.settings.dropPolicy ?? params.target.dropPolicy; } -/** Trim queue summary text to a bounded single-line preview. */ -function elideQueueText(text: string, limit = 140): string { - if (text.length <= limit) { - return text; - } - return `${truncateUtf16Safe(text, Math.max(0, limit - 1)).trimEnd()}…`; -} - /** Normalize whitespace and elide one dropped item for queue summaries. */ function buildQueueSummaryLine(text: string, limit = 160): string { const cleaned = text.replace(/\s+/g, " ").trim(); - return elideQueueText(cleaned, limit); + return cleaned.length <= limit + ? cleaned + : `${truncateUtf16Safe(cleaned, Math.max(0, limit - 1)).trimEnd()}…`; } /** Run optional duplicate detection before an item enters a queue. */ @@ -269,26 +272,6 @@ export async function drainNextQueueItem( return true; } -/** Drain one item when collect mode requires individual processing. */ -async function drainCollectItemIfNeeded(params: { - forceIndividualCollect: boolean; - isCrossChannel: boolean; - setForceIndividualCollect?: (next: boolean) => void; - items: T[]; - run: (item: T) => Promise; - reserveOptions?: DrainQueueItemOptions; -}): Promise<"skipped" | "drained" | "empty"> { - if (!params.forceIndividualCollect && !params.isCrossChannel) { - return "skipped"; - } - if (params.isCrossChannel) { - // Once cross-channel items appear, future collection stays individual to preserve ordering. - params.setForceIndividualCollect?.(true); - } - const drained = await drainNextQueueItem(params.items, params.run, params.reserveOptions); - return drained ? "drained" : "empty"; -} - /** Drain one collect step using mutable queue collection state. */ export async function drainCollectQueueStep(params: { collectState: { forceIndividualCollect: boolean }; @@ -297,39 +280,15 @@ export async function drainCollectQueueStep(params: { run: (item: T) => Promise; reserveOptions?: DrainQueueItemOptions; }): Promise<"skipped" | "drained" | "empty"> { - return await drainCollectItemIfNeeded({ - forceIndividualCollect: params.collectState.forceIndividualCollect, - isCrossChannel: params.isCrossChannel, - setForceIndividualCollect: (next) => { - params.collectState.forceIndividualCollect = next; - }, - items: params.items, - run: params.run, - reserveOptions: params.reserveOptions, - }); -} - -/** Build the queue overflow summary prompt. */ -function buildQueueSummaryPrompt(params: { - state: QueueSummaryState; - noun: string; - title?: string; -}): string | undefined { - if (params.state.droppedCount <= 0) { - return undefined; + if (!params.collectState.forceIndividualCollect && !params.isCrossChannel) { + return "skipped"; } - const noun = params.noun; - const title = - params.title ?? - `[Queue overflow] Dropped ${params.state.droppedCount} ${noun}${params.state.droppedCount === 1 ? "" : "s"} due to cap.`; - const lines = [title]; - if (params.state.summaryLines.length > 0) { - lines.push("Summary:"); - for (const line of params.state.summaryLines) { - lines.push(`- ${line}`); - } + if (params.isCrossChannel) { + // Once cross-channel items appear, future collection stays individual to preserve ordering. + params.collectState.forceIndividualCollect = true; } - return lines.join("\n"); + const drained = await drainNextQueueItem(params.items, params.run, params.reserveOptions); + return drained ? "drained" : "empty"; } /** Render a collect prompt from queued items and optional overflow summary. */