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
5 changes: 5 additions & 0 deletions .changeset/full-plan-card.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@moonshot-ai/kimi-code": patch
---

Show full plan cards directly and remove the Plan card keyboard shortcut.
5 changes: 0 additions & 5 deletions apps/kimi-code/src/tui/components/dialogs/approval-panel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,6 @@ export class ApprovalPanelComponent extends Container implements Focusable {
private request: PendingApproval;
private readonly colors: ColorPalette;
private readonly onToggleToolOutput: (() => void) | undefined;
private readonly onTogglePlanExpand: (() => void) | undefined;
private readonly onOpenPreview:
| ((block: DiffDisplayBlock | FileContentDisplayBlock) => void)
| undefined;
Expand All @@ -227,15 +226,13 @@ export class ApprovalPanelComponent extends Container implements Focusable {
onResponse: (response: ApprovalPanelResponse) => void,
colors: ColorPalette,
onToggleToolOutput?: () => void,
onTogglePlanExpand?: () => void,
onOpenPreview?: (block: DiffDisplayBlock | FileContentDisplayBlock) => void,
) {
super();
this.request = request;
this.onResponse = onResponse;
this.colors = colors;
this.onToggleToolOutput = onToggleToolOutput;
this.onTogglePlanExpand = onTogglePlanExpand;
this.onOpenPreview = onOpenPreview;
this.feedbackInput.onSubmit = (value) => {
this.submit(this.selectedIndex, value);
Expand Down Expand Up @@ -281,8 +278,6 @@ export class ApprovalPanelComponent extends Container implements Focusable {
const previewable = this.findPreviewableBlock();
if (previewable !== undefined && this.onOpenPreview !== undefined) {
this.onOpenPreview(previewable);
} else {
this.onTogglePlanExpand?.();
}
return;
}
Expand Down
8 changes: 0 additions & 8 deletions apps/kimi-code/src/tui/components/dialogs/question-dialog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,23 +99,20 @@ export class QuestionDialogComponent extends Container implements Focusable {
private readonly answers: (string | undefined)[];

private readonly onToggleToolOutput: (() => void) | undefined;
private readonly onTogglePlanExpand: (() => void) | undefined;

constructor(
request: PendingQuestion,
onAnswer: (response: QuestionPanelResponse) => void,
colors: ColorPalette,
maxVisibleOptions = 6,
onToggleToolOutput?: () => void,
onTogglePlanExpand?: () => void,
) {
super();
this.request = request;
this.onAnswer = onAnswer;
this.colors = colors;
this.maxVisibleOptions = maxVisibleOptions;
this.onToggleToolOutput = onToggleToolOutput;
this.onTogglePlanExpand = onTogglePlanExpand;
this.otherInput.onSubmit = (value) => {
this.commitOtherInput(value, 'enter');
};
Expand Down Expand Up @@ -147,11 +144,6 @@ export class QuestionDialogComponent extends Container implements Focusable {
return;
}

if (matchesKey(data, Key.ctrl('e'))) {
this.onTogglePlanExpand?.();
return;
}

if (this.isEditingOther()) {
this.handleOtherInput(data);
return;
Expand Down
9 changes: 0 additions & 9 deletions apps/kimi-code/src/tui/components/editor/custom-editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,6 @@ export class CustomEditor extends Editor {
public onCtrlD?: () => void;
public onCtrlC?: () => void;
public onToggleToolExpand?: () => void;
// Returns true when a plan card actually handled the toggle. When it
// returns false (no plan in the transcript) the keystroke falls through
// to pi-tui's default ctrl+e binding (move cursor to end of line).
public onTogglePlanExpand?: () => boolean;
public onOpenExternalEditor?: () => void;
public onCtrlS?: () => void;
public onUndo?: () => void;
Expand Down Expand Up @@ -292,11 +288,6 @@ export class CustomEditor extends Editor {
return;
}

if (matchesKey(normalized, Key.ctrl('e'))) {
if (this.onTogglePlanExpand?.() === true) return;
// No plan to toggle — fall through to pi-tui's end-of-line.
}

if (matchesKey(normalized, Key.ctrl('s'))) {
this.onCtrlS?.();
return;
Expand Down
25 changes: 1 addition & 24 deletions apps/kimi-code/src/tui/components/messages/plan-box.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ const TITLE_PREFIX = ' plan: ';
const TITLE_SUFFIX = ' ';

export interface PlanBoxOptions {
maxContentLines?: number;
expanded?: boolean;
status?: {
readonly label: string;
readonly colorHex: string;
Expand All @@ -29,8 +27,6 @@ export interface PlanBoxOptions {

export class PlanBoxComponent implements Component {
private readonly markdown: Markdown;
private readonly maxContentLines: number | undefined;
private readonly expanded: boolean;
private readonly status: PlanBoxOptions['status'];
private cachedWidth: number | undefined;
private cachedLines: string[] | undefined;
Expand All @@ -47,8 +43,6 @@ export class PlanBoxComponent implements Component {
// instance means repeated render() calls from the parent Container
// hit the cache instead of re-parsing on every frame.
this.markdown = new Markdown(plan.trim(), 0, 0, markdownTheme);
this.maxContentLines = opts?.maxContentLines;
this.expanded = opts?.expanded ?? false;
this.status = opts?.status;
}

Expand Down Expand Up @@ -81,36 +75,19 @@ export class PlanBoxComponent implements Component {
const bottom = indent + paint('└' + '─'.repeat(horzLen) + '┘');

const rawLines = this.markdown.render(contentWidth);
const { shown, hiddenCount } = this.capContentLines(rawLines);

const lines: string[] = [top];
for (const raw of shown) {
for (const raw of rawLines) {
const pad = Math.max(0, contentWidth - visibleWidth(raw));
lines.push(indent + paint('│') + ' ' + raw + ' '.repeat(pad) + ' ' + paint('│'));
}
if (hiddenCount > 0) {
const footer = chalk.dim(
`... (${String(hiddenCount)} more line${hiddenCount === 1 ? '' : 's'}, ctrl+e to expand)`,
);
const pad = Math.max(0, contentWidth - visibleWidth(footer));
lines.push(indent + paint('│') + ' ' + footer + ' '.repeat(pad) + ' ' + paint('│'));
}
lines.push(bottom);

this.cachedWidth = width;
this.cachedLines = lines;
return lines;
}

private capContentLines(rawLines: string[]): { shown: string[]; hiddenCount: number } {
const cap = this.maxContentLines;
if (this.expanded || cap === undefined || rawLines.length <= cap) {
return { shown: rawLines, hiddenCount: 0 };
}
const shownCount = Math.max(0, cap - 1);
return { shown: rawLines.slice(0, shownCount), hiddenCount: rawLines.length - shownCount };
}

private buildTitle(horzLen: number): string {
const fallback = ' plan ';
const statusSuffix = this.buildStatusSuffix();
Expand Down
20 changes: 0 additions & 20 deletions apps/kimi-code/src/tui/components/messages/tool-call.ts
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,6 @@ class PrefixedWrappedLine implements Component {

export class ToolCallComponent extends Container {
private expanded = false;
private planExpanded = false;
private toolCall: ToolCallBlockData;
private result: ToolResultBlockData | undefined;
private colors: ColorPalette;
Expand Down Expand Up @@ -592,17 +591,6 @@ export class ToolCallComponent extends Container {
this.rebuildBody();
}

// Toggle the plan box's expanded state independently from tool-output
// expansion. Returns true iff this card actually owns a plan preview
// (ExitPlanMode), so the caller can decide whether to consume the keystroke.
setPlanExpanded(expanded: boolean): boolean {
if (this.toolCall.name !== 'ExitPlanMode') return false;
if (this.planExpanded === expanded) return true;
this.planExpanded = expanded;
this.rebuildBody();
return true;
}

setResult(result: ToolResultBlockData): void {
this.result = result;
// Result supersedes any live progress chatter; the result body is the
Expand Down Expand Up @@ -1740,8 +1728,6 @@ export class ToolCallComponent extends Container {
if (this.markdownTheme !== undefined) {
this.addChild(
new PlanBoxComponent(plan, this.markdownTheme, this.colors.success, path, {
maxContentLines: this.computePlanBoxMaxContentLines(),
expanded: this.planExpanded,
status: this.resolvePlanBoxStatus(),
}),
);
Expand All @@ -1750,12 +1736,6 @@ export class ToolCallComponent extends Container {
}
}

private computePlanBoxMaxContentLines(): number | undefined {
const rows = this.ui?.terminal.rows;
if (rows === undefined || !Number.isFinite(rows) || rows <= 0) return undefined;
return Math.max(8, Math.floor(rows * 0.6) - 4);
}

private resolvePlanForPreview(): string {
const inlinePlan = str(this.toolCall.args['plan']);
if (inlinePlan.length > 0) return inlinePlan;
Expand Down
3 changes: 0 additions & 3 deletions apps/kimi-code/src/tui/controllers/editor-keyboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ export interface EditorKeyboardHost {
updateEditorBorderHighlight(text?: string): void;
updateQueueDisplay(): void;
toggleToolOutputExpansion(): void;
togglePlanExpansion(): boolean;
hideSessionPicker(): void;
stop(exitCode?: number): Promise<void>;
handlePlanToggle(next: boolean): void;
Expand Down Expand Up @@ -150,8 +149,6 @@ export class EditorKeyboardController {
host.toggleToolOutputExpansion();
};

editor.onTogglePlanExpand = () => host.togglePlanExpansion();

editor.onCtrlS = () => {
if (host.state.appState.streamingPhase === 'idle' || host.state.appState.isCompacting) return;
const text = editor.getText().trim();
Expand Down
2 changes: 0 additions & 2 deletions apps/kimi-code/src/tui/controllers/streaming-ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -617,7 +617,6 @@ export class StreamingUIController {
state.appState.workDir,
);
if (state.toolOutputExpanded) tc.setExpanded(true);
if (state.planExpanded) tc.setPlanExpanded(true);
this._pendingToolComponents.set(toolCall.id, tc);

if (toolCall.name !== 'Agent') this._pendingAgentGroup = null;
Expand Down Expand Up @@ -664,7 +663,6 @@ export class StreamingUIController {
state.appState.workDir,
);
if (state.toolOutputExpanded) completed.setExpanded(true);
if (state.planExpanded) completed.setPlanExpanded(true);
state.transcriptContainer.addChild(completed);
state.ui.requestRender();
}
Expand Down
24 changes: 1 addition & 23 deletions apps/kimi-code/src/tui/kimi-tui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ import {
type TUIStartupState,
} from './types';
import { createTUIState, type TUIState } from './tui-state';
import { isExpandable, isPlanExpandable } from './utils/component-capabilities';
import { isExpandable } from './utils/component-capabilities';
import { isDeadTerminalError } from './utils/dead-terminal';
import { formatErrorMessage } from './utils/event-payload';
import { ImageAttachmentStore, type ImageAttachment } from './utils/image-attachment-store';
Expand Down Expand Up @@ -1313,7 +1313,6 @@ export class KimiTUI {
this.state.appState.workDir,
);
if (this.state.toolOutputExpanded) tc.setExpanded(true);
if (this.state.planExpanded) tc.setPlanExpanded(true);
return tc;
}
if (entry.backgroundAgentStatus !== undefined) {
Expand Down Expand Up @@ -1589,21 +1588,6 @@ export class KimiTUI {
this.state.ui.requestRender();
}

// Returns true when at least one card toggled, so the caller can consume the keystroke.
togglePlanExpansion(): boolean {
const next = !this.state.planExpanded;
let toggled = false;
for (const child of this.state.transcriptContainer.children) {
if (isPlanExpandable(child) && child.setPlanExpanded(next)) {
toggled = true;
}
}
if (!toggled) return false;
this.state.planExpanded = next;
this.state.ui.requestRender();
return true;
}

updateEditorBorderHighlight(text?: string): void {
const trimmed = (text ?? this.state.editor.getText()).trimStart();
const highlighted = this.state.appState.planMode || trimmed.startsWith('/');
Expand Down Expand Up @@ -1832,9 +1816,6 @@ export class KimiTUI {
() => {
this.toggleToolOutputExpansion();
},
() => {
this.togglePlanExpansion();
},
(block) => {
this.openApprovalPreview(panel, block);
},
Expand Down Expand Up @@ -1905,9 +1886,6 @@ export class KimiTUI {
() => {
this.toggleToolOutputExpansion();
},
() => {
this.togglePlanExpansion();
},
);
this.mountEditorReplacement(dialog);
}
Expand Down
2 changes: 0 additions & 2 deletions apps/kimi-code/src/tui/tui-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ export interface TUIState {
terminalState: TerminalState;
activitySpinner: { instance: MoonLoader; style: SpinnerStyle } | null;
toolOutputExpanded: boolean;
planExpanded: boolean;
sessions: SessionRow[];
loadingSessions: boolean;
activeDialog: 'session-picker' | 'help' | null;
Expand Down Expand Up @@ -93,7 +92,6 @@ export function createTUIState(options: KimiTUIOptions): TUIState {
terminalState: createTerminalState(),
activitySpinner: null,
toolOutputExpanded: false,
planExpanded: false,
sessions: [],
loadingSessions: false,
activeDialog: null,
Expand Down
15 changes: 0 additions & 15 deletions apps/kimi-code/src/tui/utils/component-capabilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,6 @@ export interface Expandable {
setExpanded(expanded: boolean): void;
}

export interface PlanExpandable {
// Returns true iff the component actually owns a plan preview and
// applied the new state.
setPlanExpanded(expanded: boolean): boolean;
}

export interface Disposable {
dispose(): void;
}
Expand All @@ -21,15 +15,6 @@ export function isExpandable(obj: unknown): obj is Expandable {
);
}

export function isPlanExpandable(obj: unknown): obj is PlanExpandable {
return (
typeof obj === 'object' &&
obj !== null &&
'setPlanExpanded' in obj &&
typeof (obj as PlanExpandable).setPlanExpanded === 'function'
);
}

export function hasDispose(value: unknown): value is Disposable {
return (
typeof value === 'object' &&
Expand Down
Loading
Loading