Skip to content
Open
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
14 changes: 14 additions & 0 deletions src/google/adk/cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,19 @@ def _collect_pending_function_calls(
return pending


def _enable_line_editing() -> None:
"""Enables arrow-key editing and history for input() when available.

input() only supports line editing once the readline module is imported.
readline is not available on Windows, where the console already provides
history.
"""
try:
import readline # noqa: F401
except ImportError:
pass


def _is_positive_response(s: str) -> bool:
"""Returns True if the string is a positive response."""
return s.strip().lower() in ('y', 'yes', 'true', 'confirm')
Expand Down Expand Up @@ -267,6 +280,7 @@ async def run_interactively(
agent_loader: Optional[AgentLoader] = None,
agent_folder_name: Optional[str] = None,
) -> None:
_enable_line_editing()
app = _to_app(root_agent_or_app, session.app_name)
runner = Runner(
app=app,
Expand Down
47 changes: 47 additions & 0 deletions tests/unittests/cli/utils/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -644,6 +644,53 @@ async def test_run_interactively_whitespace_and_exit(
assert any("echo:hello" in m for m in echoed)


def test_enable_line_editing_imports_readline(
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""_enable_line_editing should import readline so input() gets history."""
pytest.importorskip("readline")
monkeypatch.delitem(sys.modules, "readline", raising=False)

cli._enable_line_editing()

assert "readline" in sys.modules


def test_enable_line_editing_without_readline(
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""_enable_line_editing should not fail where readline is missing."""
# A None entry in sys.modules makes the import raise ImportError, as on
# Windows.
monkeypatch.setitem(sys.modules, "readline", None)

cli._enable_line_editing()


@pytest.mark.asyncio
async def test_run_interactively_enables_line_editing(
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""run_interactively should enable line editing before reading input."""
session_service = InMemorySessionService()
sess = await session_service.create_session(app_name="dummy", user_id="u")
calls: list[str] = []
monkeypatch.setattr(
cli, "_enable_line_editing", lambda: calls.append("enabled")
)
monkeypatch.setattr("builtins.input", lambda *_a, **_k: "exit")

await cli.run_interactively(
BaseAgent(name="root"),
InMemoryArtifactService(),
sess,
session_service,
InMemoryCredentialService(),
)

assert calls == ["enabled"]


def test_print_event_omits_internal_metadata_in_jsonl(
monkeypatch: pytest.MonkeyPatch,
) -> None:
Expand Down
Loading