galaxyproject / galaxyproject/loom

Context-fill indicator flickers (intermittently hidden) during streaming and after model switch

Open
#172 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
14
Forks
12
Avg merge
6d 5h
Merged PRs (30d)
17

Description

## Symptom

The footer context-fill indicator (#164, shipped in 0.3.1) is intermittent — it appears and disappears during normal use rather than staying continuously visible. The separate model-name chip is unaffected (correctly shows the active model, e.g. DeepSeek).

Observed on `deepseek-v4-pro` (after switching from `gemini-3.5-flash`).

## Root cause

Not a missing context window — `deepseek-v4-pro` is in pi-ai's registry with `contextWindow = 1_000_000`, so the denominator resolves. The flicker is a logic flaw in the renderer:

- `updateContextFill()` hides the bar whenever `contextTokens <= 0` (`app/src/renderer/app.ts` ~L349).
- `captureUsage()` runs on **every** `message_start` / `message_update` / `message_end` / `turn_end` event, and recomputes `contextTokens = (u.input ?? 0) + (u.cacheRead ?? 0) + (u.cacheWrite ?? 0)` whenever *any* of those fields is a number (~L1029).
- During streaming, providers emit early usage deltas with `input: 0` (an explicit numeric zero) before the prompt-token count is finalized at `message_end`. The guard treats `input: 0` as a usable signal → sets `contextTokens = 0` → the bar **hides** mid-turn, reappearing only when the final usage lands. DeepSeek's reasoning turns are long, so the bar is gone for seconds each turn.
- A model switch also sets `contextTokens = 0` (intended, to drop the prior model's size), hiding the bar until the new model's first usage — a one-time hide that compounds the impression.

The existing comment ("Update only when we have a usable signal so a partial event doesn't zero it") describes the intended behavior, but the guard doesn't achieve it: a numeric `0` passes through and zeroes the value.

## Fix (interim, on #164)

- Only update `contextTokens` when the computed **sum is > 0** — treat an all-zero usage event as "no signal, keep the last value." That preserves the bar through transient mid-stream zeros.
- Optionally: once a model has produced a positive reading, keep the bar visible (don't let a later zero hide it) until an actual model switch / new session.

## Better fix (supersedes)

Option B (#165): drive the indicator from the harness's stable `ctx.getContextUsage()` instead of reconstructing the number from streaming usage deltas. That removes the transient-zero class of bug entirely (and also fixes the post-compaction staleness noted in #165).

## Acceptance criteria

- [ ] While on a model with a known context window and at least one completed turn, the bar stays continuously visible (no blink during streaming).
- [ ] The bar is hidden only before the first turn of a session/model, or when the window is genuinely unknown.
- [ ] A model switch hides it at most until the next turn's usage, then it stays put.

## Related

- #164 — the indicator this fixes.
- #165 — Option B (the robust supersede; also covers post-compaction refresh).

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.