From 8ba0498eb773517c26b0215c718b13df05e40779 Mon Sep 17 00:00:00 2001 From: can1357 Date: Sun, 11 Jan 2026 22:59:04 +0100 Subject: [PATCH] fix(coding-agent): fixed keybindings and input handling for TUI editor and Cursor provider - Changed temporary model selector keybinding from Ctrl+Y to Alt+P to avoid conflicts. - Fixed Alt+Enter to insert newline when not streaming instead of submitting. - Fixed Cursor provider to avoid advertising Edit tool, using full-file Write instead. - Added Ctrl+Enter support for inserting newlines in TUI editor using Kitty and legacy terminal formats. - Removed duplicate Ctrl+Y handler and refactored input controller to use trimmedText variable. --- packages/coding-agent/CHANGELOG.md | 8 +++++ packages/coding-agent/src/core/sdk.ts | 3 ++ .../interactive/components/custom-editor.ts | 15 +++------- .../controllers/command-controller.ts | 2 +- .../controllers/input-controller.ts | 30 +++++++++++-------- packages/tui/CHANGELOG.md | 3 ++ packages/tui/src/components/editor.ts | 2 ++ 7 files changed, 39 insertions(+), 24 deletions(-) diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index 3a63f03dd..8ab401dab 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -1,15 +1,23 @@ # Changelog ## [Unreleased] + ### Added - Added grouped display for consecutive Read tool calls, showing multiple file reads in a compact tree view ### Changed +- Changed temporary model selector keybinding from Ctrl+Y to Alt+P - Changed expand hint text from "Ctrl+O to expand" to "Ctrl+O for more" - Changed Read tool result display to hide content by default, showing only file path and status +### Fixed + +- Fixed Alt+Enter to insert a newline when not streaming, instead of submitting the message +- Fixed Alt+Enter inserting a new line when not streaming instead of submitting a message +- Fixed Cursor provider to avoid advertising the Edit tool, relying on full-file Write operations instead + ## [4.3.2] - 2026-01-11 ### Changed diff --git a/packages/coding-agent/src/core/sdk.ts b/packages/coding-agent/src/core/sdk.ts index e327376ff..ec0ffacee 100644 --- a/packages/coding-agent/src/core/sdk.ts +++ b/packages/coding-agent/src/core/sdk.ts @@ -855,6 +855,9 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {} toolRegistry.set(tool.name, wrapToolWithExtensions(tool, extensionRunner)); } } + if (model?.provider === "cursor") { + toolRegistry.delete("edit"); + } time("combineTools"); let cursorEventEmitter: ((event: AgentEvent) => void) | undefined; diff --git a/packages/coding-agent/src/modes/interactive/components/custom-editor.ts b/packages/coding-agent/src/modes/interactive/components/custom-editor.ts index 6fda68cd6..7ee5964aa 100644 --- a/packages/coding-agent/src/modes/interactive/components/custom-editor.ts +++ b/packages/coding-agent/src/modes/interactive/components/custom-editor.ts @@ -9,7 +9,6 @@ import { isCtrlP, isCtrlT, isCtrlV, - isCtrlY, isCtrlZ, isEscape, isShiftCtrlP, @@ -36,7 +35,7 @@ export class CustomEditor extends Editor { public onCtrlZ?: () => void; public onQuestionMark?: () => void; public onCapsLock?: () => void; - public onCtrlY?: () => void; + public onAltP?: () => void; /** Called when Ctrl+V is pressed. Returns true if handled (image found), false to fall through to text paste. */ public onCtrlV?: () => Promise; /** Called when Alt+Up is pressed (dequeue keybinding). */ @@ -84,9 +83,9 @@ export class CustomEditor extends Editor { return; } - // Intercept Ctrl+Y for voice input - if (isCtrlY(data) && this.onCtrlY) { - this.onCtrlY(); + // Intercept Alt+P for quick model switching + if (matchesKey(data, "alt+p") && this.onAltP) { + this.onAltP(); return; } @@ -102,12 +101,6 @@ export class CustomEditor extends Editor { return; } - // Intercept Ctrl+Y for role-based model cycling - if (isCtrlY(data) && this.onCtrlY) { - this.onCtrlY(); - return; - } - // Intercept Ctrl+L for model selector if (isCtrlL(data) && this.onCtrlL) { this.onCtrlL(); diff --git a/packages/coding-agent/src/modes/interactive/controllers/command-controller.ts b/packages/coding-agent/src/modes/interactive/controllers/command-controller.ts index 3b2a2661a..54652bf0d 100644 --- a/packages/coding-agent/src/modes/interactive/controllers/command-controller.ts +++ b/packages/coding-agent/src/modes/interactive/controllers/command-controller.ts @@ -334,7 +334,7 @@ export class CommandController { | \`Shift+Tab\` | Cycle thinking level | | \`Ctrl+P\` | Cycle role models (slow/default/smol) | | \`Shift+Ctrl+P\` | Cycle role models (temporary) | -| \`Ctrl+Y\` | Select model (temporary) | +| \`Alt+P\` | Select model (temporary) | | \`Ctrl+L\` | Select model (set roles) | | \`Ctrl+R\` | Search prompt history | | \`Ctrl+O\` | Toggle tool output expansion | diff --git a/packages/coding-agent/src/modes/interactive/controllers/input-controller.ts b/packages/coding-agent/src/modes/interactive/controllers/input-controller.ts index aff937002..be12c7e3e 100644 --- a/packages/coding-agent/src/modes/interactive/controllers/input-controller.ts +++ b/packages/coding-agent/src/modes/interactive/controllers/input-controller.ts @@ -60,7 +60,7 @@ export class InputController { this.ctx.editor.onShiftTab = () => this.cycleThinkingLevel(); this.ctx.editor.onCtrlP = () => this.cycleRoleModel(); this.ctx.editor.onShiftCtrlP = () => this.cycleRoleModel({ temporary: true }); - this.ctx.editor.onCtrlY = () => this.ctx.showModelSelector({ temporaryOnly: true }); + this.ctx.editor.onAltP = () => this.ctx.showModelSelector({ temporaryOnly: true }); // Global debug handler on TUI (works regardless of focus) this.ctx.ui.onDebug = () => this.ctx.handleDebugCommand(); @@ -85,28 +85,34 @@ export class InputController { }; this.ctx.editor.onAltEnter = async (text: string) => { - text = text.trim(); - if (!text) return; + const trimmedText = text.trim(); // Queue follow-up messages while compaction is running if (this.ctx.session.isCompacting) { - this.ctx.queueCompactionMessage(text, "followUp"); + if (!trimmedText) { + this.ctx.editor.handleInput("\n"); + return; + } + this.ctx.queueCompactionMessage(trimmedText, "followUp"); return; } - // Alt+Enter queues a follow-up message (waits until agent finishes) - // This handles extension commands (execute immediately), prompt template expansion, and queueing + // Alt+Enter queues a follow-up message while streaming if (this.ctx.session.isStreaming) { - this.ctx.editor.addToHistory(text); + if (!trimmedText) { + this.ctx.editor.handleInput("\n"); + return; + } + this.ctx.editor.addToHistory(trimmedText); this.ctx.editor.setText(""); - await this.ctx.session.prompt(text, { streamingBehavior: "followUp" }); + await this.ctx.session.prompt(trimmedText, { streamingBehavior: "followUp" }); this.ctx.updatePendingMessagesDisplay(); this.ctx.ui.requestRender(); + return; } - // If not streaming, Alt+Enter acts like regular Enter (trigger onSubmit) - else if (this.ctx.editor.onSubmit) { - this.ctx.editor.onSubmit(text); - } + + // Default behavior: insert a new line + this.ctx.editor.handleInput("\n"); }; } diff --git a/packages/tui/CHANGELOG.md b/packages/tui/CHANGELOG.md index 8e3e5e657..deba203b2 100644 --- a/packages/tui/CHANGELOG.md +++ b/packages/tui/CHANGELOG.md @@ -1,6 +1,9 @@ # Changelog ## [Unreleased] +### Fixed + +- Fixed Ctrl+Enter sequences to insert new lines in the editor ## [4.3.2] - 2026-01-11 diff --git a/packages/tui/src/components/editor.ts b/packages/tui/src/components/editor.ts index 7021883e1..833793e7d 100644 --- a/packages/tui/src/components/editor.ts +++ b/packages/tui/src/components/editor.ts @@ -708,6 +708,8 @@ export class Editor implements Component { // New line shortcuts (but not plain LF/CR which should be submit) else if ( (data.charCodeAt(0) === 10 && data.length > 1) || // Ctrl+Enter with modifiers + data === "\x1b[13;5u" || // Ctrl+Enter (Kitty protocol) + data === "\x1b[27;5;13~" || // Ctrl+Enter (legacy format) data === "\x1b\r" || // Option+Enter in some terminals (legacy) data === "\x1b[13;2~" || // Shift+Enter in some terminals (legacy format) isShiftEnter(data) || // Shift+Enter (Kitty protocol, handles lock bits)