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 README.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,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
- 13 themes: `dark`, `light`, `dracula`, `nord`, `ayu`, `catppuccin`, `gruvbox`, `neon`, `synthwave`, `ember`, `matrix`, `cobalt`, `midnight` (`/theme`)
- 14 themes: `dark`, `light`, `dracula`, `nord`, `ayu`, `catppuccin`, `gruvbox`, `neon`, `synthwave`, `ember`, `matrix`, `cobalt`, `midnight`, `tokyo-night` (`/theme`)
- 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
Binary file added assets/tokyo-night-theme.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/auth/credentials.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export interface Credentials {
export interface Config {
baseUrl: string; // KlaatAI API base URL
routingDisplay: "minimal" | "full" | "off";
theme: string; // Theme name: dark | light | dracula | nord | ayu | catppuccin | gruvbox
theme: string; // Theme name from THEME_NAMES (for example dark, light, tokyo-night)
vimMode: boolean; // Vim-style key bindings in the input field
/**
* Disable TLS certificate verification (corporate MITM proxies whose root
Expand Down
42 changes: 42 additions & 0 deletions src/engine/theme.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { describe, expect, test } from "bun:test";
import {
THEME_DESCRIPTIONS,
THEME_NAMES,
TOKYO_NIGHT_PALETTE,
getPalette,
} from "./theme.js";

describe("Tokyo Night theme", () => {
test("is registered with its description and palette", () => {
expect(THEME_NAMES).toContain("tokyo-night");
expect(THEME_DESCRIPTIONS["tokyo-night"]).toContain("Tokyo Night");
expect(getPalette("tokyo-night")).toBe(TOKYO_NIGHT_PALETTE);
});

test("uses valid 256-color slots", () => {
const numericSlots = Object.values(TOKYO_NIGHT_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", () => {
const hexSlots = [
TOKYO_NIGHT_PALETTE.accent,
TOKYO_NIGHT_PALETTE.dimText,
TOKYO_NIGHT_PALETTE.userColor,
TOKYO_NIGHT_PALETTE.border,
TOKYO_NIGHT_PALETTE.thumb,
];

for (const color of hexSlots) {
expect(color).toMatch(/^#[0-9a-f]{6}$/i);
}
expect(TOKYO_NIGHT_PALETTE.bg).toBeNull();
});
});
29 changes: 26 additions & 3 deletions src/engine/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,27 @@ export const MIDNIGHT_PALETTE: ThemePalette = {
assistantFg: 117, // sky blue
};

/** Tokyo Night — deep navy with cool blue and green accents */
export const TOKYO_NIGHT_PALETTE: ThemePalette = {
accent: "#7aa2f7", // blue
dimText: "#7f87b2", // dark foreground
userColor: "#9ece6a", // green
border: "#3b4261", // terminal black
thumb: "#545c7e",
bg: null,
inputBg: 234,
chatFg: 189, // pale blue-white
mutedFg: 103, // muted lavender-blue
toolFg: 110, // cyan-blue
codeFg: 111, // bright blue
codeBg: 235,
headingFg: "white",
sidebarLabel: 103,
sidebarValue: 189,
userFg: 149, // green
assistantFg: 111, // blue
};

export type Theme =
| "dark"
| "light"
Expand All @@ -341,11 +362,12 @@ export type Theme =
| "ember"
| "matrix"
| "cobalt"
| "midnight";
| "midnight"
| "tokyo-night";

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

export const THEME_DESCRIPTIONS: Record<Theme, string> = {
Expand All @@ -362,6 +384,7 @@ export const THEME_DESCRIPTIONS: Record<Theme, string> = {
matrix: "Matrix — green phosphor terminal aesthetic",
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",
};

export function getPalette(theme: Theme): ThemePalette {
Expand All @@ -378,6 +401,7 @@ export function getPalette(theme: Theme): ThemePalette {
case "matrix": return MATRIX_PALETTE;
case "cobalt": return COBALT_PALETTE;
case "midnight": return MIDNIGHT_PALETTE;
case "tokyo-night": return TOKYO_NIGHT_PALETTE;
default: return DARK_PALETTE;
}
}
Expand Down Expand Up @@ -446,4 +470,3 @@ export async function detectTheme(): Promise<Theme> {
timer = setTimeout(() => finish("dark"), 200);
});
}

Loading