The ledger is a Markdown table; spent() reads the running total from its last cell. guard() refuses a call that would pass the cap, and log() appends a row from the response's usage:
export function guard(cost) { // call before every request
const total = spent();
if (total + cost > CAP) {
throw new Error(`Refused: $${total.toFixed(4)} spent + $${cost.toFixed(4)} > $${CAP}`);
}
return total;
}
export function log({ model, size, quality, n = 1, what }, usage, extra = 0) {
const d = usage.input_tokens_details ?? {};
const t = { textIn: d.text_tokens ?? 0, imageIn: d.image_tokens ?? 0,
out: usage.output_tokens };
const cost = dollars(t) + extra, total = spent() + cost, time = new Date().toISOString();
const cells = [rows().length + 1, time.slice(0, 16), model, size, quality, n, what,
t.textIn, t.imageIn, t.out, `$${cost.toFixed(4)}`, `$${total.toFixed(4)}`];
fs.appendFileSync(LEDGER, `| ${cells.join(' | ')} |\n`);
return { cost, total };
}Every call in this chapter ran through these functions, with IMAGE_CAP=2 as a stricter stop than the author's $5; failed requests are not billed and not logged. After Masks and References the ledger held 16 rows and $0.1622, and the guard refused ten 4K images at max: Refused: $0.1622 spent + $4.0026 > $2.
<!doctype html>
<style>
body { margin: 0; padding: 8px; background: #fafaf7; font: 11px system-ui, sans-serif; color: #263238; }
svg { width: 100%; max-width: 600px; display: block; }
#msg { font-weight: bold; min-height: 1.4em; }
</style>
<script src="https://cdn.jsdelivr.net/npm/d3@7.9.0/dist/d3.min.js"></script>
<p>cap <select id="cap"><option value="2">$2 (IMAGE_CAP=2)</option><option value="5">$5</option></select>
<button id="small">Log a low-quality call ($0.006)</button> <button id="big">Try ten 4K images at max ($4.0026)</button></p>
<p id="msg"></p>
<svg viewBox="0 0 600 230" font-size="11"></svg>
<script>
// The chapter's 16 ledger rows (cost per call); the total reaches $0.1622
const ledger = [0.0060, 0.0070, 0.0076, 0.0142, 0.0143, 0.0225, 0.0078, 0.0179, 0.0019, 0.0050, 0.0172, 0.0064, 0.0142, 0.0143, 0.0038, 0.0021]
.map((cost, i) => ({ row: i + 1, cost }));
const spent = () => d3.sum(ledger, r => r.cost);
const svg = d3.select('svg');
const gx = svg.append('g').attr('transform', 'translate(0,200)'), gy = svg.append('g').attr('transform', 'translate(40,0)');
const path = svg.append('path').attr('fill', 'none').attr('stroke', '#1f5f8b').attr('stroke-width', 2);
const capLine = svg.append('line').attr('stroke', '#b5452f').attr('stroke-dasharray', '5 3');
const capText = svg.append('text').attr('fill', '#b5452f');
// guard(): refuse a call that would take the running total past the cap
function guard(cost) {
const total = spent(), cap = +document.getElementById('cap').value;
if (total + cost > cap) throw new Error(`Refused: $${total.toFixed(4)} spent + $${cost.toFixed(4)} > $${cap}`);
return total;
}
function draw() {
const cap = +document.getElementById('cap').value;
let run = 0;
const points = [{ row: 0, total: 0 }, ...ledger.map(r => ({ row: r.row, total: run += r.cost }))];
const x = d3.scaleLinear([0, Math.max(20, ledger.length)], [40, 590]);
const y = d3.scaleLinear([0, Math.max(cap * 1.05, run)], [200, 10]);
gx.call(d3.axisBottom(x).ticks(10)).append('text');
gy.call(d3.axisLeft(y).ticks(5, '$.2f'));
path.datum(points).attr('d', d3.line(d => x(d.row), d => y(d.total)).curve(d3.curveStepAfter));
svg.selectAll('circle').data(points.slice(1)).join('circle').attr('r', 3).attr('fill', '#1f5f8b')
.attr('cx', d => x(d.row)).attr('cy', d => y(d.total));
capLine.attr('x1', 40).attr('x2', 590).attr('y1', y(cap)).attr('y2', y(cap));
capText.attr('x', 44).attr('y', y(cap) - 5).text(`cap $${cap}`);
svg.selectAll('text.tot').data([run]).join('text').attr('class', 'tot').attr('x', x(ledger.length) + 6).attr('y', y(run) - 6)
.text(t => `$${t.toFixed(4)} after ${ledger.length} rows`);
}
function attempt(cost, what) {
try {
guard(cost);
ledger.push({ row: ledger.length + 1, cost });
document.getElementById('msg').style.color = '#3f7d3a';
document.getElementById('msg').textContent = `logged row ${ledger.length}: ${what}, $${cost.toFixed(4)}`;
} catch (err) {
document.getElementById('msg').style.color = '#b5452f';
document.getElementById('msg').textContent = err.message;
}
draw();
}
document.getElementById('small').onclick = () => attempt(0.006, '1024x1024 low');
document.getElementById('big').onclick = () => attempt(4.0026, 'ten 3840x2160 at max');
document.getElementById('cap').onchange = draw;
draw();
attempt(4.0026, 'ten 3840x2160 at max'); // the refusal from the chapter
</script>