Repository navigation
v2.6.0
- Re-released on 2026-09-15. The first
2.6.0and2.6.1builds (published 2026-09-14) were replaced by this single release, which also contains the context-window work below. If you installed either of them, paste this file again - the version number did not change. - Running chat token total (
🧮). A new metric shows how many tokens the chat has consumed so far: the sum of every response'sΣon the current branch - the token twin of the💰Σcost total, and the only chat-wide number for models that report no cost (Ollama, llama.cpp, other local or free models). Because the model re-reads the whole history on every turn, it counts processed tokens and grows much faster than the context window - it is not the size of the chat (that is📐). Details:- New admin valve
show_cumulative_tokens(on by default) and metric keytokens_total, placed right aftertotalin the default order. If you saved a customdisplay_order, the new key is appended at the end, as with any unlisted metric - addtokens_totalwhere you want it. Icons:🧮(emoji) /ΣΣ(simple);compact_numbersapplies to it. - Hidden when it equals the message
Σ(the first turn), like💰Σ. Marked≈when the current turn'sΣis a tiktoken estimate. - Past responses are summed from their stored
usagewith the same cache-aware total asΣ; responses without usage are skipped, not re-estimated. - Temporary chats (and API requests without a chat id): Open WebUI hands the filter their history without per-message usage, so both
🧮and💰Σcollapse to the current message there (and are hidden). Verified against Open WebUI v0.11.0 and v0.11.3. debug_mode: newcumulative_tokens_debugblock (total,estimated,messages_counted,messages_skipped_no_usage); thetokensblock carriescumulative/cumulative_est.
- New admin valve
- Fixed: a non-finite token count (
NaN/Infinity) inusageno longer breaks the stats line. Python's JSON parser accepts these values, and the plugin converted them withint()on a path that is not exception-guarded, so such a value in the current response aborted the line - and, with the new chat total walking the history, one bad stored response would have aborted it for every later response in the chat. Non-finite numbers are now treated as "not a number" at the single numeric intake (_num), so the affected field is simply omitted. The same class of value in thecontext_size_mapvalve (Infinity) is now skipped per entry instead of disabling the whole map. - Fixed: a local model showed its trained maximum instead of the server's real context window (#6: Qwen3.6 on
llama-server --ctx-size 16384showed7.2k/131.1k (6%)instead of7.2k/16.4k (44%); #14: a llama.cpp model started by llama-swap with--fitshowed no real context size). The size came from the built-in table (qwen3= 131072), and the opt-in llama.cpp / llama-swap probe was ranked below that table, so it never ran for any model family the table knows - settingllamacpp_urlcould not fix it either. Behind llama-swap three more things stood in the way: llama.cpp's--fit(on by default) picks the window at load time, so the--ctx-sizethe probe looked for is not in the launch command; llama-swap refuses a plain/propswithout?model=; and the probe URL needed the API key typed into a valve. The context size is now resolved in this order:context_size_override->num_ctx-> yourcontext_size_map-> live connection window -> backend listing -> matched probe -> models.dev -> built-in table -> unmatched probe. Changes:- New automatic source: the running window asked through the model's own Open WebUI connection. For a model listed by llama-swap (
owned_by: llama-swap) or a llama.cpp router (owned_by: llamacppwith astatusblock), the plugin reuses that connection's base URL, API key andprefix_idfrom Open WebUI - no valve, no key copied. Cloud connections are never contacted: they are not detected. Debugcontext_debug.source: connection_probe,matched_keynames the backend and model id. A hit is cached forcontext_probe_ttl; a miss is not. - New automatic source, no configuration and no network: the size the serving backend lists for the model in its
/v1/modelsrow, which Open WebUI already passes to the plugin. llama.cpp lists the running window asmeta.n_ctx(builds since May 2026), llama-swap does the same whencapabilities.contextis set in its config, and vLLM listsmax_model_len. A live connection answer beats it, because llama-swap'scapabilities.contextis a config number that may not be the window--fitpicked. Debugcontext_debug.source: backend,matched_keynames the field. Workspace/"agent" models read it from their base model's listing entry. It is not cached, so a relisted model applies at once. - A probe never loads a model. A model-dispatched request makes llama-swap start the model if it is not running, evicting whatever is. llama-swap is therefore asked
/runningfirst and/props?model=only for a model in stateready; a llama.cpp router is asked withautoload=false, which refuses instead of loading. The API key is sent only as a bearer token, and only when the connection itself uses bearer auth; session / OAuth / Entra ID connections are probed without it. Not detected: a connection restricted to hand-typed model ids (Open WebUI keeps no listing row for those) - use the valves orcontext_size_mapthere. - The valve probe (
llamacpp_url/llama_swap_url) now outranks models.dev and the built-in table when its row matches the called model (debugmatched_keynames the row). llama-swap can run several models at once, and the probe used to take the first/runningrow regardless of which model Open WebUI called; it now picks the matching row, asks/props?model=for it when it isready, and falls back to the--ctx-sizeof its command (e.g. a vLLM upstream without/props). With several running models and no match it reports nothing and falls through tollamacpp_url, if set. llama.cpp is asked/v1/modelsfirst (id or alias ->meta.n_ctx), then/propsfor older builds (matched by the model alias or GGUF file name). A backend's only running model under a different id (an alias) is still used, but only after the tables, so a cloud model is never given a local server's window. - Strict probe id matching: a row matches when its id equals the called id or ends it after a connection prefix (
prefix.id) or a path (org/id) - no substring match, so a localqwennever claims a cloudqwen3-max. debug_mode: newmodel.backend_contextblock with the listing'sn_ctx(running),n_ctx_train(trained) andmax_model_len, andmodel.live_backend([kind, listed id]ornull) showing whether the model was recognized as a live-probe candidate.outletnow also accepts__request__(needed for the workspace-model and connection lookups); its dunder parameters became keyword-only, which is how Open WebUI passes them.- Verified against Open WebUI v0.11.3 (connection lookup
routers/openai.py:get_openai_connection, 0.10.0+;app.state.configon 0.9.x), llama.cppmaster(2026-09-15), llama-swapmain(2026-09-13) and vLLMmain.
- New automatic source: the running window asked through the model's own Open WebUI connection. For a model listed by llama-swap (
- Internal (no behavior change): stricter linting (ruff with every rule enabled), the stats-line renderers take a single
_Statsobject instead of six positional arguments, and the most branchy resolvers were split into helpers. Development tooling moved fromrequirements-dev.txtto uv with a committeduv.lock, so CI runs exactly the locally locked ruff/mypy/pytest versions (see CONTRIBUTING.md). - Idea credit for the chat token total: the fork ArtyCooL/openwebui-token-usage-display.
Full Changelog: v2.5.2...v2.6.0