Skip to content
Open
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 README.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ Markdown responses render with per-language syntax highlighting directly in the
- Slash-command autocomplete — type `/` for a fuzzy-filtered live suggestion strip
- Collapsible tool output and thinking blocks — click to expand
- Full mouse support: click, scroll, drag-select
- 14 themes: `dark`, `light`, `dracula`, `nord`, `ayu`, `catppuccin`, `gruvbox`, `neon`, `synthwave`, `ember`, `matrix`, `cobalt`, `midnight`, `tokyo-night` (`/theme`)
- Themes via `/theme`: `dark`, `light`, `dracula`, `nord`, `ayu`, `catppuccin` (+ latte/frappe/macchiato), `gruvbox`, `neon`, `synthwave`, `ember`, `matrix`, `cobalt`, `midnight`, `tokyo-night`, `rose-pine`
- Vim keybindings (`/vimmode on`)
- Sidebar: usage, context window fill, MCP servers, routing analytics
- Diffs render as colored, syntax-highlighted unified-diff blocks — including multi-file patches
Expand Down
34 changes: 34 additions & 0 deletions src/engine/theme.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
THEME_DESCRIPTIONS,
THEME_NAMES,
TOKYO_NIGHT_PALETTE,
ROSE_PINE_PALETTE,
getPalette,
} from "./theme.js";

Expand Down Expand Up @@ -40,3 +41,36 @@ describe("Tokyo Night theme", () => {
expect(TOKYO_NIGHT_PALETTE.bg).toBeNull();
});
});

describe("Rosé Pine theme", () => {
test("is registered with its description and palette", () => {
expect(THEME_NAMES).toContain("rose-pine");
expect(THEME_DESCRIPTIONS["rose-pine"]).toContain("Rosé Pine");
expect(getPalette("rose-pine")).toBe(ROSE_PINE_PALETTE);
});

test("uses valid 256-color slots", () => {
const numericSlots = Object.values(ROSE_PINE_PALETTE)
.filter((value): value is number => typeof value === "number");

expect(numericSlots.length).toBeGreaterThan(0);
for (const color of numericSlots) {
expect(Number.isInteger(color)).toBe(true);
expect(color).toBeGreaterThanOrEqual(0);
expect(color).toBeLessThanOrEqual(255);
}
});

test("uses supported hex colors and the terminal background", () => {
for (const color of [
ROSE_PINE_PALETTE.accent,
ROSE_PINE_PALETTE.dimText,
ROSE_PINE_PALETTE.userColor,
ROSE_PINE_PALETTE.border,
ROSE_PINE_PALETTE.thumb,
]) {
expect(color).toMatch(/^#[0-9a-f]{6}$/i);
}
expect(ROSE_PINE_PALETTE.bg).toBeNull();
});
});
27 changes: 26 additions & 1 deletion src/engine/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,27 @@ export const TOKYO_NIGHT_PALETTE: ThemePalette = {
assistantFg: 111, // blue
};

/** Rosé Pine — warm muted purple with rose & pine accents */
export const ROSE_PINE_PALETTE: ThemePalette = {
accent: "#c4a7e7", // iris
dimText: "#6e6a86", // muted
userColor: "#ebbcba", // rose
border: "#26233a", // overlay
thumb: "#403d52",
bg: null,
inputBg: 235,
chatFg: 189, // soft lavender-white (text)
mutedFg: 103, // muted
toolFg: 245,
codeFg: 152, // foam / soft teal
codeBg: 236,
headingFg: "white",
sidebarLabel: 103,
sidebarValue: 189,
userFg: 217, // rose
assistantFg: 183, // iris
};

export type Theme =
| "dark"
| "light"
Expand All @@ -428,12 +449,14 @@ export type Theme =
| "matrix"
| "cobalt"
| "midnight"
| "tokyo-night";
| "tokyo-night"
| "rose-pine";

export const THEME_NAMES: Theme[] = [
"dark", "light", "dracula", "nord", "ayu",
"catppuccin", "catppuccin-latte", "catppuccin-frappe", "catppuccin-macchiato",
"gruvbox", "neon", "synthwave", "ember", "matrix", "cobalt", "midnight", "tokyo-night",
"rose-pine",
];

export const THEME_DESCRIPTIONS: Record<Theme, string> = {
Expand All @@ -454,6 +477,7 @@ export const THEME_DESCRIPTIONS: Record<Theme, string> = {
cobalt: "Cobalt — deep blue with golden highlights",
midnight: "Midnight — indigo depths with sky blue & lavender",
"tokyo-night": "Tokyo Night — deep navy with cool blue & green",
"rose-pine": "Rosé Pine — warm muted purple with rose & pine",
};

export function getPalette(theme: Theme): ThemePalette {
Expand All @@ -474,6 +498,7 @@ export function getPalette(theme: Theme): ThemePalette {
case "cobalt": return COBALT_PALETTE;
case "midnight": return MIDNIGHT_PALETTE;
case "tokyo-night": return TOKYO_NIGHT_PALETTE;
case "rose-pine": return ROSE_PINE_PALETTE;
default: return DARK_PALETTE;
}
}
Expand Down
Loading