Skip to content

chore(deps): bump tuika to 0.9 and migrate the dashboard runner - #80

Merged
chaliy merged 2 commits into
mainfrom
claude/tuika-bump-test-ship-8idbjf
Aug 15, 2026
Merged

chaliy merged 2 commits into
mainfrom
claude/tuika-bump-test-ship-8idbjf

Conversation

@chaliy

@chaliy chaliy commented Aug 15, 2026

Copy link
Copy Markdown
Owner

What changed

serve --tui now runs on tuika 0.9 (from 0.4). The dashboard looks and behaves
exactly as before — same panels, same colors, same q/r bindings — so this is
a no-op for users of the binary. What changed is underneath:

  • The host loop moved to tuika 0.9's single FrameSource seam
    (run(theme, async_from_fn(state, view, update))), replacing the four-argument
    run(theme, state, view, update) that 0.9 removed.
  • The async update closure now returns UpdateResult (Dirty / Exit / Clean)
    instead of ControlFlow<()>. Ticks and manual refreshes return Dirty so the
    frame still repaints on every poll; unmatched and modified keys return Clean,
    which lets the runner apply its own default input handling.
  • Signal handling is split out of the runner closure into an update function.
    That is what makes the tick/refresh/quit contract testable without a terminal —
    previously none of it was covered.
  • Import moves: Flex → tuika::components, RatatuiView → tuika::interop;
    RunnerConfig gained a screen_mode field (left at its Alternate default).

ratatui still unifies on 0.30.2 across the RatatuiView interop boundary, so the
widget code is untouched.

Why

tuika 0.4 is five releases behind. 0.9 is a breaking release that collapses the
runner's ten run* methods into one seam and changes the update-result type, so
the bump could not be a version-only change — taking it now keeps the dashboard
on a supported API instead of accumulating more drift.

Before / After

The rendered dashboard is unchanged. Captured live against a running server
(serve --tui) on this branch, after driving traffic through the OpenAI and
Anthropic endpoints:

 ┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
 │  LLMSim Stats Dashboard   │ ● CONNECTED │ Uptime: 8s                                                               │
 └────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
 ┌ Requests ───────────────────────────────────────────────┐┌ Tokens ─────────────────────────────────────────────────┐
 │Total Requests                    6                      ││Prompt Tokens                     57                     │
 │Active Requests                   0                      ││Completion Tokens                 644                    │
 │Completions API                   3                      ││Total Tokens                      701                    │
 │Responses API                     0                      ││Tokens/sec                        0.0                    │
 │Messages API                      3                      ││                                                         │
 │Streaming                         0                      ││                                                         │
 │Requests/sec                      1.20                   ││                                                         │
 └─────────────────────────────────────────────────────────┘└─────────────────────────────────────────────────────────┘
 ┌ Latency ────────────────────────────────────────────────┐┌ Errors ─────────────────────────────────────────────────┐
 │Average                      423.81 ms                   ││Total Errors                      0 (0.0%)               │
 │Minimum                      301.58 ms                   ││Rate Limit (429)                  0                      │
 │Maximum                      566.21 ms                   ││Server (5xx)                      0                      │
 │                                                         ││Timeout (504)                     0                      │
 └─────────────────────────────────────────────────────────┘└─────────────────────────────────────────────────────────┘
 ┌ RPS (current: 1.20, max: 2.00) ────────────────────────────────────┐┌ Models (top 8) ──────────────────────────────┐
 │                      ██  ███  ███                                  ││███ ███                                       │
 │                      ██ ▄███▆▆███▄▄▄▄▄                             ││███ ███                                       │
 │                      ██ ██████████████▄▄▄                          ││███ ███                                       │
 │                   ███████████████████████                          ││███ ███                                       │
 └────────────────────────────────────────────────────────────────────┘│███ ███                                       │
 ┌ Tokens/sec (current: 0, max: 618) ─────────────────────────────────┐│███ ███                                       │
 │  █▄  ▃ ▅▅                                                          ││█3█ █3█                                       │
 │  ██  █ ██                                                          ││cla gpt                                       │
 └────────────────────────────────────────────────────────────────────┘└──────────────────────────────────────────────┘
  q  Quit   r  Refresh

Live-refresh (r) and quit (q) were both exercised interactively: the panels
update out of the tick cadence on r, and q tears the alternate screen down
and exits cleanly.

Before the bump, the crate did not build against tuika 0.9 at all — 6 compile
errors across the two TUI modules (unresolved Flex/RatatuiView, the missing
RunnerConfig::screen_mode field, and the changed run signature).

Risk

  • Low
  • The blast radius is the optional tui feature; the server, APIs, and library
    paths are untouched. A behavior regression would be confined to the dashboard's
    repaint cadence or key handling, both of which are now covered by tests and were
    verified interactively.

Checklist

  • Tests added or updated — 5 new tests over the migrated signal handling
    (tick polls and repaints, dead server records the disconnected state, r
    refreshes out of cadence, q/Esc exit, unmatched and modified keys stay
    Clean), against a stub stats endpoint so no terminal is needed. Full
    suite: 289 passing.
  • Backward compatibility considered — no public API or wire-format change;
    dashboard rendering is byte-identical.

Generated by Claude Code

chaliy added 2 commits August 15, 2026 05:34
tuika 0.9 collapses the runner's ten `run*` methods into one `FrameSource`
seam and replaces the async update closure's `ControlFlow<()>` with
`UpdateResult`, so the dashboard host loop moves to
`run(theme, async_from_fn(state, view, update))` and returns
`Dirty`/`Exit`/`Clean` instead of `Continue`/`Break`. `Flex` and
`RatatuiView` moved to `components` and `interop` respectively, and
`RunnerConfig` gained a `screen_mode` field.

The signal handling is split out of the runner closure into `update`, so
the tick/refresh/quit contract is covered by tests that need no terminal:
ticks poll and repaint, a dead server records the disconnected state,
`r` refreshes out of the tick cadence, `q`/`Esc` exit, and unmatched or
modified keys stay `Clean` for the runner's own default handling.

Rendering is unchanged; ratatui still unifies on 0.30.2.
`openai` 3.x depends on `httpx2` rather than `httpx`, so the raw Responses
API call in this example lost its transitive `httpx` and died with
`ModuleNotFoundError`. The examples resolve from PyPI at run time, so the
break arrived with the upstream release rather than with any repo change.

Declare `httpx` explicitly in the script's inline metadata.
@chaliy
chaliy merged commit dfbd05a into main Aug 15, 2026
11 checks passed
@chaliy
chaliy deleted the claude/tuika-bump-test-ship-8idbjf branch August 15, 2026 05:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant