Support backend-specific minimum target tokens

This commit is contained in:
FBukovina 2026-05-20 12:03:27 +02:00
commit 480dbd5c1a
2 changed files with 43 additions and 12 deletions

View file

@ -26,9 +26,10 @@ Drops `burn` into `~/.local/bin` — no sudo, no Homebrew tap. Needs
## Usage ## Usage
```bash ```bash
burn 10000 # the minimum burn 10000 # the Claude minimum
burn 50000 --model haiku # cheap and fast burn 50000 --model haiku # cheap and fast
burn 100000 --model sonnet # walk away burn 100000 --model sonnet # walk away
burn 13000 --backend codex # the Codex minimum
burn 50000 --backend codex # 🤖 burn OpenAI tokens burn 50000 --backend codex # 🤖 burn OpenAI tokens
``` ```
@ -36,7 +37,7 @@ Run `burn` with no arguments to open the TUI. When you select OpenAI
Codex and press `IGNITE`, the TUI launches the default browser OAuth Codex and press `IGNITE`, the TUI launches the default browser OAuth
flow if Codex is not already connected. You can also use the `AUTH` row flow if Codex is not already connected. You can also use the `AUTH` row
to recheck or sign in manually, or run `codex login` before opening to recheck or sign in manually, or run `codex login` before opening
`burn`. `burn`. The TUI adjusts the minimum target automatically per backend.
![burn in action](screenshot.png) ![burn in action](screenshot.png)

View file

