Fix lockstep versioning and improve documentation

- Sync all packages to version 0.7.7
- Rewrite sync-versions.js to handle ALL inter-package dependencies automatically
- Fix web-ui dependency on pi-ai (was 0.6.0, now 0.7.7)
- Move agent fix changelog entry to coding-agent CHANGELOG
- Remove redundant agent CHANGELOG.md
- Improve README.md with clearer lockstep versioning docs
- Add /changelog command to display full changelog in TUI (newest last)
- Fix changelog description (not a scrollable viewer, just displays in chat)
- Update CHANGELOG for 0.7.7 release
This commit is contained in:
Mario Zechner 2025-11-13 23:37:43 +01:00
parent 7b347291ff
commit bc670bc63c
17 changed files with 1721 additions and 186 deletions

View file

@ -0,0 +1,310 @@
# Theme System Analysis
## Problem Statement
Issue #7: In terminals with light backgrounds, some outputs use dark colors that are hard to read. We need a theme system that allows users to choose between light and dark themes.
## Current Color Usage Analysis
### Color Usage Statistics
Total chalk color calls: 132 across 14 files
Most frequent colors:
- `chalk.dim` (48 occurrences) - Used for secondary text
- `chalk.gray` (28 occurrences) - Used for borders, metadata, dimmed content
- `chalk.bold` (20 occurrences) - Used for emphasis
- `chalk.blue` (12 occurrences) - Used for selections, borders, links
- `chalk.cyan` (9 occurrences) - Used for primary UI elements (logo, list bullets, code)
- `chalk.red` (7 occurrences) - Used for errors, stderr output
- `chalk.green` (6 occurrences) - Used for success, stdout output
- `chalk.yellow` (3 occurrences) - Used for headings in markdown
- `chalk.bgRgb` (6 occurrences) - Used for custom backgrounds in Text/Markdown
### Files Using Colors
#### coding-agent Package
1. **main.ts** - CLI output messages
2. **tui/assistant-message.ts** - Thinking text (gray italic), errors (red), aborted (red)
3. **tui/dynamic-border.ts** - Configurable border color (default blue)
4. **tui/footer.ts** - Stats and pwd (gray)
5. **tui/model-selector.ts** - Borders (blue), selection arrow (blue), provider badge (gray), checkmark (green)
6. **tui/session-selector.ts** - Border (blue), selection cursor (blue), metadata (dim)
7. **tui/thinking-selector.ts** - Border (blue)
8. **tui/tool-execution.ts** - stdout (green), stderr (red), dim lines (dim), line numbers
9. **tui/tui-renderer.ts** - Logo (bold cyan), instructions (dim/gray)
#### tui Package
1. **components/editor.ts** - Horizontal border (gray)
2. **components/loader.ts** - Spinner (cyan), message (dim)
3. **components/markdown.ts** - Complex color system:
- H1 headings: bold.underline.yellow
- H2 headings: bold.yellow
- H3+ headings: bold
- Code blocks: gray (delimiters), dim (indent), green (code)
- List bullets: cyan
- Blockquotes: gray (pipe), italic (text)
- Horizontal rules: gray
- Inline code: gray (backticks), cyan (code)
- Links: underline.blue (text), gray (URL)
- Strikethrough: strikethrough
- Tables: bold (headers)
4. **components/select-list.ts** - No matches (gray), selection arrow (blue), selected item (blue), description (gray)
5. **components/text.ts** - Custom bgRgb support
### Color System Architecture
#### Current Implementation
- Colors are hardcoded using `chalk` directly
- No centralized theme management
- No way to switch themes at runtime
- Some components accept color parameters (e.g., DynamicBorder, Text, Markdown)
#### Markdown Component Color System
The Markdown component has a `Color` type enum:
```typescript
type Color = "black" | "red" | "green" | "yellow" | "blue" | "magenta" | "cyan" | "white" | "gray" |
"bgBlack" | "bgRed" | "bgGreen" | "bgYellow" | "bgBlue" | "bgMagenta" | "bgCyan" | "bgWhite" | "bgGray"
```
It accepts optional `bgColor` and `fgColor` parameters, plus `customBgRgb`.
## Proposed Solution
### Theme Structure
Create a centralized theme system with semantic color names:
```typescript
interface Theme {
name: string;
// UI Chrome
border: ChalkFunction;
selection: ChalkFunction;
selectionText: ChalkFunction;
// Text hierarchy
primary: ChalkFunction;
secondary: ChalkFunction;
dim: ChalkFunction;
// Semantic colors
error: ChalkFunction;
success: ChalkFunction;
warning: ChalkFunction;
info: ChalkFunction;
// Code/output
code: ChalkFunction;
codeDelimiter: ChalkFunction;
stdout: ChalkFunction;
stderr: ChalkFunction;
// Markdown specific
heading1: ChalkFunction;
heading2: ChalkFunction;
heading3: ChalkFunction;
link: ChalkFunction;
linkUrl: ChalkFunction;
listBullet: ChalkFunction;
blockquote: ChalkFunction;
blockquotePipe: ChalkFunction;
inlineCode: ChalkFunction;
inlineCodeDelimiter: ChalkFunction;
// Backgrounds (optional, for components like Text/Markdown)
backgroundRgb?: { r: number; g: number; b: number };
}
type ChalkFunction = (str: string) => string;
```
### Built-in Themes
#### Dark Theme (current default)
```typescript
const darkTheme: Theme = {
name: "dark",
border: chalk.blue,
selection: chalk.blue,
selectionText: chalk.blue,
primary: (s) => s, // no color
secondary: chalk.gray,
dim: chalk.dim,
error: chalk.red,
success: chalk.green,
warning: chalk.yellow,
info: chalk.cyan,
code: chalk.green,
codeDelimiter: chalk.gray,
stdout: chalk.green,
stderr: chalk.red,
heading1: chalk.bold.underline.yellow,
heading2: chalk.bold.yellow,
heading3: chalk.bold,
link: chalk.underline.blue,
linkUrl: chalk.gray,
listBullet: chalk.cyan,
blockquote: chalk.italic,
blockquotePipe: chalk.gray,
inlineCode: chalk.cyan,
inlineCodeDelimiter: chalk.gray,
};
```
#### Light Theme
```typescript
const lightTheme: Theme = {
name: "light",
border: chalk.blue,
selection: chalk.blue,
selectionText: chalk.blue.bold,
primary: (s) => s,
secondary: chalk.gray,
dim: chalk.gray, // Don't use chalk.dim on light backgrounds
error: chalk.red.bold,
success: chalk.green.bold,
warning: chalk.yellow.bold,
info: chalk.cyan.bold,
code: chalk.green.bold,
codeDelimiter: chalk.gray,
stdout: chalk.green.bold,
stderr: chalk.red.bold,
heading1: chalk.bold.underline.blue,
heading2: chalk.bold.blue,
heading3: chalk.bold,
link: chalk.underline.blue,
linkUrl: chalk.blue,
listBullet: chalk.blue.bold,
blockquote: chalk.italic,
blockquotePipe: chalk.gray,
inlineCode: chalk.blue.bold,
inlineCodeDelimiter: chalk.gray,
};
```
### Implementation Plan
#### 1. Create Theme Module
**Location:** `packages/tui/src/theme.ts`
```typescript
export interface Theme { ... }
export const darkTheme: Theme = { ... };
export const lightTheme: Theme = { ... };
export const themes = { dark: darkTheme, light: lightTheme };
let currentTheme: Theme = darkTheme;
export function setTheme(theme: Theme): void {
currentTheme = theme;
}
export function getTheme(): Theme {
return currentTheme;
}
```
#### 2. Update Settings Manager
**Location:** `packages/coding-agent/src/settings-manager.ts`
Add `theme` field to Settings interface:
```typescript
export interface Settings {
lastChangelogVersion?: string;
theme?: "dark" | "light";
}
```
#### 3. Create Theme Selector Component
**Location:** `packages/coding-agent/src/tui/theme-selector.ts`
Similar to ModelSelector and ThinkingSelector, create a TUI component for selecting themes.
#### 4. Refactor Color Usage
Replace all hardcoded `chalk.*` calls with `theme.*`:
**Example - Before:**
```typescript
lines.push(chalk.blue("─".repeat(width)));
const cursor = chalk.blue(" ");
```
**Example - After:**
```typescript
const theme = getTheme();
lines.push(theme.border("─".repeat(width)));
const cursor = theme.selection(" ");
```
#### 5. Update Components
##### High Priority (User-facing content issues)
1. **markdown.ts** - Update all color calls to use theme
2. **tool-execution.ts** - stdout/stderr colors
3. **assistant-message.ts** - Error messages
4. **tui-renderer.ts** - Logo and instructions
5. **footer.ts** - Stats display
##### Medium Priority (UI chrome)
6. **dynamic-border.ts** - Accept theme parameter
7. **model-selector.ts** - Selection colors
8. **session-selector.ts** - Selection colors
9. **thinking-selector.ts** - Border colors
10. **select-list.ts** - Selection colors
11. **loader.ts** - Spinner color
12. **editor.ts** - Border color
##### Low Priority (CLI output)
13. **main.ts** - CLI messages
#### 6. Add Theme Slash Command
**Location:** `packages/coding-agent/src/tui/tui-renderer.ts`
Add `/theme` command similar to `/model` and `/thinking`.
#### 7. Initialize Theme on Startup
**Location:** `packages/coding-agent/src/main.ts`
```typescript
// Load theme from settings
const settingsManager = new SettingsManager();
const themeName = settingsManager.getTheme() || "dark";
const theme = themes[themeName] || darkTheme;
setTheme(theme);
```
### Migration Strategy
1. **Phase 1:** Create theme infrastructure (theme.ts, types, built-in themes)
2. **Phase 2:** Update TUI package components (markdown, text, loader, editor, select-list)
3. **Phase 3:** Update coding-agent TUI components (all tui/*.ts files)
4. **Phase 4:** Add theme selector and persistence
5. **Phase 5:** Update CLI output in main.ts (optional, low priority)
### Testing Plan
1. Test both themes in terminals with light backgrounds
2. Test both themes in terminals with dark backgrounds
3. Verify theme switching works at runtime via `/theme`
4. Verify theme persists across sessions via settings.json
5. Test all components for readability in both themes
### Open Questions
1. Should we support custom user themes loaded from a JSON file?
2. Should we auto-detect terminal background color and choose theme automatically?
3. Should theme apply to background colors used in Text/Markdown components?
4. Do we need more than two themes initially?
### Breaking Changes
None - the default theme will remain "dark" matching current behavior.
### Performance Considerations
- Theme getter is called frequently (on every render)
- Should be a simple variable access, not a function call chain
- Consider caching theme functions if performance becomes an issue