Fix permission-prompt screen jumping + OpenAI token over-counting#104
Open
QodeXcli wants to merge 9 commits into
Open
Fix permission-prompt screen jumping + OpenAI token over-counting#104QodeXcli wants to merge 9 commits into
QodeXcli wants to merge 9 commits into
Conversation
The 250ms nowTick interval kept firing during accept/decline/always prompts, re-painting the whole dynamic Ink frame 4x/second — with a tall diff+prompt on screen this read as violent scroll-jumping until the user answered. The ticker now goes quiet via a ref (timer and task start time stay intact, the readout just freezes), and tool-activity lines hide under the prompt.
…ults sooner OpenAI's prompt_tokens INCLUDES automatically-cached prefix tokens; usage now splits prompt_tokens_details.cached_tokens into cacheRead (matching Anthropic semantics), so the budget no longer re-bills the whole context at 1x every turn for OpenAI-provider models. Result aging also tightens (3 turns/8KB -> 2 turns/5KB) so large unique tool outputs stop riding the context full-size.
…text re-reads An agentic turn makes one API call per tool round and each call re-sends the whole conversation, so charging every call's full input made budget spend grow quadratically with tool rounds — a 21k-context task on a local model (no cache fields at all) burned 216k/200k within two minutes and died. A prompt high-water mark now counts each context token ONCE: consume = output + max(0, seen - mark). Dollar cost stays full-usage per call — bills are bills; the token budget is a runaway guard, not an invoice.
…ust apply blindly qodex already had 'qodex update' and a dashboard button that ran git pull → npm install → build. Both fired blind — no way to know an update EXISTED. Adds checkForUpdate(): a no-merge 'git fetch' + behind-count against the upstream. - terminal: 'qodex update --check' reports availability without applying - dashboard: Health panel now shows 'QodeX vX.Y.Z', an 'update available — N behind' badge (instant local-only check on render), a 'Check for updates' button (networked, app.checkUpdate), and the existing update button Tests build a real local remote→clone pair (no network) to prove the behind count and the fetchRemote:false fast path.
…sks mid-work checkpoint() runs right after a completed model call, so the old absolute ceiling could ONLY ever kill a task that was actively working (live: 'Time budget exceeded: 608s/600s' during an active edit loop on a local model) — a hung task never reaches a checkpoint at all. The ceiling now fires only when the task is ALSO stalled (no completed call in the last 2 minutes); true runaways stay bounded by the iteration and token caps. Default ceiling raised 600s -> 3600s: it was calibrated for cloud latency, and a local model legitimately spends 10 minutes on a handful of long generations.
…he status bar The bar said 'local' whenever cost was zero (a guess) and rendered the STATIC context window from the model table even though loop.ts already live-syncs the real window from LM Studio's native API — the detection existed, unwired. Now budget_update carries providerName/providerIsLocal and the live-synced window: - source badge next to the model: 'ollama·local', 'lmstudio·local', 'anthropic·api' … (LM Studio detected via its /api/v0/models registry, which its OpenAI-compat facade hides) - cloud at zero accrued cost shows 'api · $0.0000', never 'local · free' — billing surfaces the moment real cost accrues - context meter uses the live window, falling back to the static table
…rst write — fabricated sub-session ids (parent/sub-<ts>) had no parent row in sessions, so the messages FK failed instantly and every delegation died with SUBAGENT_FAILED
…re ceiling A 5-minute shell command is work, not a stall — but only consume() (a model call) bumped lastProgressAt, so the wall ceiling read long tool runs as 'stalled' and killed the task right after the tool returned (live: 'Time budget exceeded: 808s/600s (stalled 300s)' immediately after a 300s shell). noteProgress() now fires when tool executions complete, at all three dispatch sites (parallel read-only, sequential mutating, batched).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
1. UI: violent screen jumping while a permission prompt is open (
src/cli/ui.tsx)busystays true), re-painting the whole dynamic Ink frame 4×/second. With a tall diff + confirmation on screen, that re-paint reads as heavy scroll-jumping until the user answers.2. Tokens: OpenAI-provider models appeared to burn a 200k budget in minutes (
src/llm/providers/openai.ts,src/agent/result-aging.ts)prompt_tokensINCLUDES automatically-cached prefix tokens. Usage now splitsprompt_tokens_details.cached_tokensout ascacheRead, matching the Anthropic provider's semantics — so the budget counts only fresh input instead of re-billing the entire context at 1× every turn.Why
Two live reports from daily use: the chat view bounces hard whenever a tool-permission prompt appears, and some models exhaust their 200k token budget within minutes while comparable environments stay economical.
Reviewer notes
inputexcludescacheRead) — untouched.sessionToolNamesper task: its monotonic growth is a documented design choice (src/agent/loop.ts~917) that keeps the serialized schema prefix byte-stable for prompt caching.npx tsc --noEmitclean;test/result-aging.test.tsandtest/openai-user-agent.test.tsgreen (12/12).