Skip to content

Commit 544ac4e

Browse files
committed
fix: invalidate assistant Markdown instances on theme change (Codex review)
The pi-tui Markdown component caches rendered output by text+width and caches the defaultStylePrefix for its entire lifetime. After a theme switch, existing AssistantMessageComponent instances held stale ANSI colors because the Markdown child was never rebuilt. - Add ThemeAwareComponent interface + isThemeAware type guard to component-capabilities.ts following the existing Expandable pattern - Add AssistantMessageComponent.applyTheme() that rebuilds the Markdown child with the new markdownTheme and defaultTextStyle - Wire KimiTUI.applyTheme() to iterate transcript children and call applyTheme() on any theme-aware component
1 parent 7a4c80e commit 544ac4e

3 files changed

Lines changed: 35 additions & 1 deletion

File tree

‎apps/kimi-code/src/tui/components/messages/assistant-message.ts‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,18 @@ export class AssistantMessageComponent implements Component {
3131
this.showBullet = show;
3232
}
3333

34+
applyTheme(markdownTheme: MarkdownTheme, colors: ColorPalette): void {
35+
this.markdownTheme = markdownTheme;
36+
this.bulletColor = colors.roleAssistant;
37+
this.defaultTextStyle = { color: (text) => chalk.hex(colors.text)(text) };
38+
if (this.lastText) {
39+
this.contentContainer.clear();
40+
this.contentContainer.addChild(
41+
new Markdown(this.lastText.trim(), 0, 0, this.markdownTheme, this.defaultTextStyle),
42+
);
43+
}
44+
}
45+
3446
updateContent(text: string): void {
3547
const displayText = text;
3648
if (displayText === this.lastText) return;

‎apps/kimi-code/src/tui/kimi-tui.ts‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ import {
112112
type TUIStartupState,
113113
} from './types';
114114
import { createTUIState, type TUIState } from './tui-state';
115-
import { isExpandable, isPlanExpandable } from './utils/component-capabilities';
115+
import { isExpandable, isPlanExpandable, isThemeAware } from './utils/component-capabilities';
116116
import { isDeadTerminalError } from './utils/dead-terminal';
117117
import { formatErrorMessage } from './utils/event-payload';
118118
import { ImageAttachmentStore, type ImageAttachment } from './utils/image-attachment-store';
@@ -1563,6 +1563,11 @@ export class KimiTUI {
15631563
this.state.theme.styles = nextTheme.styles;
15641564
this.state.theme.markdownTheme = nextTheme.markdownTheme;
15651565
this.setAppState({ theme });
1566+
for (const child of this.state.transcriptContainer.children) {
1567+
if (isThemeAware(child)) {
1568+
child.applyTheme(this.state.theme.markdownTheme, this.state.theme.colors);
1569+
}
1570+
}
15661571
this.updateEditorBorderHighlight();
15671572
this.state.ui.requestRender(true);
15681573
}

‎apps/kimi-code/src/tui/utils/component-capabilities.ts‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
import type { MarkdownTheme } from '@earendil-works/pi-tui';
2+
3+
import type { ColorPalette } from '#/tui/theme/colors';
4+
15
export interface Expandable {
26
setExpanded(expanded: boolean): void;
37
}
@@ -12,6 +16,19 @@ export interface Disposable {
1216
dispose(): void;
1317
}
1418

19+
export interface ThemeAwareComponent {
20+
applyTheme(markdownTheme: MarkdownTheme, colors: ColorPalette): void;
21+
}
22+
23+
export function isThemeAware(obj: unknown): obj is ThemeAwareComponent {
24+
return (
25+
typeof obj === 'object' &&
26+
obj !== null &&
27+
'applyTheme' in obj &&
28+
typeof (obj as ThemeAwareComponent).applyTheme === 'function'
29+
);
30+
}
31+
1532
export function isExpandable(obj: unknown): obj is Expandable {
1633
return (
1734
typeof obj === 'object' &&

0 commit comments

Comments
 (0)