import type { TaskEnvelope } from "../types.js"; export function estimateTokens(value: unknown): number { return Math.ceil(JSON.stringify(value).length / 4); } export function fitEnvelope(envelope: TaskEnvelope, hardCapTokens = 8000): TaskEnvelope { const fitted: TaskEnvelope = structuredClone(envelope); while (estimateTokens(fitted) > hardCapTokens && fitted.knownFacts.length > 0) fitted.knownFacts.pop(); while (estimateTokens(fitted) > hardCapTokens && fitted.openQuestions.length > 1) fitted.openQuestions.pop(); while (estimateTokens(fitted) > hardCapTokens && fitted.constraints.length > 1) fitted.constraints.pop(); if (estimateTokens(fitted) > hardCapTokens) throw new Error("Task Envelope exceeds hard cap; narrow scope before spawn"); if ((fitted.declaredArtifacts?.length ?? 0) !== (envelope.declaredArtifacts?.length ?? 0)) throw new Error("Task Envelope must not drop declared artifacts"); return fitted; } export function envelopePrompt(envelope: TaskEnvelope): string { const fitted = fitEnvelope(envelope); return [ "Work only within the declared scope. Do not delegate. Return exactly one JSON AgentResult and no prose.", `Fact IDs must use F:${fitted.trace.runId}:${fitted.trace.nodeId}:.`, JSON.stringify(fitted), ].join("\n\n"); }