Adds up what calls to a person's own AI model have cost today and this month, and stops a call that could pass the limits the person set.
How the precision is kept
A call's cost is its input and output token counts times the model's prices per million tokens, in 64-bit numbers. Costs are kept per call and added for the day and the month. Before a call the worst case is estimated from the size of the request text, which is an estimate and not a token count, plus the largest answer allowed. The limits are compared with the unrounded sums; only the message text rounds to 2 decimals.
Calculations under this policy
4 calculations in 1 source file. The code is read from the released app when this page loads. It is the calculation people run, not a copy kept for this page.
ai-byok.jsShared shell, every app64-bit4 calculationsReviewed
Tests bin/test-ask-byok.mjs
Cost of one call
64-bit
The cost of a call from its token counts and the model's prices.
cost = (in × price in + out × price out) ÷ 1,000,000
One 64-bit expression: two products added, then one division. With no price for the model the cost is 0.
ai-byok.js
line 139
const costOf = (price, i, o) => (price ? (i * price.in + o * price.out) / 1e6 : 0);
Spending today and this month
64-bit
The cost, tokens and number of calls for the current day and month, and the calls in the last hour.
amount = Σ cost of the calls in the period
Costs are 64-bit numbers added in the order the calls were recorded, with no rounding of the stored amounts. A call belongs to a day or month by the first characters of its UTC timestamp.
ai-byok.js
lines 141 to 148
/** What is used so far, and what one more call could cost at most. */
function usage() {
const s = S(), L = readLedger(), t = now();
const day = L.filter((e) => dayKey(e.t) === dayKey(t)), month = L.filter((e) => monthKey(e.t) === monthKey(t));
const sum = (a, k) => a.reduce((x, e) => x + (e[k] || 0), 0);
return { currency: s.currency, day: { amount: sum(day, 'cost'), tokens: sum(day, 'in') + sum(day, 'out'), calls: day.length }, month: { amount: sum(month, 'cost'), tokens: sum(month, 'in') + sum(month, 'out'), calls: month.length },
lastHour: L.filter((e) => t - e.t < 3600000).length, priced: !!priceOf(s) || isLocal(s), caps: s.caps };
}
Check before a call
64-bit
Refuses a call when the calls per hour, the day's or month's spending, or the day's tokens could pass a limit.
refuse when spent + worst-case cost > limit; worst case = cost(estimated input, largest allowed output)
The comparison uses the unrounded sum plus the worst-case cost of this call. The amount in the message is formatted with toFixed(2) for reading only. Without a price the check falls back to a daily token limit.
ai-byok.js
lines 150 to 164
/** The gate in front of every provider call. `estIn` = tokens in the request (estimated); the call may add up to maxOutputTokens. */
function check(estIn) {
const s = S(), u = usage(), c = s.caps;
if (u.lastHour >= c.callsPerHour) return { ok: false, code: 'calls_hour', message: `That is ${c.callsPerHour} calls in the last hour, the limit you set. It resets as the hour passes.`, raise: 'caps.callsPerHour', usage: u };
if (isLocal(s)) return { ok: true };
const price = priceOf(s), worstTok = estIn + s.maxOutputTokens;
if (price) {
const worst = costOf(price, estIn, s.maxOutputTokens);
if (u.day.amount + worst > c.dayAmount) return { ok: false, code: 'cap_day', message: `Today's spending (${u.day.amount.toFixed(2)} ${s.currency}) plus this call could pass the daily limit of ${c.dayAmount} ${s.currency} you set.`, raise: 'caps.dayAmount', usage: u };
if (u.month.amount + worst > c.monthAmount) return { ok: false, code: 'cap_month', message: `This month's spending (${u.month.amount.toFixed(2)} ${s.currency}) plus this call could pass the monthly limit of ${c.monthAmount} ${s.currency} you set.`, raise: 'caps.monthAmount', usage: u };
} else if (u.day.tokens + worstTok > c.dayTokens) {
return { ok: false, code: 'cap_tokens', message: `No price is set for ${s.model || 'this model'}, so a daily limit of ${c.dayTokens} tokens applies (${u.day.tokens} used). Enter the model's price in the settings to limit by money instead.`, raise: 'prices', usage: u };
}
return { ok: true };
}
Recorded cost and the token estimate
64-bit
Stores each call's cost and estimates the input tokens of the next request.
estimated tokens = ⌈JSON length ÷ 3⌉ + 500
The recorded cost uses the token counts the provider reported; a model on the person's own computer is recorded at 0. The estimate before a call divides the request's character count by 3 and adds 500: a rule of thumb, not a count.
cost = (input tokens × input price + output tokens × output price) ÷ 1,000,000. Estimated input tokens = ⌈characters of the request as JSON ÷ 3⌉ + 500.
Number types
64-bit numbers; token counts are integers.
Limits
The token estimate before a call is a rule of thumb. Day and month are taken from the UTC date. Calls older than 62 days are dropped from the record. The amounts depend on the prices entered for the model.
Approach: 64-bit, stated limit
The arithmetic is 64-bit, but the method or the data sets the accuracy: a solver tolerance, a mesh, a step size, a datum shift, a table. The limit is stated where the result is shown.