agents
Version:
A home for your AI agents
52 lines (51 loc) • 2.36 kB
JavaScript
/** Approximate token multiplier per whitespace-separated word */
const WORDS_TOKEN_MULTIPLIER = 1.3;
/** Flat token charge for an image attachment (vision-model ballpark). */
const IMAGE_ATTACHMENT_TOKENS = 1600;
/** Ceiling for a non-image attachment's bytes/4 token charge. */
const MAX_ATTACHMENT_TOKENS = 2e4;
function estimateStringTokens(text) {
if (!text) return 0;
const charEstimate = text.length / 4;
const wordEstimate = text.split(/\s+/).filter(Boolean).length * WORDS_TOKEN_MULTIPLIER;
return Math.ceil(Math.max(charEstimate, wordEstimate));
}
function estimateUnknownTokens(value) {
if (value === null || value === void 0) return 0;
if (typeof value === "string") return estimateStringTokens(value);
try {
return estimateStringTokens(JSON.stringify(value));
} catch {
return estimateStringTokens(String(value));
}
}
/** Estimate tokens for messages from their text, reasoning, and tool parts. */
function estimateMessageTokens(messages) {
let tokens = 0;
for (const msg of messages) {
tokens += 4;
for (const part of msg.parts) if (part.type === "text" || part.type === "reasoning") tokens += estimateUnknownTokens(part.text ?? part.reasoning);
else if (part.type.startsWith("tool-") || part.type === "dynamic-tool") {
tokens += estimateUnknownTokens(part.input);
tokens += estimateUnknownTokens(part.output ?? part.result);
} else if (part.text !== void 0) tokens += estimateUnknownTokens(part.text);
else if (part.result !== void 0) tokens += estimateUnknownTokens(part.result);
}
return tokens;
}
/** Heuristic token weight of one attachment so media never counts as zero. */
function estimateAttachmentTokens(mediaType, bytes) {
if (mediaType.startsWith("image/")) return IMAGE_ATTACHMENT_TOKENS;
return Math.min(Math.ceil(bytes / 4), MAX_ATTACHMENT_TOKENS);
}
/** Approximate decoded size of a `data:` URL without decoding it. */
function estimatedDataUrlBytes(url) {
const comma = url.indexOf(",");
if (!url.startsWith("data:") || comma < 0) return 0;
const header = url.slice(5, comma);
const payload = url.slice(comma + 1);
return header.endsWith(";base64") ? Math.floor(payload.length * 3 / 4) : payload.length;
}
//#endregion
export { estimatedDataUrlBytes as i, estimateMessageTokens as n, estimateStringTokens as r, estimateAttachmentTokens as t };
//# sourceMappingURL=tokens-nHAKcN6M.js.map