import { defaultCountTokens, type CoreMessage } from "acp-kernel"; export function collectCoveredMessageIds(state: { blocks: { active: boolean; effectiveMessageIds: string[] }[] }): Set { const ids = new Set(); for (const b of state.blocks) { if (!b.active) continue; for (const id of b.effectiveMessageIds) ids.add(id); } return ids; } export function estimateTokens(messages: CoreMessage[], coveredIds?: Set): number { let tokens = 0; for (const m of messages) { if (m.toolName === "compress") continue; if (coveredIds?.has(m.id)) continue; tokens += defaultCountTokens(m.text ?? ""); } return tokens; } /** Id of the last user-role entry — used as a per-turn key so a nudge prints at * most once per turn. Returns undefined if there is no user message yet. */ export function lastUserMessageId(entries: { id: string; message?: { role?: string } }[]): string | undefined { for (let i = entries.length - 1; i >= 0; i--) { const e = entries[i]!; if (e.message?.role === "user") return e.id; } return undefined; }