diff --git a/CHANGELOG.md b/CHANGELOG.md index ca46420f..70667575 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,9 +39,16 @@ This format follows [Keep a Changelog](https://keepachangelog.com/) and adheres explicit message. - **The Cockpit Observe dashboard was redesigned.** Shared design tokens now live in `agentops.agent.ui_theme`; Observe uses an explicit `data-theme` attribute - with an in-memory toggle instead of following the OS colour scheme, and the - Overview is organised around executive KPI cards. The Cockpit itself now renders - its tokens from the same module, so the two surfaces cannot drift. + instead of following the OS colour scheme, and the Overview is organised around + executive KPI cards. Cockpit and Observe now use the same dark/light control and + carry the non-sensitive theme preference in navigation URLs, without browser + storage or cookies. +- **Observe usage tables now present telemetry consistently.** Agents, models, + tools, runs, and drill-through details use compact UTC timestamps, seconds for + durations, separate cache-read, cache-write, and reasoning-token columns, + contextual information icons, and totals for additive metrics. Model deployment + falls back to the request model when a deployment attribute is absent, while the + response model remains independently visible. - **Observability readiness only reports what it can actually verify.** Multi-turn coverage is treated as a dataset property and inferred solely from conversation rows; rubric evaluators count as ready only when they are both declared and diff --git a/src/agentops/agent/cockpit.py b/src/agentops/agent/cockpit.py index 6231710a..04119739 100644 --- a/src/agentops/agent/cockpit.py +++ b/src/agentops/agent/cockpit.py @@ -3,7 +3,7 @@ ``agentops cockpit`` boots a tiny FastAPI server that reads the analysis history from ``.agentops/agent/history.jsonl`` **and** the evaluation history from ``.agentops/results/*/results.json``, then -serves a single cockpit page in a dark theme. No external frontend +serves a single cockpit page with explicit dark and light themes. No external frontend dependencies (sparklines are inline SVG); no Azure resource required. The server is intentionally read-only and bound to ``127.0.0.1`` by @@ -28,7 +28,11 @@ from agentops.agent.history import AnalysisRecord, load_analysis_history from agentops.agent.time_range import TimeRange -from agentops.agent.ui_theme import render_theme_variables +from agentops.agent.ui_theme import ( + THEME_TOGGLE_SCRIPT, + render_theme_toggle, + render_theme_variables, +) from agentops.core.attribution import load_attribution_config from agentops.core.cost import MAX_COST_COMPONENTS, MAX_COST_PERIODS, load_cost_model from agentops.core.governance import ( @@ -4463,6 +4467,10 @@ def render_cockpit_html(payload: Dict[str, Any]) -> str: workspace_display=workspace_display, workspace=payload["workspace"], icon_uri=_icon_data_uri(), + theme_toggle=render_theme_toggle( + control_id="cockpit-theme-toggle", extra_class="cockpit-theme-toggle" + ), + theme_script=THEME_TOGGLE_SCRIPT, ) @@ -4517,6 +4525,22 @@ def _shorten_workspace(path: str) -> str: display: flex; flex-direction: column; align-items: flex-end; gap: 10px; color: var(--text-dim); font-size: 12px; font-weight: 500; }} + header .header-actions {{ + display: flex; align-items: center; gap: 12px; flex-wrap: wrap; + }} + .aos-btn {{ + display: inline-flex; align-items: center; gap: 6px; + padding: 6px 13px; border-radius: 8px; + border: 1px solid var(--border); background: var(--card); + color: var(--text); font: inherit; font-size: 13px; font-weight: 600; + cursor: pointer; + transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease; + }} + .aos-btn:hover {{ border-color: var(--border-strong); background: var(--card-hi); }} + .aos-btn:focus-visible {{ + outline: 2px solid var(--accent); outline-offset: 2px; + }} + .aos-theme-toggle .aos-theme-icon {{ font-size: 14px; line-height: 1; }} header .stats-counts {{ display: flex; align-items: center; gap: 18px; }} @@ -5304,7 +5328,10 @@ def _shorten_workspace(path: str) -> str: