Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 82437bd4b9 | |||
| ac690c11d5 | |||
| d845b20efd | |||
| 8463eb22ff | |||
| eb93e6d5f0 |
@@ -163,7 +163,7 @@ New `Static(id="pane-name")` widget alongside the existing `identity` + `hint` w
|
||||
- **INV-021** *(new v0.6.0)*: `Text` events do NOT route to `log` per-delta. They accumulate into `TuiPresenterState.text_buffer` and update a single `current_text` Static (docked above the prompt). On terminal event (`Done`/`Error`/`Cancelled`), `current_text` is cleared and (raw mode) accumulated text or (non-raw) post-Done `Markdown(response)` is written to `log`. The pre-v0.6.0 per-token RichLog spam is retired.
|
||||
- **INV-022** *(new v0.6.0)*: Closed thinking runs route to `thinking_log`, NOT `debug_log`. Each closed run writes three entries: `Rule(title=f"turn N · thinking #K start")`, `Markdown(content)`, `Rule(title=f"turn N · thinking #K end")` — the model's chain-of-thought is presented as rendered Markdown (model reasoning often has lists / code / structure) wrapped in operator-visible start/end markers. `thinking_run_index` increments per-run within a turn.
|
||||
- **INV-023** *(new v0.6.0)*: Turn-ID header `Rule(title=f"turn N")` is written to all four log panes (`log`, `tools_log`, `debug_log`, `thinking_log`) by `_stream_turn_worker` on the first event of each turn — enables cross-pane visual correlation during multi-turn debugging.
|
||||
- **INV-024** *(new v0.6.0)*: `thinking-current` Static remains in the right column (above TabbedContent) per INV-017 — live per-delta thinking visibility persists across tab switches. Prefix `thinking… ` self-identifies the widget contents.
|
||||
- **INV-024** *(amended v0.6.1)*: `thinking-current` Static lives INSIDE the Thinking TabPane (docked bottom, below `thinking-log`) — co-located with closed thinking runs so the operator sees streaming + history in one pane. Pre-v0.6.1 it sat above the TabbedContent (right-column header) which created a top/bottom discontinuity; the co-located shape resolves that. Trade-off: live thinking is now visible only when the Thinking tab is active (Ctrl+3). Prefix `thinking… ` self-identifies the widget contents.
|
||||
|
||||
## TESTS (additions / changes to test_tui.py)
|
||||
|
||||
|
||||
@@ -32,9 +32,9 @@ separate dev team rather than an in-tree Worldtree tool.
|
||||
|
||||
## Current state / in-flight
|
||||
|
||||
_As of 2026-05-24 (post-v0.6.0 streaming + Thinking pane + turn headers):_
|
||||
_As of 2026-05-24 (post-v0.6.4 picker Aurora-blue highlight):_
|
||||
|
||||
**Status: v0.6.0 shipped.** Nine core issues complete (`sse_client`
|
||||
**Status: v0.6.4 shipped.** Nine core issues complete (`sse_client`
|
||||
#1, `sessions` #2, `cli` #3, `tui` #4, `--end-user-id` #5, TUI
|
||||
startup error visibility #6, presenter contract semantics amendment
|
||||
#12, startup agent picker #8, §5 layout reshape + Tools pane #13)
|
||||
@@ -51,7 +51,11 @@ Static in the footer (static "Tools" v1; dynamic when more tabs
|
||||
land). CLI mode (--send) unaffected by design — INV-018.
|
||||
|
||||
Last commits on `main`:
|
||||
- v0.6.0 refactor(tui): streaming Static + turn headers + Thinking pane + agent picker multi-line
|
||||
- v0.6.4 style(tui): picker highlighted item → Aurora blue (brand selection treatment)
|
||||
- `ac690c1` style(tui): restore Australis palette, only $background → pure black (v0.6.3)
|
||||
- `d845b20` style(tui): neutralize Australis dark palette (v0.6.2, reverted)
|
||||
- `8463eb2` style(tui): kill remaining blue + thinking-current into pane (v0.6.1)
|
||||
- `cfee89a` refactor(tui): streaming + turn headers + Thinking pane (v0.6.0)
|
||||
- `7106af5` style(tui): UI polish pass — terminal label colors, placeholders (v0.5.1)
|
||||
- `ffd22fb` refactor(tui): content-only main pane + Debug tab + chrome dark (v0.5.0)
|
||||
- `2756f5f` style(tui): apply Australis theme to TUI chrome + widgets (v0.4.1)
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
||||
|
||||
[project]
|
||||
name = "ratatoskr"
|
||||
version = "0.6.0"
|
||||
version = "0.6.4"
|
||||
description = "Worldtree Conversation API debug TUI — multi-pane observability dashboard"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.12"
|
||||
|
||||
+83
-19
@@ -68,16 +68,25 @@ from ratatoskr.sse_client import (
|
||||
# for primary surfaces; Dawn accents (red/yellow/magenta) used sparingly for
|
||||
# terminal-event labels (error/cancelled).
|
||||
#
|
||||
# **v0.6.3 single deviation from spec**: `$background` is `#000000` (pure
|
||||
# black), NOT Australis Ice black `#222531`. The Ice black is RGB(34,37,49)
|
||||
# — blue dominant — and at App-wide scale the cumulative cast reads as
|
||||
# "the whole app is blue" to operators (even though no single surface is
|
||||
# "blue" in the strict-color sense). Pure black for the App background
|
||||
# kills that perception. EVERY OTHER Australis value — Aurora accents,
|
||||
# Sea darks for chrome (surface/panel), Ice white foreground, Dawn
|
||||
# accents — stays verbatim per spec.
|
||||
#
|
||||
# Mapping to Textual's Theme semantic tokens:
|
||||
# primary = Aurora blue (#6388D8) — focus rings, active selection.
|
||||
# secondary = Aurora cyan (#00b1a8) — secondary highlights.
|
||||
# accent = Aurora bright cyan (#42dcd1) — bright accents (pane-name, prompt echo).
|
||||
# accent = Aurora bright cyan (#42dcd1) — bright accents.
|
||||
# success = Aurora green (#16B866) — [done] label.
|
||||
# warning = Dawn yellow (#e1c631) — [cancelled] label.
|
||||
# error = Dawn red (#ff491a) — [error] label.
|
||||
# foreground = Ice white (#a9bcc3) — default text.
|
||||
# background = Ice black (#222531) — App background.
|
||||
# surface = Sea bright black (#373b46) — raised chrome (header/footer/input).
|
||||
# background = pure black (#000000) — App background (v0.6.3 deviation).
|
||||
# surface = Sea bright black (#373b46) — raised chrome.
|
||||
# panel = Sea dark 30 (#414751) — borders, separators.
|
||||
|
||||
AUSTRALIS_THEME = Theme(
|
||||
@@ -89,7 +98,7 @@ AUSTRALIS_THEME = Theme(
|
||||
warning="#e1c631",
|
||||
error="#ff491a",
|
||||
foreground="#a9bcc3",
|
||||
background="#222531",
|
||||
background="#000000",
|
||||
surface="#373b46",
|
||||
panel="#414751",
|
||||
dark=True,
|
||||
@@ -115,9 +124,9 @@ AUSTRALIS_THEME = Theme(
|
||||
_AU_SUCCESS = "#16B866"
|
||||
_AU_ERROR = "#ff491a"
|
||||
_AU_WARNING = "#e1c631"
|
||||
_AU_USER_ECHO = "#42dcd1" # bright cyan — operator's voice
|
||||
_AU_DEMOTED = "#86929d" # dark 60 — demoted telemetry (was bare "dim")
|
||||
_AU_DEMOTED_FAINT = "#6e7882" # dark 50 — empty-state placeholder text
|
||||
_AU_USER_ECHO = "#42dcd1" # Aurora bright cyan — operator's voice
|
||||
_AU_DEMOTED = "#86929d" # Sea dark 60 — demoted telemetry
|
||||
_AU_DEMOTED_FAINT = "#6e7882" # Sea dark 50 — empty-state placeholders
|
||||
|
||||
|
||||
# ---- Issue #12 presenter contract semantics amendment -------------------------
|
||||
@@ -382,13 +391,28 @@ class AgentPickerApp(App[str | None]):
|
||||
"""
|
||||
|
||||
DEFAULT_CSS = """
|
||||
Header {
|
||||
/* v0.6.1: kill Textual's $primary-blue tints everywhere — Header sub-
|
||||
widgets (HeaderIcon etc.) have their own $primary tinting that the
|
||||
parent `Header { background: $surface }` rule alone doesn't cover.
|
||||
Sub-selectors force the cool palette down to every level. */
|
||||
Header, HeaderIcon, HeaderTitle, HeaderClock {
|
||||
background: $surface;
|
||||
color: $au-bright-blue;
|
||||
}
|
||||
Footer {
|
||||
background: $surface;
|
||||
}
|
||||
/* v0.6.1: scrollbar uses Textual's $primary-tint by default. Force
|
||||
Australis Sea darks so the scrollbar gutter doesn't read as a blue
|
||||
strip. Applied to ListView (the scrollable widget here). */
|
||||
ListView {
|
||||
scrollbar-background: $background;
|
||||
scrollbar-background-hover: $background;
|
||||
scrollbar-background-active: $background;
|
||||
scrollbar-color: $au-dark-50;
|
||||
scrollbar-color-hover: $au-dark-60;
|
||||
scrollbar-color-active: $au-bright-cyan;
|
||||
}
|
||||
#picker-prompt {
|
||||
dock: top;
|
||||
height: 1;
|
||||
@@ -400,21 +424,41 @@ class AgentPickerApp(App[str | None]):
|
||||
height: 1fr;
|
||||
background: $background;
|
||||
}
|
||||
/* v0.6.0: multi-line agent items. Each ListItem is auto-height so the
|
||||
full description wraps below the agent_id/name line — no truncation. */
|
||||
/* Multi-line agent items. Each ListItem is auto-height so the full
|
||||
description wraps below the agent_id/name line — no truncation.
|
||||
v0.6.4: lock bg to $background so Textual's auto background-tint on
|
||||
focus doesn't bleed through unwanted color into the non-highlighted
|
||||
items. */
|
||||
#agent-list > ListItem {
|
||||
height: auto;
|
||||
padding: 1 1;
|
||||
background: $background;
|
||||
}
|
||||
#agent-list > ListItem.--highlight {
|
||||
background: $au-dark-30;
|
||||
/* v0.6.4: highlighted item gets Aurora blue background (Textual's
|
||||
default $block-cursor-background = $primary). Override only the
|
||||
text-color descendants so id-line/desc stay readable on blue. The
|
||||
background itself comes from Textual's default ListItem.-highlight
|
||||
rule — we removed our previous overriding selectors.
|
||||
|
||||
Textual's class is `-highlight` (single dash). Use plain descendant
|
||||
combinator to bypass internal DOM wrappers. */
|
||||
#agent-list:focus ListItem.-highlight {
|
||||
background: $primary;
|
||||
}
|
||||
#agent-list:focus ListItem.-highlight .agent-id-line {
|
||||
color: $au-bright-white;
|
||||
text-style: bold;
|
||||
}
|
||||
#agent-list:focus ListItem.-highlight .agent-desc {
|
||||
color: $au-bright-80;
|
||||
}
|
||||
/* Default (unhighlighted) item text styling. */
|
||||
.agent-id-line {
|
||||
color: $au-bright-blue;
|
||||
text-style: bold;
|
||||
}
|
||||
.agent-desc {
|
||||
color: $au-dark-60;
|
||||
color: $au-bright-70;
|
||||
}
|
||||
"""
|
||||
|
||||
@@ -489,16 +533,27 @@ class RatatoskrApp(App[int]):
|
||||
# Australis theme variables ($primary/$accent/$au-dark-60/$au-bright-cyan/
|
||||
# etc.) carry colors so a future theme swap rebinds centrally.
|
||||
DEFAULT_CSS = """
|
||||
/* Kill Textual's default $primary-blue tinting on chrome — Header,
|
||||
Footer, ContentTabs strip, active-tab Underline all forced to the
|
||||
Australis cool-dark palette. */
|
||||
Header {
|
||||
/* v0.6.1: kill Textual's default $primary-blue tinting on chrome —
|
||||
Header sub-widgets (HeaderIcon, HeaderTitle, HeaderClock) each carry
|
||||
their own $primary tint that the parent `Header { background }` rule
|
||||
doesn't override; sub-selectors force the cool palette down. */
|
||||
Header, HeaderIcon, HeaderTitle, HeaderClock {
|
||||
background: $surface;
|
||||
color: $au-bright-blue;
|
||||
}
|
||||
Footer {
|
||||
background: $surface;
|
||||
}
|
||||
/* v0.6.1: scrollbars default to $primary-tint blue. Force Sea darks
|
||||
on the scrollable widgets (RichLog instances). */
|
||||
RichLog {
|
||||
scrollbar-background: $background;
|
||||
scrollbar-background-hover: $background;
|
||||
scrollbar-background-active: $background;
|
||||
scrollbar-color: $au-dark-50;
|
||||
scrollbar-color-hover: $au-dark-60;
|
||||
scrollbar-color-active: $au-bright-cyan;
|
||||
}
|
||||
#main-row {
|
||||
height: 1fr;
|
||||
}
|
||||
@@ -509,12 +564,17 @@ class RatatoskrApp(App[int]):
|
||||
#right-column {
|
||||
width: 1fr;
|
||||
}
|
||||
/* v0.6.1: thinking-current Static moved INTO the Thinking pane (below
|
||||
thinking-log) so streaming + closed runs co-locate. Docked bottom of
|
||||
its TabPane so it acts as the live "tail" of the chronological log
|
||||
above. Empty (height:0) when no thinking is active. */
|
||||
#thinking-current {
|
||||
dock: top;
|
||||
dock: bottom;
|
||||
height: auto;
|
||||
color: $au-dark-60;
|
||||
padding: 0 1;
|
||||
text-style: italic;
|
||||
background: $background;
|
||||
}
|
||||
#transcript {
|
||||
height: 1fr;
|
||||
@@ -633,7 +693,6 @@ class RatatoskrApp(App[int]):
|
||||
yield Static("", id="current-text")
|
||||
yield Input(id="prompt", placeholder="Type a message and press Enter")
|
||||
with Vertical(id="right-column"):
|
||||
yield Static("", id="thinking-current")
|
||||
with TabbedContent(id="side-panes"):
|
||||
with TabPane("Tools", id="tools-tab"):
|
||||
yield RichLog(
|
||||
@@ -647,6 +706,11 @@ class RatatoskrApp(App[int]):
|
||||
yield RichLog(
|
||||
id="thinking-log", wrap=True, markup=False, highlight=False
|
||||
)
|
||||
# v0.6.1: live thinking lives INSIDE the Thinking
|
||||
# pane (docked bottom) — co-located with the closed
|
||||
# runs in thinking-log above. No more top/bottom
|
||||
# discontinuity across the right column.
|
||||
yield Static("", id="thinking-current")
|
||||
# INV-002 + INV-003: visible identity + hint widgets (Footer-area).
|
||||
# pane-name widget displays current side-pane name.
|
||||
yield Static("", id="identity")
|
||||
|
||||
Reference in New Issue
Block a user