UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

76 lines (75 loc) • 3.42 kB
import { sanitizeUntrustedText, SHELLED_BODY_ENVELOPE_TAGS } from "../untrusted-text.js"; export function foldListingWithin(items, spec) { if (items.length === 0) return undefined; const bytes = (s) => Buffer.byteLength(s, "utf8"); const render = spec.frame; const lineCost = (l) => bytes(l) + 1; const bodyBudget = spec.blockMaxBytes - bytes(render([])); const fullLines = items.map((it) => spec.full(it)); const fullTotal = fullLines.reduce((acc, l) => acc + lineCost(l), 0); if (fullTotal <= bodyBudget) return { text: render(fullLines), nameOnly: [], dropped: [] }; const nameLines = items.map((it) => spec.nameOnly(it)); const namePrefix = new Array(nameLines.length + 1); namePrefix[0] = 0; for (let i = 0; i < nameLines.length; i++) namePrefix[i + 1] = namePrefix[i] + lineCost(nameLines[i]); const markerCost = lineCost(spec.capMarker); const floorCost = markerCost + namePrefix[nameLines.length]; if (floorCost <= bodyBudget) { let slack = bodyBudget - floorCost; const byPriority = items .map((it, i) => ({ i, rank: spec.rank?.(it, i) ?? i })) .toSorted((a, b) => a.rank - b.rank || a.i - b.i); const withFull = new Set(); for (const { i } of byPriority) { const delta = lineCost(fullLines[i]) - lineCost(nameLines[i]); if (delta <= slack) { withFull.add(i); slack -= delta; } } return { text: render([spec.capMarker, ...items.map((_it, i) => (withFull.has(i) ? fullLines[i] : nameLines[i]))]), nameOnly: items.filter((_it, i) => !withFull.has(i)).map((it) => spec.nameOf(it)), dropped: [], }; } for (let m = items.length - 1; m >= 0; m--) { const overflow = spec.overflowLine(items.length - m); if (markerCost + namePrefix[m] + lineCost(overflow) <= bodyBudget) { return { text: render([spec.capMarker, ...nameLines.slice(0, m), overflow]), nameOnly: items.slice(0, m).map((it) => spec.nameOf(it)), dropped: items.slice(m).map((it) => spec.nameOf(it)), }; } } return { text: render([spec.capMarker, spec.overflowLine(items.length)]), nameOnly: [], dropped: items.map((it) => spec.nameOf(it)), }; } export function removalArmFloor(header, count) { return [header, `(… +${count} more are no longer available)`].join("\n"); } export function foldRemovalArmWithin(removed, header, maxBytes) { const bytes = (s) => Buffer.byteLength(s, "utf8"); const lines = removed.map((n) => `- ${sanitizeUntrustedText(n, SHELLED_BODY_ENVELOPE_TAGS)}`); const head = bytes(header); const lineCost = (l) => bytes(l) + 1; const prefix = new Array(lines.length + 1); prefix[0] = 0; for (let i = 0; i < lines.length; i++) prefix[i + 1] = prefix[i] + lineCost(lines[i]); if (head + prefix[lines.length] <= maxBytes) return [header, ...lines].join("\n"); for (let m = lines.length - 1; m >= 0; m--) { const tail = `(… +${lines.length - m} more are no longer available)`; if (head + prefix[m] + lineCost(tail) <= maxBytes) return [header, ...lines.slice(0, m), tail].join("\n"); } return removalArmFloor(header, lines.length); }