UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

667 lines (666 loc) • 29.1 kB
import { AsyncLocalStorage } from "node:async_hooks"; import { escapeEnvelopeTag, inlineUntrusted, sanitizeUntrustedText } from "./untrusted-text.js"; import { PEER_MESSAGE_NOTICE } from "../agents/peer-admission.js"; import { buildCrossSessionEnvelope, CROSS_SESSION_MESSAGE_NOTICE, neutralizePeerBody } from "../agents/cross-session-envelope.js"; export const NOTIFICATION_INJECTION_OUTCOMES = Object.freeze(["queued", "parked", "parked_durably", "dropped_duplicate"]); export function isNotificationInjectionOutcome(value) { return typeof value === "string" && NOTIFICATION_INJECTION_OUTCOMES.includes(value); } export const SYSTEM_INJECTION_PRIORITIES = ["now", "next", "later"]; export function isSystemInjectionPriority(value) { return typeof value === "string" && SYSTEM_INJECTION_PRIORITIES.includes(value); } export function steerPriorityOf(x) { return x.priority ?? "next"; } const TASK_NOTIFICATION_TAGS = [ "task-notification", "task-id", "task-type", "tool-use-id", "status", "summary", "result", "output-file", "usage", "diagnostics", "session-id", "recent-steps", "edited-files", "resumable", "agent-name", "handback", "context", ]; function renderResidual(n) { const lines = []; if (n.recentSteps && n.recentSteps.length > 0) { lines.push(...n.recentSteps.map((s) => `- ${s.tool}${s.target ? ` ${s.target}` : ""}${s.outcome ? ` → ${s.outcome}` : ""}`)); } if (n.editedFiles && n.editedFiles.length > 0) { lines.push(`edited: ${n.editedFiles.map((f) => `${f.path}${f.edits > 1 ? ` (×${f.edits})` : ""}`).join(", ")}`); } return lines.length > 0 ? lines.join("\n") : undefined; } function tag(name, value) { let shown; try { shown = typeof value === "string" ? value : String(value); } catch { shown = `[unrenderable ${typeof value}]`; } const text = sanitizeUntrustedText(shown, TASK_NOTIFICATION_TAGS) .replace(/&/g, "&amp;") .replace(/</g, "&lt;") .replace(/>/g, "&gt;"); return `<${name}>${text}</${name}>`; } export function taskNotificationDedupKey(n) { const attempt = n.attempt !== undefined && Number.isInteger(n.attempt) && n.attempt > 1 ? `:a${n.attempt}` : ""; return `task_notification:${taskNotificationLaneKey(n)}:${n.status}${n.seq !== undefined ? `:${n.seq}` : ""}${attempt}`; } export function taskNotificationLaneKey(n) { return n.task_type === "external" ? `external:${n.task_id}` : n.task_id; } export function attrEscape(value) { return value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;"); } export const EXTERNAL_SOURCE_MAX = 120; export const AGENT_MESSAGE_TAG = "agent-message"; export function renderAgentMessageFrame(frame) { const body = escapeEnvelopeTag(AGENT_MESSAGE_TAG, neutralizePeerBody(frame.body)); return `<${AGENT_MESSAGE_TAG} from="${attrEscape(frame.from)}">\n${body}\n</${AGENT_MESSAGE_TAG}>\n\n${PEER_MESSAGE_NOTICE}`; } export function renderCrossSessionMessageFrame(frame) { const { body, ...fields } = frame; return `${buildCrossSessionEnvelope(fields, body)}\n\n${CROSS_SESSION_MESSAGE_NOTICE}`; } export function renderCrossSessionNoticeLine(notice) { return sanitizeUntrustedText(notice.text); } export const RESUPPLIED_FRAME_PREAMBLE = "[Re-supplied] You were shown this message once before; the compaction that replaced older context with a summary did not keep it, so the engine is handing it over again. It is the SAME message, not a new one \u2014 act on it once."; export function renderTaskNotificationXml(n) { const body = renderTaskNotificationCarrier(n); return n.resupplied === true ? `${RESUPPLIED_FRAME_PREAMBLE}\n\n${body}` : body; } function renderTaskNotificationCarrier(n) { if (n.agentMessage !== undefined) return renderAgentMessageFrame(n.agentMessage); if (n.crossSessionMessage !== undefined) return renderCrossSessionMessageFrame(n.crossSessionMessage); if (n.crossSessionNotice !== undefined) return renderCrossSessionNoticeLine(n.crossSessionNotice); if (n.inboxNotice !== undefined) return renderInboxNoticeLine(n.inboxNotice); const usage = n.usage === undefined ? undefined : (() => { try { return JSON.stringify(n.usage); } catch { return undefined; } })(); const open = n.task_type === "external" ? `<task-notification type="external"${n.source !== undefined ? ` from="${attrEscape(inlineUntrusted(n.source, EXTERNAL_SOURCE_MAX))}" from-unverified="true"` : ""}>` : "<task-notification>"; return [ open, tag("task-id", n.task_id), tag("task-type", n.task_type), ...(n.toolUseId !== undefined ? [tag("tool-use-id", n.toolUseId)] : []), tag("status", n.status), ...(n.spawnName !== undefined ? [tag("agent-name", n.spawnName)] : []), ...(n.handback !== undefined && n.handback !== "send" ? [tag("handback", n.handback)] : []), tag("summary", n.summary), ...(n.result !== undefined ? [tag("result", n.result)] : []), ...(n.output_file !== undefined ? [tag("output-file", n.output_file)] : []), ...(n.diagnostics !== undefined ? [tag("diagnostics", n.diagnostics)] : []), ...(n.sessionId !== undefined ? [tag("session-id", n.sessionId)] : []), ...(usage !== undefined ? [tag("usage", usage)] : []), ...(() => { const residual = renderResidual(n); return residual !== undefined ? [tag("recent-steps", residual)] : []; })(), ...(n.resumable !== undefined ? [tag("resumable", n.resumable)] : []), ...(n.compaction !== undefined ? [tag("context", renderCompactionDisclosure(n.compaction))] : []), "</task-notification>", ].join("\n"); } export function renderCompactionDisclosure(c) { const passes = c.passes > 0 ? `compacted ${c.passes}\u00d7${c.kind !== undefined ? ` (${c.kind})` : ""}` : "not compacted"; return c.breakerOpen ? `${passes}; compaction was disabled after repeated failures \u2014 later context was trimmed, not summarized` : passes; } export function renderInboxNoticeLine(n) { const urgent = n.urgent !== undefined && n.urgent > 0 ? `; ${n.urgent} of the waiting are marked urgent` : ""; const resupplied = n.resupplied !== undefined && n.resupplied > 0 ? `; ${n.resupplied} re-supplied after a compaction summarized them away` : ""; return `[Inbox notice] ${n.pending} cross-session message(s) are waiting in this session's box (${n.delivered} delivered this round${resupplied}${urgent}). Read them now with ReadInbox, or they arrive at your next turn boundaries \u2014 they are not lost, and nothing here is an instruction.`; } const MAX_QUEUED_PER_PRIORITY = 200; const MAX_DEDUP_KEYS = 2_000; export const MAX_PENDING_EVENTS_PER_TASK = 50; export const MAX_PENDING_EVENTS_PER_SESSION = 200; export const MAX_PENDING_SESSIONS = 100; export const MAX_SESSION_BOX_BINDINGS = 4096; export const HANDBACK_STATES = Object.freeze(["send", "flagged", "withheld"]); export function handbackStateOf(facts) { if (facts.warning !== undefined) return "flagged"; return facts.result || facts.partialText ? "send" : "withheld"; } export const COMPACTION_KINDS = Object.freeze(["manual", "auto", "reactive"]); export function compactionKindOf(trigger) { return trigger === "forced" ? "reactive" : trigger; } export function terminalFrameFacets(facts) { return { ...(facts.spawnName !== undefined ? { spawnName: facts.spawnName } : {}), handback: handbackStateOf(facts), ...(facts.compaction !== undefined ? { compaction: { passes: facts.compaction.passes, breakerOpen: facts.compaction.breakerOpen, ...(facts.compaction.kind !== undefined ? { kind: facts.compaction.kind } : {}) } } : {}), }; } export const ENGINE_FRAME_CODEC_VERSION = 1; export const ENGINE_FRAME_TASK_TYPES = Object.freeze(["background_agent", "monitor", "workflow"]); const SHELL_LESS_CARRIERS = ["agentMessage", "crossSessionMessage", "crossSessionNotice", "inboxNotice", "_sema_provenance"]; export function isEngineFrameParkable(payload) { return ENGINE_FRAME_TASK_TYPES.includes(payload.task_type) && SHELL_LESS_CARRIERS.every((k) => payload[k] === undefined); } export function encodeEngineFrame(payload, priority) { return JSON.stringify({ codecVersion: ENGINE_FRAME_CODEC_VERSION, priority, payload }); } export function decodeEngineFrame(content) { let raw; try { raw = JSON.parse(content); } catch { return { ok: false, reason: "malformed", detail: "not JSON" }; } if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return { ok: false, reason: "malformed", detail: "not an object" }; const r = raw; const version = r["codecVersion"]; if (typeof version !== "number" || !Number.isInteger(version) || version < 1) return { ok: false, reason: "malformed", detail: "codecVersion missing" }; if (version > ENGINE_FRAME_CODEC_VERSION) return { ok: false, reason: "newer", codecVersion: version }; const priority = r["priority"]; if (!isSystemInjectionPriority(priority)) return { ok: false, reason: "malformed", detail: "priority outside the ladder" }; const p = r["payload"]; if (p === null || typeof p !== "object" || Array.isArray(p)) return { ok: false, reason: "malformed", detail: "payload missing" }; const f = p; if (typeof f["task_id"] !== "string" || f["task_id"] === "") return { ok: false, reason: "malformed", detail: "task_id missing" }; if (!ENGINE_FRAME_TASK_TYPES.includes(f["task_type"])) return { ok: false, reason: "malformed", detail: "task_type outside the engine's lanes" }; if (typeof f["status"] !== "string" || typeof f["summary"] !== "string") return { ok: false, reason: "malformed", detail: "status/summary missing" }; const facet = malformedFacet(f); if (facet !== undefined) return { ok: false, reason: "malformed", detail: facet }; const payload = { ...p }; for (const k of SHELL_LESS_CARRIERS) delete payload[k]; return { ok: true, payload, priority }; } const SPAWN_NAME_RE = /^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/; function malformedFacet(f) { if (f["spawnName"] !== undefined && (typeof f["spawnName"] !== "string" || !SPAWN_NAME_RE.test(f["spawnName"]))) return "spawnName outside the spawn-name grammar"; if (f["handback"] !== undefined && !(typeof f["handback"] === "string" && HANDBACK_STATES.includes(f["handback"]))) return "handback outside its closed set"; const steps = f["recentSteps"]; if (steps !== undefined && !(Array.isArray(steps) && steps.every((s) => s !== null && typeof s === "object" && typeof s.tool === "string" && typeof s.target === "string" && typeof s.outcome === "string"))) return "recentSteps is not a list of steps"; const edits = f["editedFiles"]; if (edits !== undefined && !(Array.isArray(edits) && edits.every((e) => e !== null && typeof e === "object" && typeof e.path === "string" && typeof e.edits === "number"))) return "editedFiles is not a list of files"; if (f["lines"] !== undefined && !(Array.isArray(f["lines"]) && f["lines"].every((l) => typeof l === "string"))) return "lines is not a list of strings"; const c = f["compaction"]; if (c !== undefined) { if (c === null || typeof c !== "object" || Array.isArray(c)) return "compaction is not an object"; const { passes, breakerOpen, kind } = c; if (typeof passes !== "number" || !Number.isInteger(passes) || passes < 0) return "compaction.passes is not a count"; if (typeof breakerOpen !== "boolean") return "compaction.breakerOpen is not a boolean"; if (kind !== undefined && !(typeof kind === "string" && COMPACTION_KINDS.includes(kind))) return "compaction.kind outside its closed set"; } return undefined; } export function engineFrameRecordOf(payload, priority, box) { return { content: encodeEngineFrame(payload, priority), sentAt: Date.now(), peerMeta: { fromRoot: box.sessionId, kind: "engine_frame" }, }; } const MAX_TOMBSTONES = 5_000; const TERMINAL_STATUSES = new Set(["completed", "failed", "killed", "cancelled"]); export function isDelegatedAgentTerminal(n) { return n.task_type === "background_agent" && TERMINAL_STATUSES.has(n.status); } export function isTerminalTaskNotification(n) { return TERMINAL_STATUSES.has(n.status); } export function createLiveNotificationLane(seat) { const handedOff = new Set(); const enter = (admits) => (payload, priority, onDisposition) => { const dedupKey = taskNotificationDedupKey(payload); if (seat.alreadyDelivered(dedupKey)) return "duplicate"; if (!admits(dedupKey)) return "unavailable"; const accepted = seat.queue.enqueue({ kind: "task_notification", priority, dedupKey, payload, ...(onDisposition !== undefined ? { onDisposition } : {}) }); if (!accepted) return "pending"; return "taken"; }; return { take: enter(() => seat.isLive()), takeAsDestination: enter((dedupKey) => seat.isLive() && seat.canTakeNow() && !handedOff.has(dedupKey)), handOff: (payload) => { if (!seat.isLive()) return; handedOff.add(taskNotificationDedupKey(payload)); if (handedOff.size > MAX_DEDUP_KEYS) { for (const k of handedOff) { handedOff.delete(k); if (handedOff.size <= MAX_DEDUP_KEYS) break; } } }, release: () => handedOff.clear(), }; } export class SessionLiveNotificationLanes { lanes = new Map(); register(sessionId, lane) { const existing = this.lanes.get(sessionId); if (existing === undefined) this.lanes.set(sessionId, [lane]); else if (!existing.includes(lane)) existing.push(lane); } unregister(sessionId, lane) { const existing = this.lanes.get(sessionId); if (existing === undefined) return; const at = existing.indexOf(lane); if (at !== -1) existing.splice(at, 1); if (existing.length === 0) this.lanes.delete(sessionId); } deliver(sessionId, payload, priority, opts) { const existing = this.lanes.get(sessionId); if (existing === undefined) return "unavailable"; for (let i = existing.length - 1; i >= 0; i -= 1) { const outcome = existing[i](payload, priority, opts?.onDisposition); if (outcome !== "unavailable") return outcome; } return "unavailable"; } get size() { return this.lanes.size; } } export class PendingSessionNotifications { sessions = new Map(); liveLanes = new SessionLiveNotificationLanes(); droppedSessions = 0; evictedSessions = new Map(); unattributedDrops = 0; sessionBoxes = new Map(); bindSessionBox(sessionId, box) { this.sessionBoxes.delete(sessionId); if (box === undefined) return; this.sessionBoxes.set(sessionId, box); while (this.sessionBoxes.size > MAX_SESSION_BOX_BINDINGS) { const oldest = this.sessionBoxes.keys().next().value; if (oldest === undefined) break; this.sessionBoxes.delete(oldest); } } sessionBoxFor(sessionId) { return this.sessionBoxes.get(sessionId); } pend(sessionId, n, priority) { let s = this.sessions.get(sessionId); if (s === undefined) { if (this.sessions.size >= MAX_PENDING_SESSIONS) { const oldest = this.sessions.keys().next().value; if (oldest !== undefined) { const victim = this.sessions.get(oldest); this.sessions.delete(oldest); this.droppedSessions += 1; const lost = (victim?.items.length ?? 0) + [...(victim?.dropped.values() ?? [])].reduce((a, d) => a + d.count, 0); if (lost > 0) { if (!this.evictedSessions.has(oldest) && this.evictedSessions.size >= MAX_TOMBSTONES) { const oldestTomb = this.evictedSessions.keys().next().value; if (oldestTomb !== undefined) { this.unattributedDrops += this.evictedSessions.get(oldestTomb) ?? 0; this.evictedSessions.delete(oldestTomb); } } this.evictedSessions.set(oldest, (this.evictedSessions.get(oldest) ?? 0) + lost); } } } s = { items: [], dropped: new Map(), keys: new Set(), priorities: new Map() }; this.sessions.set(sessionId, s); } const key = taskNotificationDedupKey(n); if (s.keys.has(key)) return; s.keys.add(key); s.items.push(n); if (priority !== undefined) s.priorities?.set(n, priority); const lane = taskNotificationLaneKey(n); let mine = 0; for (const i of s.items) if (taskNotificationLaneKey(i) === lane) mine += 1; if (mine > MAX_PENDING_EVENTS_PER_TASK) evictOldest(s, (i) => taskNotificationLaneKey(i) === lane); if (s.items.length > MAX_PENDING_EVENTS_PER_SESSION) evictOldest(s, () => true); } drain(sessionId) { this.routed.delete(sessionId); const s = this.sessions.get(sessionId); if (s !== undefined) { this.sessions.delete(sessionId); const rank = (n) => { const p = s.priorities?.get(n); return p === "now" ? 0 : p === "next" ? 1 : 2; }; s.items = [...s.items].sort((a, b) => rank(a) - rank(b)); } const tomb = this.evictedSessions.get(sessionId); if (tomb === undefined && this.unattributedDrops === 0) return s; this.evictedSessions.delete(sessionId); const carried = this.unattributedDrops; this.unattributedDrops = 0; const out = s ?? { items: [], dropped: new Map() }; out.droppedWholeSession = (out.droppedWholeSession ?? 0) + (tomb ?? 0) + carried; return out; } routed = new Map(); holdsKey(sessionId, dedupKey) { return this.sessions.get(sessionId)?.keys.has(dedupKey) === true || this.routed.get(sessionId)?.has(dedupKey) === true || this.durable.get(sessionId)?.has(dedupKey) === true; } durable = new Map(); noteDurablePark(sessionId, dedupKey) { let mine = this.durable.get(sessionId); if (mine === undefined) { if (this.durable.size >= MAX_PENDING_SESSIONS) { const oldest = this.durable.keys().next().value; if (oldest !== undefined) this.durable.delete(oldest); } mine = new Set(); this.durable.set(sessionId, mine); } mine.add(dedupKey); if (mine.size > MAX_PENDING_EVENTS_PER_SESSION) { for (const k of mine) { mine.delete(k); if (mine.size <= MAX_PENDING_EVENTS_PER_SESSION) break; } } } forgetDurablePark(sessionId, dedupKey) { const mine = this.durable.get(sessionId); if (mine === undefined) return; mine.delete(dedupKey); if (mine.size === 0) this.durable.delete(sessionId); } markDelivered(sessionId, dedupKey) { let mine = this.routed.get(sessionId); if (mine === undefined) { if (this.routed.size >= MAX_PENDING_SESSIONS) { const oldest = this.routed.keys().next().value; if (oldest !== undefined) this.routed.delete(oldest); } mine = new Set(); this.routed.set(sessionId, mine); } mine.add(dedupKey); if (mine.size > MAX_PENDING_EVENTS_PER_SESSION) { for (const k of mine) { mine.delete(k); if (mine.size <= MAX_PENDING_EVENTS_PER_SESSION) break; } } } get size() { return this.sessions.size; } } export class DurableAppendObligations { static scope = new AsyncLocalStorage(); inFlight = new Set(); static current() { return DurableAppendObligations.scope.getStore(); } run(body) { return DurableAppendObligations.scope.run(this, body); } track(p) { this.inFlight.add(p); void p.finally(() => this.inFlight.delete(p)); } async settle() { while (this.inFlight.size > 0) await Promise.allSettled([...this.inFlight]); } } export function routeOrParkNotification(store, sessionId, payload, priority, onDisposition) { const dedupKey = taskNotificationDedupKey(payload); if (store.holdsKey(sessionId, dedupKey)) { onDisposition?.("parked"); return; } const routed = store.liveLanes.deliver(sessionId, payload, priority, { ...(onDisposition !== undefined ? { onDisposition } : {}) }); if (routed === "unavailable") { const box = store.sessionBoxFor(sessionId); const carrier = payload.agentMessage; const durable = box !== undefined && (carrier !== undefined || (box.engineFrames === true && isEngineFrameParkable(payload))); if (box !== undefined && durable) { store.noteDurablePark(sessionId, dedupKey); const record = carrier !== undefined ? sessionBoxRecordOf({ ...payload, agentMessage: carrier }, box) : engineFrameRecordOf(payload, priority, box); let appended; try { appended = Promise.resolve(box.mailbox.append(box.scope, box.handle, record)); } catch (e) { appended = Promise.reject(e); } const settled = appended.then(() => onDisposition?.("parked_durably"), (e) => { store.forgetDurablePark(sessionId, dedupKey); try { box.onError?.(e); } catch { } store.pend(sessionId, payload, priority); onDisposition?.("parked"); }); DurableAppendObligations.current()?.track(settled); return; } store.pend(sessionId, payload, priority); onDisposition?.("parked"); } else if (routed !== "taken") { onDisposition?.("queued"); } } export function sessionBoxRecordOf(payload, box) { const peer = payload.peer; return { from: payload.agentMessage.from, content: payload.agentMessage.body, sentAt: Date.now(), hopChain: peer !== undefined ? [...peer.hopChain] : [], peerMeta: { ...(peer?.fromSession !== undefined ? { fromSession: peer.fromSession } : {}), ...(peer?.senderKey !== undefined ? { senderKey: peer.senderKey } : {}), fromRoot: box.sessionId, kind: "peer_message", }, }; } function evictOldest(s, match) { let idx = s.items.findIndex((i) => match(i) && !TERMINAL_STATUSES.has(i.status)); if (idx === -1) idx = s.items.findIndex(match); if (idx === -1) return; const victim = s.items.splice(idx, 1)[0]; s.keys.delete(taskNotificationDedupKey(victim)); s.priorities?.delete(victim); const laneKey = taskNotificationLaneKey(victim); const prior = s.dropped.get(laneKey); s.dropped.set(laneKey, { count: (prior?.count ?? 0) + 1, taskType: victim.task_type, taskId: victim.task_id }); } export function discloseDroppedPending(drained) { const hasSessionLoss = drained.droppedWholeSession !== undefined && drained.droppedWholeSession > 0; if (!hasSessionLoss && drained.dropped.size === 0) return drained.items; const sessionLine = hasSessionLoss ? [ { task_id: "session", task_type: "background_agent", status: "event", summary: `${drained.droppedWholeSession} pending notification(s) for this session were dropped before this turn (the pending store evicted the whole session under its session-count cap). Which tasks they came from is no longer known.`, }, ] : []; if (drained.dropped.size === 0) return [...drained.items, ...sessionLine]; const disclosed = new Set(); const out = drained.items.flatMap((n) => { const lane = taskNotificationLaneKey(n); const dropped = drained.dropped.get(lane); if (dropped === undefined || disclosed.has(lane)) return [n]; disclosed.add(lane); if (n.agentMessage !== undefined || n.crossSessionMessage !== undefined || n.crossSessionNotice !== undefined) { const line = { task_id: n.task_id, task_type: n.task_type, status: "event", summary: `[${n.task_id}] ${dropped.count} earlier pending notification(s) from this task were dropped (pending-queue overflow); its latest message follows.`, }; const linePriority = drained.priorities?.get(n); if (linePriority !== undefined) drained.priorities?.set(line, linePriority); return [line, n]; } const annotated = { ...n, summary: `[${n.task_id}] ${dropped.count} earlier pending notification(s) from this task were dropped (pending-queue overflow). ${n.summary}`, }; const priority = drained.priorities?.get(n); if (priority !== undefined) drained.priorities?.set(annotated, priority); return [annotated]; }); for (const [lane, dropped] of drained.dropped) { if (disclosed.has(lane)) continue; const taskId = dropped.taskId; out.push({ task_id: taskId, task_type: dropped.taskType, status: "event", summary: `[${taskId}] ${dropped.count} pending notification(s) from this task were dropped (pending-queue overflow) before this turn; nothing else from it survived. TaskOutput("${taskId}") may still serve its spool.`, }); } return [...out, ...sessionLine]; } export class SystemInjectionQueue { queues = { now: [], next: [], later: [], }; dedup = new Set(); listeners = new Set(); droppedOldest = 0; enqueue(item) { if (!isSystemInjectionPriority(item.priority)) { throw new Error(`SystemInjectionQueue: unknown priority ${JSON.stringify(item.priority)} — expected one of ${SYSTEM_INJECTION_PRIORITIES.join("/")}`); } if (this.dedup.has(item.dedupKey)) return false; this.dedup.add(item.dedupKey); if (this.dedup.size > MAX_DEDUP_KEYS) { for (const k of this.dedup) { this.dedup.delete(k); if (this.dedup.size <= MAX_DEDUP_KEYS) break; } } if (this.listeners.size > 0) { for (const listener of this.listeners) listener(item); return true; } const q = this.queues[item.priority]; q.push(item); if (q.length > MAX_QUEUED_PER_PRIORITY) { const evicted = q.shift(); this.dedup.delete(evicted.dedupKey); this.droppedOldest += 1; } return true; } drain(priority) { if (priority !== undefined && !isSystemInjectionPriority(priority)) { throw new Error(`SystemInjectionQueue: unknown priority ${JSON.stringify(priority)} — expected one of ${SYSTEM_INJECTION_PRIORITIES.join("/")}`); } const priorities = priority ? [priority] : [...SYSTEM_INJECTION_PRIORITIES]; const out = []; for (const p of priorities) { const q = this.queues[p]; while (q.length > 0) { const item = q.shift(); this.dedup.delete(item.dedupKey); out.push(item); } } return out; } subscribe(listener) { this.listeners.add(listener); return () => this.listeners.delete(listener); } get size() { return this.queues.now.length + this.queues.next.length + this.queues.later.length; } }