diff --git a/.changeset/full-plan-card.md b/.changeset/full-plan-card.md new file mode 100644 index 000000000..ed8a5cb01 --- /dev/null +++ b/.changeset/full-plan-card.md @@ -0,0 +1,5 @@ +--- +"@moonshot-ai/kimi-code": patch +--- + +Show full plan cards directly and remove the Plan card keyboard shortcut. diff --git a/apps/kimi-code/src/tui/components/dialogs/approval-panel.ts b/apps/kimi-code/src/tui/components/dialogs/approval-panel.ts index 82d5339f2..ad92e0326 100644 --- a/apps/kimi-code/src/tui/components/dialogs/approval-panel.ts +++ b/apps/kimi-code/src/tui/components/dialogs/approval-panel.ts @@ -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; @@ -227,7 +226,6 @@ export class ApprovalPanelComponent extends Container implements Focusable { onResponse: (response: ApprovalPanelResponse) => void, colors: ColorPalette, onToggleToolOutput?: () => void, - onTogglePlanExpand?: () => void, onOpenPreview?: (block: DiffDisplayBlock | FileContentDisplayBlock) => void, ) { super(); @@ -235,7 +233,6 @@ export class ApprovalPanelComponent extends Container implements Focusable { this.onResponse = onResponse; this.colors = colors; this.onToggleToolOutput = onToggleToolOutput; - this.onTogglePlanExpand = onTogglePlanExpand; this.onOpenPreview = onOpenPreview; this.feedbackInput.onSubmit = (value) => { this.submit(this.selectedIndex, value); @@ -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; } diff --git a/apps/kimi-code/src/tui/components/dialogs/question-dialog.ts b/apps/kimi-code/src/tui/components/dialogs/question-dialog.ts index a21989ebe..2a9cac262 100644 --- a/apps/kimi-code/src/tui/components/dialogs/question-dialog.ts +++ b/apps/kimi-code/src/tui/components/dialogs/question-dialog.ts @@ -99,7 +99,6 @@ 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, @@ -107,7 +106,6 @@ export class QuestionDialogComponent extends Container implements Focusable { colors: ColorPalette, maxVisibleOptions = 6, onToggleToolOutput?: () => void, - onTogglePlanExpand?: () => void, ) { super(); this.request = request; @@ -115,7 +113,6 @@ export class QuestionDialogComponent extends Container implements Focusable { this.colors = colors; this.maxVisibleOptions = maxVisibleOptions; this.onToggleToolOutput = onToggleToolOutput; - this.onTogglePlanExpand = onTogglePlanExpand; this.otherInput.onSubmit = (value) => { this.commitOtherInput(value, 'enter'); }; @@ -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; diff --git a/apps/kimi-code/src/tui/components/editor/custom-editor.ts b/apps/kimi-code/src/tui/components/editor/custom-editor.ts index a7dfb87fb..6966dc50e 100644 --- a/apps/kimi-code/src/tui/components/editor/custom-editor.ts +++ b/apps/kimi-code/src/tui/components/editor/custom-editor.ts @@ -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; @@ -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; diff --git a/apps/kimi-code/src/tui/components/messages/plan-box.ts b/apps/kimi-code/src/tui/components/messages/plan-box.ts index c1cafd48d..cbefc2300 100644 --- a/apps/kimi-code/src/tui/components/messages/plan-box.ts +++ b/apps/kimi-code/src/tui/components/messages/plan-box.ts @@ -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; @@ -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; @@ -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; } @@ -81,20 +75,12 @@ 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; @@ -102,15 +88,6 @@ export class PlanBoxComponent implements Component { 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(); diff --git a/apps/kimi-code/src/tui/components/messages/tool-call.ts b/apps/kimi-code/src/tui/components/messages/tool-call.ts index 649c4ffd1..7fd287bc6 100644 --- a/apps/kimi-code/src/tui/components/messages/tool-call.ts +++ b/apps/kimi-code/src/tui/components/messages/tool-call.ts @@ -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; @@ -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 @@ -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(), }), ); @@ -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; diff --git a/apps/kimi-code/src/tui/controllers/editor-keyboard.ts b/apps/kimi-code/src/tui/controllers/editor-keyboard.ts index b36917263..847a6434d 100644 --- a/apps/kimi-code/src/tui/controllers/editor-keyboard.ts +++ b/apps/kimi-code/src/tui/controllers/editor-keyboard.ts @@ -31,7 +31,6 @@ export interface EditorKeyboardHost { updateEditorBorderHighlight(text?: string): void; updateQueueDisplay(): void; toggleToolOutputExpansion(): void; - togglePlanExpansion(): boolean; hideSessionPicker(): void; stop(exitCode?: number): Promise; handlePlanToggle(next: boolean): void; @@ -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(); diff --git a/apps/kimi-code/src/tui/controllers/streaming-ui.ts b/apps/kimi-code/src/tui/controllers/streaming-ui.ts index 35d0f6a9b..881489ea7 100644 --- a/apps/kimi-code/src/tui/controllers/streaming-ui.ts +++ b/apps/kimi-code/src/tui/controllers/streaming-ui.ts @@ -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; @@ -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(); } diff --git a/apps/kimi-code/src/tui/kimi-tui.ts b/apps/kimi-code/src/tui/kimi-tui.ts index 7e59fa4e5..f162fcc97 100644 --- a/apps/kimi-code/src/tui/kimi-tui.ts +++ b/apps/kimi-code/src/tui/kimi-tui.ts @@ -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'; @@ -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) { @@ -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('/'); @@ -1832,9 +1816,6 @@ export class KimiTUI { () => { this.toggleToolOutputExpansion(); }, - () => { - this.togglePlanExpansion(); - }, (block) => { this.openApprovalPreview(panel, block); }, @@ -1905,9 +1886,6 @@ export class KimiTUI { () => { this.toggleToolOutputExpansion(); }, - () => { - this.togglePlanExpansion(); - }, ); this.mountEditorReplacement(dialog); } diff --git a/apps/kimi-code/src/tui/tui-state.ts b/apps/kimi-code/src/tui/tui-state.ts index bc1c3214b..a3bf88c24 100644 --- a/apps/kimi-code/src/tui/tui-state.ts +++ b/apps/kimi-code/src/tui/tui-state.ts @@ -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; @@ -93,7 +92,6 @@ export function createTUIState(options: KimiTUIOptions): TUIState { terminalState: createTerminalState(), activitySpinner: null, toolOutputExpanded: false, - planExpanded: false, sessions: [], loadingSessions: false, activeDialog: null, diff --git a/apps/kimi-code/src/tui/utils/component-capabilities.ts b/apps/kimi-code/src/tui/utils/component-capabilities.ts index 5f1f0ba97..5b4f81356 100644 --- a/apps/kimi-code/src/tui/utils/component-capabilities.ts +++ b/apps/kimi-code/src/tui/utils/component-capabilities.ts @@ -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; } @@ -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' && diff --git a/apps/kimi-code/test/tui/components/dialogs/approval-panel.test.ts b/apps/kimi-code/test/tui/components/dialogs/approval-panel.test.ts index d6b7b8dda..9454ab316 100644 --- a/apps/kimi-code/test/tui/components/dialogs/approval-panel.test.ts +++ b/apps/kimi-code/test/tui/components/dialogs/approval-panel.test.ts @@ -260,14 +260,12 @@ describe('ApprovalPanelComponent', () => { }, }; let toolOutputToggles = 0; - let planToggles = 0; const previewCalls: Array = []; const dialog = new ApprovalPanelComponent( pending, (r) => responses.push(r), COLORS, () => toolOutputToggles++, - () => planToggles++, (block) => previewCalls.push(block), ); @@ -284,8 +282,7 @@ describe('ApprovalPanelComponent', () => { expect(after).not.toContain('new30'); expect(after).toContain('ctrl+e preview'); expect(previewCalls).toEqual([diffBlock]); - // The unrelated forward-only callbacks must not fire for ctrl+e. - expect(planToggles).toBe(0); + // The unrelated forward-only callback must not fire for ctrl+e. expect(toolOutputToggles).toBe(0); expect(responses).toEqual([]); }); @@ -320,10 +317,7 @@ describe('ApprovalPanelComponent', () => { expect(after).not.toContain('new30'); }); - // When there is no diff / file_content block to preview (e.g. plan_review - // with an empty display), ctrl+e falls through to the legacy global plan - // expand toggle so plan mode keeps working. - it('falls through to onTogglePlanExpand when there is nothing to preview', () => { + it('does nothing on ctrl+e when there is nothing to preview', () => { const pending: PendingApproval = { data: { id: 'approval_plan_only', @@ -335,19 +329,16 @@ describe('ApprovalPanelComponent', () => { choices: [{ label: 'Approve', response: 'approved' }], }, }; - let planToggles = 0; const previewCalls: Array = []; const dialog = new ApprovalPanelComponent( pending, () => {}, COLORS, undefined, - () => planToggles++, (block) => previewCalls.push(block), ); dialog.handleInput('\u0005'); // Ctrl+E - expect(planToggles).toBe(1); expect(previewCalls).toEqual([]); }); @@ -377,7 +368,6 @@ describe('ApprovalPanelComponent', () => { (r) => responses.push(r), COLORS, undefined, - undefined, (block) => previewCalls.push(block), ); @@ -420,7 +410,6 @@ describe('ApprovalPanelComponent', () => { () => {}, COLORS, undefined, - undefined, (block) => previewCalls.push(block), ); const collapsed = strip(dialog.render(120).join('\n')); diff --git a/apps/kimi-code/test/tui/components/dialogs/question-dialog.test.ts b/apps/kimi-code/test/tui/components/dialogs/question-dialog.test.ts index a015e4176..98604f43e 100644 --- a/apps/kimi-code/test/tui/components/dialogs/question-dialog.test.ts +++ b/apps/kimi-code/test/tui/components/dialogs/question-dialog.test.ts @@ -36,7 +36,6 @@ function makePending( function makeDialog( pending: PendingQuestion, onToggleToolOutput?: () => void, - onTogglePlanExpand?: () => void, ): { dialog: QuestionDialogComponent; collected: string[][]; @@ -53,7 +52,6 @@ function makeDialog( darkColors, 6, onToggleToolOutput, - onTogglePlanExpand, ); return { dialog, collected, methods }; } @@ -431,17 +429,6 @@ describe('QuestionDialogComponent', () => { expect(collected).toEqual([]); }); - it('forwards ctrl+e to the global plan-expand toggle without answering', () => { - let planToggles = 0; - const pending = makePending([ - { question: 'Q?', multi_select: false, options: [{ label: 'A' }] }, - ]); - const { dialog, collected } = makeDialog(pending, undefined, () => planToggles++); - dialog.handleInput('\u0005'); // Ctrl+E - expect(planToggles).toBe(1); - expect(collected).toEqual([]); - }); - describe('long-content wrapping', () => { const longQuestion = 'Please confirm whether this dangerous shell command should really be executed in the current workspace, including all of its side effects on the filesystem and the network.'; diff --git a/apps/kimi-code/test/tui/components/messages/tool-call.test.ts b/apps/kimi-code/test/tui/components/messages/tool-call.test.ts index 88cc967e2..bcd1156a3 100644 --- a/apps/kimi-code/test/tui/components/messages/tool-call.test.ts +++ b/apps/kimi-code/test/tui/components/messages/tool-call.test.ts @@ -255,7 +255,7 @@ describe('ToolCallComponent', () => { expect(after).not.toContain('/tmp/refactor.md'); }); - it('caps the plan preview to the terminal height and expands on ctrl+e', () => { + it('renders the full plan preview', () => { const longPlan = `# Refactor session\n\n${Array.from({ length: 40 }, (_, i) => `- step ${String(i + 1)}`).join('\n')}`; const component = new ToolCallComponent( { @@ -269,39 +269,13 @@ describe('ToolCallComponent', () => { createMarkdownTheme(darkColors), ); - const collapsed = strip(component.render(100).join('\n')); - expect(collapsed).toContain('step 1'); - expect(collapsed).toMatch(/\.\.\. \(\d+ more lines, ctrl\+e to expand\)/); - expect(collapsed).not.toContain('step 40'); - - expect(component.setPlanExpanded(true)).toBe(true); - const expanded = strip(component.render(100).join('\n')); - expect(expanded).toContain('step 40'); - expect(expanded).not.toContain('ctrl+e to expand'); - }); - - it('plan preview controls are no-ops for non-ExitPlanMode tool calls', () => { - const component = new ToolCallComponent( - { - id: 'call_bash_plan', - name: 'Bash', - args: { command: 'echo hi' }, - }, - undefined, - darkColors, - undefined, - createMarkdownTheme(darkColors), - ); - - expect(component.setPlanExpanded(true)).toBe(false); - component.setPlanInfo({ plan: 'should be ignored', path: '/etc/hosts' }); - const out = strip(component.render(100).join('\n')); - expect(out).not.toContain('should be ignored'); - expect(out).not.toContain('plan:'); + expect(out).toContain('step 1'); + expect(out).toContain('step 40'); + expect(out).not.toContain('more lines'); }); - it('ctrl+o does not affect the plan preview cap', () => { + it('ctrl+o does not affect the full plan preview', () => { const longPlan = `# P\n\n${Array.from({ length: 40 }, (_, i) => `- step ${String(i + 1)}`).join('\n')}`; const component = new ToolCallComponent( { @@ -316,8 +290,8 @@ describe('ToolCallComponent', () => { ); component.setExpanded(true); const out = strip(component.render(100).join('\n')); - expect(out).toContain('ctrl+e to expand'); - expect(out).not.toContain('step 40'); + expect(out).toContain('step 40'); + expect(out).not.toContain('more lines'); }); it('header chips an Approved status when ExitPlanMode result indicates approval', () => { diff --git a/apps/kimi-code/test/tui/components/panels/plan-box.test.ts b/apps/kimi-code/test/tui/components/panels/plan-box.test.ts index 9b35a481f..6813a7137 100644 --- a/apps/kimi-code/test/tui/components/panels/plan-box.test.ts +++ b/apps/kimi-code/test/tui/components/panels/plan-box.test.ts @@ -89,44 +89,13 @@ describe('PlanBoxComponent', () => { expect(top).not.toContain('plan:'); }); - it('renders all lines when content fits under maxContentLines', () => { - const plan = Array.from({ length: 5 }, (_, i) => `- step ${String(i + 1)}`).join('\n'); - const box = new PlanBoxComponent(plan, theme, darkColors.success, undefined, { - maxContentLines: 20, - }); + it('renders all plan lines without a truncation footer', () => { + const plan = Array.from({ length: 30 }, (_, i) => `- step ${String(i + 1)}`).join('\n'); + const box = new PlanBoxComponent(plan, theme, darkColors.success); const out = strip(box.render(80).join('\n')); expect(out).toContain('step 1'); - expect(out).toContain('step 5'); - expect(out).not.toContain('ctrl+e to expand'); - }); - - it('truncates content over maxContentLines with a footer inside the box', () => { - const plan = Array.from({ length: 30 }, (_, i) => `- step ${String(i + 1)}`).join('\n'); - const box = new PlanBoxComponent(plan, theme, darkColors.success, undefined, { - maxContentLines: 10, - }); - const rendered = box.render(80); - const out = strip(rendered.join('\n')); - expect(out).toContain('step 1'); - expect(out).toContain('step 9'); - expect(out).not.toContain('step 10'); - expect(out).toMatch(/\.\.\. \(\d+ more lines, ctrl\+e to expand\)/); - // Footer must live inside the bordered box, not after it. - const footerIdx = rendered.findIndex((line) => strip(line).includes('ctrl+e to expand')); - const bottomIdx = rendered.findIndex((line) => strip(line).includes('└')); - expect(footerIdx).toBeGreaterThan(-1); - expect(footerIdx).toBeLessThan(bottomIdx); - expect(strip(rendered[footerIdx]!)).toMatch(/^\s+│.*│\s*$/); - }); - - it('renders the full plan when expanded is true, ignoring maxContentLines', () => { - const plan = Array.from({ length: 30 }, (_, i) => `- step ${String(i + 1)}`).join('\n'); - const box = new PlanBoxComponent(plan, theme, darkColors.success, undefined, { - maxContentLines: 10, - expanded: true, - }); - const out = strip(box.render(80).join('\n')); expect(out).toContain('step 30'); - expect(out).not.toContain('ctrl+e to expand'); + expect(out).not.toContain('more lines'); }); + }); diff --git a/docs/en/reference/keyboard.md b/docs/en/reference/keyboard.md index c097d6238..5c4eea7ff 100644 --- a/docs/en/reference/keyboard.md +++ b/docs/en/reference/keyboard.md @@ -34,7 +34,6 @@ Press `Shift-Tab` to enable or disable Plan mode. When enabled, the Agent priori | `Ctrl-G` | Edit the current input in an external editor | | `Ctrl-V` | Paste an image or video from the clipboard (Unix / macOS) | | `Alt-V` | Paste an image or video from the clipboard (Windows) | -| `Ctrl-E` | Expand or collapse the Plan card (moves the cursor to end-of-line when no Plan card is present) | | `Ctrl--` | Undo | Pressing `Ctrl-G` opens an external editor, selected according to the following priority: diff --git a/docs/zh/reference/keyboard.md b/docs/zh/reference/keyboard.md index 4390ca929..ddc6db4b9 100644 --- a/docs/zh/reference/keyboard.md +++ b/docs/zh/reference/keyboard.md @@ -34,7 +34,6 @@ Kimi Code CLI 的 TUI 交互模式支持一套键盘快捷键。键位按使用 | `Ctrl-G` | 在外部编辑器中编辑当前输入 | | `Ctrl-V` | 粘贴剪贴板中的图片或视频(Unix / macOS) | | `Alt-V` | 粘贴剪贴板中的图片或视频(Windows) | -| `Ctrl-E` | 展开或折叠 Plan 卡片(无 Plan 卡片时将光标移到行尾) | | `Ctrl--` | 撤销(Undo) | 按 `Ctrl-G` 会打开外部编辑器,编辑器按以下优先级选择: