|
|
|
@@ -61,24 +61,31 @@ from ratatoskr.sse_client import (
|
|
|
|
|
stream_turn,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# ---- Australis theme (https://github.com/lkraven/australis) ------------------
|
|
|
|
|
# ---- Australis-derived theme (https://github.com/lkraven/australis) ----------
|
|
|
|
|
#
|
|
|
|
|
# The Australis Dark color theme, inspired by the Southern Lights. 16 cool-tone
|
|
|
|
|
# terminal colors with medium contrast. Preference order: blue > cyan > green
|
|
|
|
|
# for primary surfaces; Dawn accents (red/yellow/magenta) used sparingly for
|
|
|
|
|
# terminal-event labels (error/cancelled).
|
|
|
|
|
# v0.6.2 deliberate deviation from spec: the Australis Dark theme's design
|
|
|
|
|
# principle "all colors are cooler than neutral" bakes a blue cast into
|
|
|
|
|
# every dark surface (Ice black #222531 = RGB 34/37/49 — blue dominant).
|
|
|
|
|
# Operators reported the whole-app chrome reading as blue. Ratatoskr keeps
|
|
|
|
|
# the Australis ACCENTS (Aurora blue/cyan/green, Dawn red/yellow) — those
|
|
|
|
|
# are the brand signature — but **neutralizes the Ice/Sea dark palette to
|
|
|
|
|
# true grays** so the chrome reads as neutral dark, not blue-leaning.
|
|
|
|
|
#
|
|
|
|
|
# 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).
|
|
|
|
|
# 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).
|
|
|
|
|
# panel = Sea dark 30 (#414751) — borders, separators.
|
|
|
|
|
# primary = Aurora blue (#6388D8) — focus rings, active selection (KEEP).
|
|
|
|
|
# secondary = Aurora cyan (#00b1a8) — secondary highlights (KEEP).
|
|
|
|
|
# accent = Aurora bright cyan (#42dcd1) — bright accents (KEEP).
|
|
|
|
|
# success = Aurora green (#16B866) — [done] label (KEEP).
|
|
|
|
|
# warning = Dawn yellow (#e1c631) — [cancelled] label (KEEP).
|
|
|
|
|
# error = Dawn red (#ff491a) — [error] label (KEEP).
|
|
|
|
|
# foreground = neutral light gray (#bdbdbd) — default text (was Ice white).
|
|
|
|
|
# background = neutral near-black (#1a1a1a) — App bg (was Ice black).
|
|
|
|
|
# surface = neutral dark gray (#2a2a2a) — chrome (was Sea bright-black).
|
|
|
|
|
# panel = neutral mid gray (#3a3a3a) — borders (was Sea dark-30).
|
|
|
|
|
#
|
|
|
|
|
# Dark contrast steps preserve Australis's LAB lightness levels but drop the
|
|
|
|
|
# blue/green tint. Variables renamed mentally but kept under $au-* slugs so
|
|
|
|
|
# downstream CSS doesn't change.
|
|
|
|
|
|
|
|
|
|
AUSTRALIS_THEME = Theme(
|
|
|
|
|
name="australis",
|
|
|
|
@@ -88,20 +95,22 @@ AUSTRALIS_THEME = Theme(
|
|
|
|
|
success="#16B866",
|
|
|
|
|
warning="#e1c631",
|
|
|
|
|
error="#ff491a",
|
|
|
|
|
foreground="#a9bcc3",
|
|
|
|
|
background="#222531",
|
|
|
|
|
surface="#373b46",
|
|
|
|
|
panel="#414751",
|
|
|
|
|
foreground="#bdbdbd",
|
|
|
|
|
background="#1a1a1a",
|
|
|
|
|
surface="#2a2a2a",
|
|
|
|
|
panel="#3a3a3a",
|
|
|
|
|
dark=True,
|
|
|
|
|
variables={
|
|
|
|
|
# Sea contrast palette — usable via $au-dark-50 etc. in TCSS.
|
|
|
|
|
"au-dark-30": "#414751",
|
|
|
|
|
"au-dark-40": "#565f69",
|
|
|
|
|
"au-dark-50": "#6e7882",
|
|
|
|
|
"au-dark-60": "#86929d",
|
|
|
|
|
"au-bright-70": "#9daeb6",
|
|
|
|
|
"au-bright-80": "#b3cbcf",
|
|
|
|
|
"au-bright-white": "#cce7ec",
|
|
|
|
|
# Neutral dark contrast palette (LAB-matched to Australis Sea spec
|
|
|
|
|
# but with R=G=B, no cool cast). $au-dark-N accessible via TCSS.
|
|
|
|
|
"au-dark-30": "#3a3a3a",
|
|
|
|
|
"au-dark-40": "#4f4f4f",
|
|
|
|
|
"au-dark-50": "#6b6b6b",
|
|
|
|
|
"au-dark-60": "#878787",
|
|
|
|
|
"au-bright-70": "#9e9e9e",
|
|
|
|
|
"au-bright-80": "#bdbdbd",
|
|
|
|
|
"au-bright-white": "#e0e0e0",
|
|
|
|
|
# Accents — KEEP Australis Aurora brights for brand signature.
|
|
|
|
|
"au-bright-blue": "#a4c4ff",
|
|
|
|
|
"au-bright-cyan": "#42dcd1",
|
|
|
|
|
"au-bright-green": "#51e08a",
|
|
|
|
@@ -116,8 +125,8 @@ _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_DEMOTED = "#878787" # neutral dark-60 — demoted telemetry
|
|
|
|
|
_AU_DEMOTED_FAINT = "#6b6b6b" # neutral 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,29 @@ 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. */
|
|
|
|
|
#agent-list > ListItem {
|
|
|
|
|
height: auto;
|
|
|
|
|
padding: 1 1;
|
|
|
|
|
background: $background;
|
|
|
|
|
}
|
|
|
|
|
#agent-list > ListItem.--highlight {
|
|
|
|
|
/* v0.6.1: override Textual's default ListView:focus highlight, which
|
|
|
|
|
defaults to $primary (Aurora blue) and made the picker unreadable.
|
|
|
|
|
Both selectors needed — focused state has higher specificity in
|
|
|
|
|
Textual's defaults. */
|
|
|
|
|
ListView > ListItem.--highlight,
|
|
|
|
|
ListView:focus > ListItem.--highlight {
|
|
|
|
|
background: $au-dark-30;
|
|
|
|
|
}
|
|
|
|
|
/* Children of highlighted items keep their colors — the dark-30 bg
|
|
|
|
|
provides enough contrast for bright-blue id + dark-60 desc text. */
|
|
|
|
|
.agent-id-line {
|
|
|
|
|
color: $au-bright-blue;
|
|
|
|
|
text-style: bold;
|
|
|
|
|
}
|
|
|
|
|
.agent-desc {
|
|
|
|
|
color: $au-dark-60;
|
|
|
|
|
color: $au-bright-70;
|
|
|
|
|
}
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
@@ -489,16 +521,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 +552,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 +681,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 +694,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")
|
|
|
|
|