@ -46,7 +46,11 @@ const BACKEND_MODELS = {
] ]
}; };
const PRESETS = [10000, 50000, 100000, 500000, 'custom']; const MIN_TARGET_TOKENS = {
claude: 10000,
codex: 13000
};
const PRESETS = ['min', 50000, 100000, 500000, 'custom'];
const ACHIEVEMENTS = [ const ACHIEVEMENTS = [
"Master of Corporate Theater", "Master of Corporate Theater",
@ -290,6 +294,27 @@ function costDisplay() {
return costString === 'cost n/a' ? costString : `${costString} USD`; return costString === 'cost n/a' ? costString : `${costString} USD`;
} }
function minTargetTokens() {
return MIN_TARGET_TOKENS[backend] || MIN_TARGET_TOKENS.claude;
}
function presetTokenValue(preset) {
return preset === 'min' ? minTargetTokens() : preset;
}
function selectedTargetTokens() {
if (selectedPresetIdx === PRESETS.length - 1) {
return Math.max(customTokens, minTargetTokens());
}
return presetTokenValue(PRESETS[selectedPresetIdx]);
}
function formatPresetLabel(preset) {
if (preset === 'custom') return '[Custom]';
const value = presetTokenValue(preset);
return value % 1000 === 0 ? `[${value / 1000}k]` : `[${value.toLocaleString()}]`;
}
function codexAuthDisplay() { function codexAuthDisplay() {
switch (codexAuthState) { switch (codexAuthState) {
case 'checking': case 'checking':
@ -801,9 +826,10 @@ function handleConfigKey(str, key) {
activeModelIdx = (activeModelIdx + 1) % modelsCount; activeModelIdx = (activeModelIdx + 1) % modelsCount;
} }
} else if (focusedItem === 'tokens') { } else if (focusedItem === 'tokens') {
const minTokens = minTargetTokens();
if (isLeft) { if (isLeft) {
if (selectedPresetIdx === 4 && customTokens > 10000) { if (selectedPresetIdx === 4 && customTokens > minTokens) {
customTokens -= 25000; customTokens = Math.max(minTokens, customTokens - 25000);
} else if (selectedPresetIdx > 0) { } else if (selectedPresetIdx > 0) {
selectedPresetIdx--; selectedPresetIdx--;
} }
@ -821,6 +847,9 @@ function handleConfigKey(str, key) {
} }
} else if (isSpace) { } else if (isSpace) {
selectedPresetIdx = (selectedPresetIdx + 1) % PRESETS.length; selectedPresetIdx = (selectedPresetIdx + 1) % PRESETS.length;
if (selectedPresetIdx === 4 && customTokens < minTokens) {
customTokens = minTokens;
}
if (PRESETS[selectedPresetIdx] === 'custom' && customTokens >= 1000000) { if (PRESETS[selectedPresetIdx] === 'custom' && customTokens >= 1000000) {
isWarningNihilist = true; isWarningNihilist = true;
} }
@ -917,7 +946,7 @@ function startCombustion() {
burnWasAborted = false; burnWasAborted = false;
burnFailureSticky = false; burnFailureSticky = false;
burnFailureMessage = ''; burnFailureMessage = '';
targetTokens = selectedPresetIdx === 4 ? customTokens : PRESETS[selectedPresetIdx]; targetTokens = selectedTargetTokens();
burnedTokens = 0; burnedTokens = 0;
burnPercentage = 0; burnPercentage = 0;
costString = 'cost n/a'; costString = 'cost n/a';
@ -1135,7 +1164,7 @@ function compileConfigScreen() {
s += `${tSel}${BOLD}💸 TARGET:${RESET} `; s += `${tSel}${BOLD}💸 TARGET:${RESET} `;
PRESETS.forEach((p, idx) => { PRESETS.forEach((p, idx) => {
const isSelected = selectedPresetIdx === idx; const isSelected = selectedPresetIdx === idx;
let label = p === 'custom' ? '[Custom]' : `[${(p/1000)}k]`; let label = formatPresetLabel(p);
const color = isSelected ? GREEN : (focusedItem === 'tokens' ? RESET : DIM); const color = isSelected ? GREEN : (focusedItem === 'tokens' ? RESET : DIM);
const wrap = isSelected ? `${BOLD}${color}` : `${DIM}`; const wrap = isSelected ? `${BOLD}${color}` : `${DIM}`;
s += `${wrap}${label}${RESET} `; s += `${wrap}${label}${RESET} `;
@ -1145,19 +1174,20 @@ function compileConfigScreen() {
// Description / Custom Slider // Description / Custom Slider
if (selectedPresetIdx === 4) { if (selectedPresetIdx === 4) {
const maxVal = 1000000; const maxVal = 1000000;
const minVal = 10000; const minVal = minTargetTokens();
const pct = (customTokens - minVal) / (maxVal - minVal); const visibleCustomTokens = Math.max(customTokens, minVal);
const pct = (visibleCustomTokens - minVal) / (maxVal - minVal);
const sliderWidth = 15; const sliderWidth = 15;
const filled = Math.round(pct * sliderWidth); const filled = Math.round(pct * sliderWidth);
const empty = sliderWidth - filled; const empty = sliderWidth - filled;
const sliderBar = `${RED}█${RESET}`.repeat(filled) + `${DIM}░${RESET}`.repeat(empty); const sliderBar = `${RED}█${RESET}`.repeat(filled) + `${DIM}░${RESET}`.repeat(empty);
let desc = ''; let desc = '';
if (customTokens <= 100000) desc = "Satisfactory OKR padding."; if (visibleCustomTokens <= 100000) desc = "Satisfactory OKR padding.";
else if (customTokens <= 500000) desc = "Significant metrics!"; else if (visibleCustomTokens <= 500000) desc = "Significant metrics!";
else desc = "EXTREME nihilism! CEO promotion or fire. 🌋"; else desc = "EXTREME nihilism! CEO promotion or fire. 🌋";
s += ` ${BOLD}${ORANGE}Slider:${RESET} <─${sliderBar}─> ${BOLD}${GREEN}${customTokens.toLocaleString()}${RESET} tokens (${DIM}${desc}${RESET})\n`; s += ` ${BOLD}${ORANGE}Slider:${RESET} <─${sliderBar}─> ${BOLD}${GREEN}${visibleCustomTokens.toLocaleString()}${RESET} tokens (${DIM}${desc}${RESET})\n`;
} else { } else {
const modelsList = BACKEND_MODELS[backend]; const modelsList = BACKEND_MODELS[backend];
s += ` ${DIM}Desc: ${modelsList[activeModelIdx].desc}${RESET}\n`; s += ` ${DIM}Desc: ${modelsList[activeModelIdx].desc}${RESET}\n`;