Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
4 changes: 3 additions & 1 deletion src/kimi_cli/ui/shell/__init__.py
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 NameError: _mcp_status_block, _mcp_status_loading, and _bg_task_count are used but no longer defined

The PR deleted the local function/class definitions for _mcp_status_block, _mcp_status_loading, _BgCountCache, and _bg_task_count (previously at old lines 200-230) but left the references to them at lines 204-206 when constructing the CustomPromptSession. This means entering the interactive shell (Shell.run() without a command) will immediately crash with a NameError. This breaks the primary interactive mode of the CLI.

(Refers to lines 204-206)

Prompt for agents
Restore the deleted local function/class definitions that were previously between lines 200-230 (old) of src/kimi_cli/ui/shell/__init__.py. Specifically, you need to re-add these definitions inside the run() method, before the `with CustomPromptSession(...)` block at line 202:

1. `_mcp_status_block(columns: int)` - closure that reads `self.soul.status.mcp_status` and calls `render_mcp_prompt`
2. `_mcp_status_loading() -> bool` - closure that checks if MCP is loading
3. `_BgCountCache` dataclass with `time` and `count` fields
4. `_bg_cache` instance of `_BgCountCache`
5. `_bg_task_count() -> int` - closure that returns background task count with caching

These were defined between the `_plan_mode_toggle` definition and the `CustomPromptSession` context manager, and should be placed back there (after the new `maybe_disable_kitty_keyboard_protocol()` call at line 200 and before the `with CustomPromptSession(...)` at line 202).
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
from kimi_cli.utils.signals import install_sigint_handler
from kimi_cli.utils.slashcmd import SlashCommand, SlashCommandCall, parse_slash_command_call
from kimi_cli.utils.subprocess_env import get_clean_env
from kimi_cli.utils.term import ensure_new_line, ensure_tty_sane
from kimi_cli.utils.term import ensure_new_line, ensure_tty_sane, maybe_disable_kitty_keyboard_protocol
from kimi_cli.wire.types import ContentPart, StatusUpdate


Expand Down Expand Up @@ -109,6 +109,8 @@ async def _plan_mode_toggle() -> bool:
return await self.soul.toggle_plan_mode_from_manual()
return False

maybe_disable_kitty_keyboard_protocol()

with CustomPromptSession(
status_provider=lambda: self.soul.status,
model_capabilities=self.soul.model_capabilities or set(),
Expand Down
34 changes: 34 additions & 0 deletions src/kimi_cli/utils/term.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import sys
import time

from kimi_cli.utils.envvar import get_env_bool


def ensure_new_line() -> None:
"""Ensure the next prompt starts at column 0 regardless of prior command output."""
Expand Down Expand Up @@ -50,6 +52,33 @@ def ensure_tty_sane() -> None:
termios.tcsetattr(fd, termios.TCSADRAIN, attrs)


def maybe_disable_kitty_keyboard_protocol() -> None:
"""Disable kitty keyboard protocol in terminals that send CSI-u sequences.

This is primarily a workaround for VS Code's integrated terminal, which can
emit CSI-u key sequences that prompt_toolkit doesn't parse.
"""
if sys.platform == "win32":
return
if not sys.stdout.isatty() or not sys.stdin.isatty():
return
if not _should_disable_kitty_keyboard_protocol():
return

_write_escape("\x1b[<u")
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid popping the terminal's kitty key mode on startup

CSI < u is the kitty keyboard protocol pop/restore sequence, so sending it unconditionally here changes terminal state without a matching push from this process. In terminals where the parent shell/editor already enabled kitty key handling—or whenever users set KIMI_CLI_DISABLE_KITTY_KEYS=1 outside VS Code—starting kimi will consume the parent's stack entry and leave the outer program in the wrong keyboard mode after exit until it reconfigures the terminal.

Useful? React with 👍 / 👎.



def _should_disable_kitty_keyboard_protocol() -> bool:
env_value = os.getenv("KIMI_CLI_DISABLE_KITTY_KEYS")
if env_value is not None:
return get_env_bool("KIMI_CLI_DISABLE_KITTY_KEYS", default=False)
return _is_vscode_terminal()


def _is_vscode_terminal() -> bool:
return os.getenv("TERM_PROGRAM") == "vscode" or "VSCODE_IPC_HOOK_CLI" in os.environ


def _cursor_position_unix() -> tuple[int, int] | None:
"""Get cursor position (row, column) on Unix. Both are 1-indexed."""
assert sys.platform != "win32"
Expand Down Expand Up @@ -149,6 +178,11 @@ def _write_newline() -> None:
sys.stdout.flush()


def _write_escape(value: str) -> None:
sys.stdout.write(value)
sys.stdout.flush()


def get_cursor_row() -> int | None:
"""Get the current cursor row (1-indexed)."""
if not sys.stdout.isatty() or not sys.stdin.isatty():
Expand Down
Loading