Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .agents/plans/PLANS.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Persistent plans for multi-step work on **blxcode**. Individual plans live as Ma
| done | [plan-manager.md](plan-manager.md) | Plan Manager fuer `.agents/plans`: Manage-Tab wie Memory Files, plan-linked Tasks gruppiert, Agent-Toolcalls, System-Prompt-Update und shared Context fuer BLXCode Agent plus Terminal-Handoff |
| planned | [kanban-board-view.md](kanban-board-view.md) | Kanban-View im Plans-Panel fuer alle Plan-Tasks eines Workspaces: Status-Spalten, Drag-and-Drop fuer Karten und Spalten, Spalten ein-/ausblenden und Markdown-Writeback |
| done | [per-turn-chat-metrics.md](per-turn-chat-metrics.md) | Per-Turn Metriken (in/out/ttft/tok/s/cost) statt globaler Footer; Tool- und Subagent-Turns; Session-Gesamtkosten im Chatlog-Titel; Persistenz via workbench.json |
| planned | [settings-tabs-themes-refactor.md](settings-tabs-themes-refactor.md) | Dynamische Workbench-Tabs (Main/Settings/File-Stub); Settings inline statt Modal; Appearance mit ~12 Themes (Default blxcode-dark); Sidebar bleibt sichtbar |
| done | [settings-tabs-themes-refactor.md](settings-tabs-themes-refactor.md) | Dynamische Workbench-Tabs (Main/Settings/File-Stub); Settings inline statt Modal; Appearance mit 20 Themes (Default blxcode-dark); Sidebar bleibt sichtbar |
| done | [auto-update-github-releases.md](auto-update-github-releases.md) | Tauri Updater + signed latest.json, themed Leptos dialog/banner, Settings auto-check, hybrid release manifest flow, docs, and i18n implemented |
| done | [coordinated-subagents.md](coordinated-subagents.md) | Coordinated Subagents fuer BLXCode Agent mit Rollen, i18n Live-Subcards, Provider-Reuse, Environment Detection, Shell/Git/Web Toolsets und scoped Toolgruppen |
| done | [better-harness.md](better-harness.md) | BetterHarness: Shrink system prompt by extracting tool docs into 6 embedded Core Skills; Skills tab gets Core/User sub-tabs |
Expand Down
20 changes: 11 additions & 9 deletions .agents/plans/settings-tabs-themes-refactor.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# Settings-Refactor: Tabs + Theme-System

**Status: done** (2026-05-22)

## Summary

Refactor der BLXCode Settings von Modal-Overlay zu einem **dynamischen Tab-System** in der Workbench-Mitte: Main-Tab (fix, Terminals/Workspaces), Settings als schliessbarer Singleton-Tab, und vorbereitete **File-Tabs** (Explorer-Klick oeffnet Tab mit Stub-Editor). Settings blendet nur das Right Panel aus; linke Sidebar bleibt immer sichtbar. Neuer Appearance/Theme-Tab mit ~12 App-Themes, Suche, Dark/Light-Filter und Preview-Karten. Default-Theme `blxcode-dark` (Anzeigename „BLXCode“) ist der heutige Look 1:1.
Refactor der BLXCode Settings von Modal-Overlay zu einem **dynamischen Tab-System** in der Workbench-Mitte: Main-Tab (fix, Terminals/Workspaces), Settings als schliessbarer Singleton-Tab, und vorbereitete **File-Tabs** (Explorer-Klick oeffnet Tab mit Stub-Editor). Settings blendet nur das Right Panel aus; linke Sidebar bleibt immer sichtbar. Neuer Appearance/Theme-Tab mit **20 App-Themes**, Suche, Dark/Light-Filter und Preview-Karten. Default-Theme `blxcode-dark` (Anzeigename „BLXCode“) ist der heutige Look 1:1.

## Decisions

