TokenPak

Release

TokenPak v1.24.0

v1.24.0 · Sep 3, 2026

This release restructures the served dashboard around a savings-led information hierarchy, publishes the first reviewed wall-clock time-remaining forecast calibration cell, makes the retry primitives directly importable from a new core module, fixes a request-accounting bug for bodyless model requests, fixes tokenpak serve to honor the configured port and the TOKENPAK_PORT environment variable, expands the dev extra to include the dependencies the typed proxy surfaces import, and refreshes dependency lockfiles to close open security advisories.

Added

  • Published the first reviewed time-remaining forecast calibration cell — claude-sonnet-5 / unknown effort / streaming — into the per-cell publication table added in 1.23.0. This makes status: "available" (with a real remaining_time_likely_50_ms/remaining_time_ceiling_90_ms band) reachable for that one cell; every other cell continues to report "insufficient_data". The mechanism remains gated behind its existing default-off master switch (TOKENPAK_TIME_FORECAST_BANDS / time_forecast_bands.enabled, both still default-off) — populating the table only makes the cell eligible, it does not change the shipped default. See the time_forecast section in docs/api-reference.md.
  • The retry engine (RetryEngine, RetryExhaustedError, ImmediateAlertError, load_recent_retry_events, and their supporting constants) is now directly importable from tokenpak.core.retry. The existing tokenpak.orchestration.retry import path continues to work unchanged — it is now a compatibility re-export of the identical objects, not a copy. No behavior change.

Changed

  • The served dashboard (/dashboard) is restructured around a seven-block information hierarchy, savings-led:
  1. Savings hero — today's tokens and dollars saved, large and centered at the top of the page (an honest "not yet measured" state when there is no data yet).
  2. Status strip — one combined health signal (Healthy / Idle / Degraded / Error) plus its three supporting facts: credentials, last-request time, and queue depth. Replaces the previously buried status dot.
  3. Compression chart — last-24h original vs. compressed tokens, backed by the same query the CLI status command already uses.
  4. Cache strip — separates the product-attributed cache hit rate (cache reads this product's own cache marker produced) from the general provider-level cache hit rate, plus a client/proxy/unknown token breakdown. This replaces a card that was labeled as a cache hit rate but was actually derived from proxy uptime; that formula is removed.
  5. Recent requests — the last 20 requests (time, client, model, tokens in/out, savings, cache origin).
  6. Mode / session breakdown — retained as-is.
  7. Quick actions — retained as-is.

Backend support is additive and fails open when the request log is unavailable: new GET /savings and GET /recent endpoints, and a new window_24h field on the existing GET /cache-stats and GET /metrics/dashboard responses. The dashboard's client-side refresh interval also changes from 30s to 5s, and polling now pauses while the browser tab is backgrounded.

  • tokenpak.core.runtime.proxy remains importable as a compatibility path for the launcher, which now lives in tokenpak.proxy.bootstrap.

Fixed

  • A model-endpoint request sent with no body no longer causes the proxy to log a spurious internal error after the response has already been delivered to the client. The request's usage is now recorded normally instead of being dropped.
  • tokenpak serve now honors the configured port (<config-dir>/config.yaml) and TOKENPAK_PORT when --port is not given, instead of always binding the built-in default. Precedence: --port flag > TOKENPAK_PORT env var

config file port > 8766.

Dependencies

  • The dev extra now pulls in tokenpak[serve] (fastapi, uvicorn, starlette, jinja2, python-multipart, websockets) alongside the existing tokenpak[dispatch] pull-in, so a plain pip install -e ".[dev]" can import, test, and mypy --strict the proxy subsystem and the telemetry dashboard/query/ingest HTTP surfaces it imports at module level.

Security

  • Refreshed pinned lockfile versions to close open dependency advisories. aiohttp 3.14.1 → 3.14.3 (CVE-2026-69244, CVE-2026-69243, CVE-2026-59881), cryptography 49.0.0 → 50.0.1 (CVE-2026-69247), and h2 4.3.0 → 4.4.1 (CVE-2026-71554) are core runtime dependencies, so this closes the exposure window for anyone installing from the pinned uv.lock (a plain pip install tokenpak was already unaffected — the declared version ranges have no upper pin, so a fresh resolve already picks up the patched releases). Also bumped nltk 3.10.0 → 3.10.3, which is not part of the base install and is only pulled in by the optional compression and llamaindex extras; one nltk advisory (CVE-2026-81726) has no upstream fix yet and remains open for anyone using those extras. The sdk/ and packages/tokenpak-js/ npm lockfiles were refreshed for browserslist and js-yaml, both dev-tooling-only transitive dependencies with no runtime exposure for consumers of those packages; the packages/tokenpak-js lockfile also picked up a brace-expansion bump (1.1.16 → 1.1.18, also a dev-only transitive dependency with no runtime exposure) as an incidental result of the same npm audit fix pass.