import type { QueuedSuperagentMessage } from '../../types'; // Max concurrent turns the backend accepts for one conversation: the running turn // plus the ones waiting behind it. Mirrors the web agent-editor's MAX_PENDING // (pages/agent-editor/hooks/useChatActions.ts). export const MAX_PENDING_TURNS = 4; export function addQueued( queue: QueuedSuperagentMessage[], item: { id: string; content: string }, ): QueuedSuperagentMessage[] { return [...queue, { id: item.id, content: item.content, position: queue.length }]; } export function removeQueued(queue: QueuedSuperagentMessage[], id: string): QueuedSuperagentMessage[] { return queue.filter((message) => message.id !== id).map((message, index) => ({ ...message, position: index })); } export function editQueued(queue: QueuedSuperagentMessage[], id: string, content: string): QueuedSuperagentMessage[] { return queue.map((message) => (message.id === id ? { ...message, content } : message)); } // Dequeue the head for promotion into the live thread when a turn finishes; the // rest keep their FIFO order with positions re-based. export function promoteQueued( queue: QueuedSuperagentMessage[], ): { head: QueuedSuperagentMessage | null; rest: QueuedSuperagentMessage[] } { if (queue.length === 0) return { head: null, rest: queue }; const [head, ...rest] = queue; return { head, rest: rest.map((message, index) => ({ ...message, position: index })) }; } // Reactive proxy for the composer's enqueue affordance: while a turn is running // there's 1 active turn + `queueLength` waiting, so the cap is reached once the // strip holds max-1. The hook's pendingCountRef stays the hard guard. export function isQueueFull(queueLength: number, isSending: boolean, max = MAX_PENDING_TURNS): boolean { if (!isSending) return false; return queueLength >= max - 1; }