mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-15 06:04:40 +00:00
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:
parent
7b347291ff
commit
bc670bc63c
17 changed files with 1721 additions and 186 deletions
310
packages/coding-agent/docs/themes.md
Normal file
310
packages/coding-agent/docs/themes.md
Normal 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
|
||||
Loading…
Add table
Add a link
Reference in a new issue