Expand All @@ -11,7 +13,7 @@ Refactor der BLXCode Settings von Modal-Overlay zu einem **dynamischen Tab-Syste
- File-Tabs: schliessbar, **Dedupe** bei gleichem `(workspace_id, rel_path)` solange Tab offen ist; Editor-Inhalt ist initial ein Stub (Follow-up: echter Editor).
- Settings ist **Singleton** — erneutes Oeffnen fokussiert bestehenden Tab.
- Main-Tab ist **fix** (Index 0, nicht schliessbar).
- **~12 Starter-Themes** im ersten Release.
- **~20 Starter-Themes** im ersten Release (12 MVP + 8 moderne Ergaenzungen: Rosé Pine, Rosé Pine Dawn, Everforest Dark, Kanagawa, GitHub Dark, Night Owl, Ayu Mirage, Catppuccin Frappé).
- Default-Theme: **`blxcode-dark`** (Anzeigename **„BLXCode“**). Erststart und fehlender localStorage-Eintrag → immer dieses Theme; kein visueller Regressions-Diff.
- `:root`-Tokens werden **1:1** nach `[data-theme="blxcode-dark"]` kopiert; `:root` bleibt als Fallback.
- Workbench-Tab-Zustand ist **session-only** (nicht in `WorkbenchSnapshot`).
Expand Down Expand Up @@ -181,10 +183,10 @@ Terminal: `public/terminal_bootstrap.mjs` — Theme-Map + `blxcode-theme-changed

## Tasks

- [ ] `tab-infra` - Dynamisches Tab-Modell (Main/Settings/File), CRUD-API, TabStrip/Host, FileTabPane-Stub, Explorer-Hook, RightPanel nur bei Settings ausblenden
- [ ] `settings-inline` - SettingsChrome aus Modal extrahieren → settings/ Modul; HarnessHost bereinigen; open_settings → Tab oeffnen; Escape/Chords anpassen
- [ ] `theme-tokens` - themes/tokens.css mit 12 Theme-Sets; blxcode-dark 1:1 aus aktuellem :root; data-theme auf html; THEME_STORAGE_KEY + ThemeService; Boot-Script in index.html
- [ ] `theme-pane-ui` - HarnessSettingsCategory::Appearance + ThemePane mit Suche, Dark/Light-Filter, Preview-Grid; i18n fuer alle Locales
- [ ] `terminal-theme-sync` - terminal_bootstrap.mjs: Theme-Map + blxcode-theme-changed Event fuer live xterm-Updates
- [ ] `css-polish` - Tab-Strip mit Scroll, Settings-Inline, Theme-Grid CSS; kritische hardcoded Farben tokenisieren
- [ ] `manual-qa` - Abnahme: dynamische Tabs, Dedupe, Main nicht schliessbar, Settings/File/Theme-Flows, Sidebar sichtbar, wasm32 check
- [x] `tab-infra` - Dynamisches Tab-Modell (Main/Settings/File), CRUD-API, TabStrip/Host, FileTabPane-Stub, Explorer-Hook, RightPanel nur bei Settings ausblenden
- [x] `settings-inline` - SettingsChrome aus Modal extrahieren → settings/ Modul; HarnessHost bereinigen; open_settings → Tab oeffnen; Escape/Chords anpassen
- [x] `theme-tokens` - themes/tokens.css mit 20 Theme-Sets; blxcode-dark 1:1 aus aktuellem :root; data-theme auf html; THEME_STORAGE_KEY + ThemeService; Boot-Script in index.html
- [x] `theme-pane-ui` - HarnessSettingsCategory::Appearance + ThemePane mit Suche, Dark/Light-Filter, Preview-Grid; i18n fuer alle Locales
- [x] `terminal-theme-sync` - terminal_bootstrap.mjs: Theme-Map + blxcode-theme-changed Event fuer live xterm-Updates
- [x] `css-polish` - Tab-Strip mit Scroll, Settings-Inline, Theme-Grid CSS; kritische hardcoded Farben tokenisieren
- [x] `manual-qa` - Abnahme: dynamische Tabs, Dedupe, Main nicht schliessbar, Settings/File/Theme-Flows, Sidebar sichtbar, wasm32 check
21 changes: 21 additions & 0 deletions .agents/rules/rule-theme-tokens.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Theme tokens

## Ziel

App-weite Themes über `html[data-theme]` und semantische CSS-Custom-Properties. Keine hardcodierten Farben in UI-Stylesheets.

## Vorgaben

- **Neue UI** nutzt ausschließlich `var(--token)` aus [`themes/tokens.css`](../../themes/tokens.css).
- **Keine** `var(--token, #literal)`-Fallbacks in Komponenten-CSS.
- **Theme-Wechsel** läuft über [`ThemeService`](../../src/workbench/theme_service.rs) (`blxcode-theme-changed` Event).
- **JS-Bridges** (xterm, Graph 3D) lesen Tokens via `getComputedStyle(document.documentElement)` — nicht hardcodieren.
- **Rust/SVG** (Memory-Graph 2D): Farben aus `read_css_var()` + Reaktion auf `ThemeService::active_theme_id`.

## Bewusste Ausnahmen

Siehe [`docs/THEME_EXCEPTIONS.md`](../../docs/THEME_EXCEPTIONS.md).

## CI

`scripts/lint_theme_tokens.sh` vor Merge ausführen.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- **Boot loading screen**: new branded loading experience that paints before the WASM bundle is ready and stays on screen until the workbench is mounted. `index.html` ships a static `#blx-static-boot` section (logo, eyebrow, faux workbench preview, animated rail) so the first paint happens immediately on Trunk-served HTML; once Leptos mounts, the static node is removed and `BootLoadingScreen` (`src/boot_loading.rs`) takes over with phased copy (`Starting BLXCode` → `Restoring workspace` → `Opening workbench`). 306 lines of dedicated CSS in `styles.css` add the radial-gradient backdrop, frame-enter / sheen / rail keyframes, and the sidebar/main/panel preview skeleton. The `App` boot fallback now renders `<BootLoadingScreen phase=app_boot_phase.get()/>` instead of the prior empty `app-shell--boot` div.
- **Agent question card (`harness.ask_user`)**: new client-side tool that lets the coordinator agent ask a clarifying multiple-choice question and receive the user's answer as a structured tool result. Backend registers `harness.ask_user` (`src-tauri/src/agent/tools.rs`) with a JSON schema accepting `question`, optional `header` (≤12 chars), 2–4 `options` (label + optional description), `multiSelect`, and `allowOther`; the tool sits in the `CoordinatorHarness` group (subagents excluded) and the system prompt instructs the model to use it only when 2–4 distinct options would unblock progress. Frontend adds a new `TimelineItem::AskUser` variant and `ask_user_card/` component (Angular-style folder with co-located CSS) rendering a chat bubble with numbered option buttons, single- or multi-select mode, an optional free-text “Other” field, and a cancel button; the card submits via `agent_submit_tool_result` and transitions the row state to `Answered { selected, other }` or `Cancelled` so the bubble stays visible with disabled controls. Persistence drops `Open` ask-user rows from the saved timeline (the awaiting backend loop is dead after reload). Tool-result payload: `{ "selected": [...], "other": "...", "cancelled": false }`; on cancel: `ok=false` + `{ "cancelled": true }`. 8 new i18n keys (`AgAskUser*`) added in `en_us.rs` and `de_de.rs`; other locales receive English placeholders pending a `render_i18n_locales_from_en.py` pass.
- **Centralized API Keys settings**: new **Settings → API Keys** pane (`src/workbench/api_keys_pane/`) replaces per-provider key inputs that previously lived under Settings → Agent. Backend module `src-tauri/src/api_keys.rs` exposes `api_keys_status` (catalog of LLM + search providers with masked values, env-var hints, and `comingSoon` placeholders for Google / Mistral / **Grok xAI**) and `api_keys_apply` (batch `set` / `delete` actions). Active keys still use the existing OS keyring accounts (`agent:*`, `agent:web:*`) with optional `BLX_*` env fallback; resolve order is keyring-first so UI-saved secrets are not overridden by shell env. The pane uses draft state, a single **Save** / **Discard** footer, row-level remove/undo, and shared `settings-field-card` / `api-keys-row` styling with brand icons (`public/brand-icons/`: OpenRouter, Anthropic, OpenAI, Google/Gemini, Mistral, Groq, Tavily, Brave). 15 new `ApiKeys*` i18n keys in all 13 locales.
- **Settings revamp (docked center tab)**: harness settings moved from a modal overlay into a **center workbench tab** (`SettingsDock` in `harness_ui.rs`). Sidebar categories: **App**, **Appearance** (stub), **API Keys**, **Workspace**, **BLXCode Agent**. Legacy `HarnessSettingsCategory` values (`Image`, `Voice`, `Memory`) still deserialize and route to the correct pane for older snapshots. Command palette / tmux chords open or focus a singleton settings tab per workspace.
- **Settings revamp (docked center tab)**: harness settings moved from a modal overlay into a **center workbench tab** (`SettingsDock` in `harness_ui.rs`). Sidebar categories: **App**, **Appearance**, **API Keys**, **Workspace**, **BLXCode Agent**. Legacy `HarnessSettingsCategory` values (`Image`, `Voice`, `Memory`) still deserialize and route to the correct pane for older snapshots. Command palette / tmux chords open or focus a singleton settings tab per workspace.
- **App theme system & Appearance tab**: twenty selectable themes (`blxcode-dark` default **BLXCode**, plus BLXCode Light, Dracula, Gruvbox, Solarized, Nord, One Dark, Catppuccin, Tokyo Night, **Rosé Pine**, **Rosé Pine Dawn**, **Everforest Dark**, **Kanagawa**, **GitHub Dark**, **Night Owl**, **Ayu Mirage**, **Catppuccin Frappé**) apply app-wide via `html[data-theme]` and `themes/tokens.css`. New `src/theme/` catalog + `ThemeService` (`src/workbench/theme_service.rs`, context in `src/app.rs`) persist the choice to `blxcode_theme_v1`, set `data-theme` synchronously, and dispatch `blxcode-theme-changed` for JS bridges. `index.html` runs an inline boot script before CSS load to prevent theme flash. **Settings → Appearance** (`src/workbench/appearance_settings_pane/`) ships a hero preview, search, All/Dark/Light filters, and preview cards with roomier card padding and title/description spacing; theme names/descriptions are fully i18n (`ThemeName*` / `ThemeDesc*` + UI chrome keys in all 13 locales). Terminals (`terminal_bootstrap.mjs`), Memory graph 2D/3D, agent-terminal accent borders, and component CSS consume the same tokens. Lint: `scripts/lint_theme_tokens.sh`; contributor rule `.agents/rules/rule-theme-tokens.md`; documented exceptions in `docs/THEME_EXCEPTIONS.md`.
- **BLXCode Agent settings pane**: `src/workbench/agent_provider_pane/` — responsive grid. **Text** (top-left): provider + **thinking level** pickers (`harness-level-picker` icons), muted `text-xs` API-key status line → Settings → API Keys, shared **`AgentModelPicker`** (catalog rows, pricing-only detail sub-row, custom model id, refresh). **Image** (top-right): `AgentImageColumn` in `harness_image_pane` — provider dropdown, **quality level** picker, `AgentModelPicker`, auto-save; **fal.ai** provider + key via API Keys catalog. **Voice** (bottom, full width): `AgentVoiceColumn` in `harness_voice_pane` — unified STT/TTS provider (OpenAI / OpenRouter / **AWS Polly**), `AgentModelPicker` for speech + TTS models, recording quality, behavior (post-STT flow, gender filter, fixed 6-voice catalog per provider, TTS autoplay). Web Tools below the grid (Tavily / Brave / disabled); one **Save** / **Discard** footer for text provider + web backend. Replaced standalone `model_picker/` with `agent_model_picker/`.
- **Voice in App settings**: STT language mode + push-to-talk hotkey moved to **Settings → App** (`voice_app_controls`); full voice provider/model/voice UI lives only under BLXCode Agent.
- **Workspace category colors**: former **Settings → Memory → Color presets** moved to **Settings → Workspace** section **Category colors** (`workspace_settings_pane/category_colors.rs`, `WsSectionCategoryColors` + related i18n). Same preset list/edit/add/reset backed by `memory_color_presets` in `WorkbenchService`.
Expand All @@ -25,13 +26,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed

- **`ChatUsageStats` schema migrated**: `total_cost_usd: f64` and `current_turn_generation: u64` added; legacy `ttft_sum_ms` / `ttft_sample_count` fields removed (TTFT now lives per-row). Older `workbench.json` snapshots deserialize cleanly thanks to `#[serde(default)]` and rewrite without the removed fields on next save. `record_chat_turn_usage` signature changed to accept the new `turn_generation` and `cost_usd` and to return `bool` so callers can drop stale events.
- **Global CSS tokenization for themes**: `styles.css` hardcoded colors replaced with semantic `var(--*)` tokens; `themes/tokens.css` loaded before `styles.css`. Component sheets (`ask_user_card`, `plans-panel`, `api_keys_pane`, `agent_provider_pane`, `update_dialog`, `sidebar_resizer`, `turn_metrics_bar`, `harness_image_pane`) no longer use literal fallbacks in `var()`. `scripts/tokenize_styles_css.py` heuristics no longer map `color:` properties to overlay tokens.
- **Appearance theme cards**: increased inner padding, grid gap, and title/description spacing; active checkmark uses semi-transparent accent fill.
- **Workspace settings layout aligned with API Keys**: the Workspace pane (`src/workbench/workspace_settings_pane/`) uses `harness-subpane` sections (**Paths & sandbox**, **Embedded browser**, **Category colors**), `api-keys-list` / `api-keys-row` field cards, and one footer **Save** / **Discard** for project directory, agent sandbox root, and embedded-browser URL. Category color edits apply immediately (same as former Memory tab). Shared footer/field CSS in `workspace_settings_pane.css` and `api_keys_pane.css`.
- **BLXCode Agent API-key hints**: relocation lines under Text / Image / Voice use `0.75rem` + `--text-muted` (`.agent-provider-pane__key-row`) instead of body-sized copy.
- **Voice catalog UX**: six fixed voices per provider (OpenAI + AWS Polly active; OpenRouter shows OpenAI set disabled with hint); gender filter always visible; disabled cards keep layout (no hide-on-disable).
- **Settings panel restructured**: `AppSettingsPane` (`src/workbench/harness_ui.rs`) now reads top-to-bottom as Language → Keyboard shortcuts → Notifications → **Terminal hooks** → **App updates** (updates moved below hooks to put install actions closer to the per-agent hook list). Keyboard shortcuts and Notifications switched from single-column lists to 2-column grids (new `.app-prefs-shortcut-modes--grid` and `.app-prefs-toggle-grid`). Current version no longer renders inside a readonly `<input>` — it's now a styled `<dl>` row, and a sibling **Available version** row only appears when `UpdateService::available_version` is `Some`. Terminal hooks list (`.harness-hooks__list--grid`) lays out as 3 columns on wide screens, collapsing to 2 / 1 below 900 px / 600 px; per-agent **status is icon-only** (check / X) with full text in `title` + `aria-label`, aligned to the end of the title row. The EULA status row was removed from the App pane (acceptance is still gated at boot; the field added no actionable signal here). Workspace pane changed the agent sandbox `<textarea>` to a single-line `<input>` and gained a new **Default project directory** field above it: persisted to `blxcode_default_project_dir_v1` via new `WorkbenchService::default_project_dir` signal + setters/persist, seeded from the user's home directory through a new `harness_user_home_dir` Tauri command (`src-tauri/src/commands.rs`) on first run. Inline workspace configuration (`start_inline_configure` and snapshot hydration) now prefills new workspace `cwd` from `default_project_dir`, falling back to the agent sandbox root only when blank — sandbox path is reserved for BLXCode Agent sandbox actions. New i18n keys `AppUpdateAvailableVersion`, `WsRootHint`, `WsDefaultProjectDirLabel/Placeholder/Hint` added across all 13 locale files (English authored; other locales carry English placeholders until `scripts/tools/render_i18n_locales_from_en.py` runs).

### Fixed

- **BLXCode theme color regression after tokenization**: bulk CSS tokenization had mapped many text labels (settings radio/checkbox copy, hints, hook badges) to `var(--overlay-2)`, making them nearly invisible on dark backgrounds; restored semantic text/control tokens (`--text-secondary`, `--text-hint`, `--accent-control`, `--success-surface`, `--hook-brand-*`) and fixed ~99 mis-mapped `color:` rules in `styles.css`.
- **`scripts/tools/render_i18n_locales_from_en.py`**: `GoogleTranslator.translate()` returning `None` (recent `deep-translator` behaviour for short tokens like `"in"`, `"out"`, `"ttft"` and the bare `"—"` glyph) was cached and later crashed `rust_escape` with `TypeError: 'NoneType' object is not iterable`. The script now treats empty / `None` responses as "no translation available" and falls back to the source string; `emit_locale_rs` hard-fails with a readable `SystemExit` if a `None` still slips through.

### Removed
Expand Down
Loading
Loading