fix: batch of 7 CLI bug fixes from issue triage#569
Draft
Conversation
Co-authored-by: openhands <openhands@all-hands.dev>
setup_conversation() called Console().print() directly to stdout while the Textual TUI was running, producing 'Initializing agent...' and '✓ Agent initialized with model: ...' lines interspersed with the UI. Remove all three Console.print calls; the TUI surfaces agent status through its own notification system. Co-authored-by: openhands <openhands@all-hands.dev>
Previously the conversation ID was only printed after the session ended, making it impossible to resume or inspect a long-running headless task if the process was killed mid-way. _initialize_main_ui() now calls _print_headless_conversation_id() in headless mode before the agent starts running, printing both the hex ID and a --resume hint to stdout. Co-authored-by: openhands <openhands@all-hands.dev>
_print_conversation_summary() now reads conversation_state.metrics and prints a Cost line (e.g. '$ 0.05 (↑ 1k ↓ 200 cache 10%)') when metrics are available. When metrics are None the output is unchanged. Co-authored-by: openhands <openhands@all-hands.dev>
…orts
entrypoint.py called warnings.filterwarnings("ignore") AFTER importing
openhands_cli modules, so opentelemetry's module-level DeprecationWarning
was already emitted by the time the filter was applied.
Restructure the module so that:
1. .env is loaded (dotenv + stdlib only -- no heavy transitive deps)
2. DEBUG is checked and warnings.filterwarnings("ignore") is called
3. The heavy openhands_cli imports follow (warnings now suppressed)
noqa: E402 comments mark the intentionally-late imports.
Co-authored-by: openhands <openhands@all-hands.dev>
…etting When default_cells_expanded=True the system-prompt collapsible expanded fully, flooding the conversation view with thousands of tokens that are rarely useful to read. Force collapsed=True in _create_system_prompt_collapsible so that the system prompt always starts collapsed, independent of the global default_cells_expanded preference. Users can still expand it manually if needed. Co-authored-by: openhands <openhands@all-hands.dev>
AGENTS.md or other skill files with non-UTF-8 bytes (Latin-1, binary) caused an unhandled UnicodeDecodeError in _build_agent_context, crashing the CLI on startup rather than showing a useful message. Wrap load_project_skills() in a try-except: on UnicodeDecodeError print a warning to stderr identifying the encoding problem and the byte offset, then continue with an empty skill list so the session can still start. The underlying issue is in openhands/sdk (Skill.load opens files without errors='replace'), but this CLI-side guard ensures users always get a helpful message and a working session rather than a traceback. Co-authored-by: openhands <openhands@all-hands.dev>
…ck misfires) Clicking anywhere in the InlineConfirmationPanel's ListView area immediately fired ListView.Selected, which could accept, reject, or escalate permissions with a single accidental click on a high-DPI or small terminal. Introduce _KeyboardOnlyListView — a ListView subclass that overrides _on_list_item__child_clicked to update the highlighted index WITHOUT posting ListView.Selected. Mouse clicks now work as navigation (moving the highlight to the clicked option); the user must press Enter to actually confirm the selection. Co-authored-by: openhands <openhands@all-hands.dev>
Contributor
Coverage Report •
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Pyright cannot narrow the type of `node` through a stored boolean variable (`is_openhands_import = isinstance(...)`). Inline the `isinstance(node, ast.ImportFrom)` check directly in the `if` guard so pyright narrows the type to `ast.ImportFrom` inside the block and resolves `node.lineno` without error. Fixes: tests/test_entrypoint_warnings.py:65 - reportAttributeAccessIssue (lineno) tests/test_entrypoint_warnings.py:67 - reportAttributeAccessIssue (lineno) Co-authored-by: openhands <openhands@all-hands.dev>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
Seven standalone bug fixes identified during a triage pass of
CLI_ISSUES_ROUGH.md. Each fix is its own commit;CLI_ISSUES_REPORT.mdrecords the full triage (which issues are tracked, which are new, fix rationale).Fix 4 – TUI corruption from
setup_conversationprintssetup_conversationcalledprint()directly, which interleaved raw bytes with Textual's TUI output. Replaced withConsole(stderr=True)so setup logs are always written to stderr, never into the TUI.Fix 10 – Conversation ID not shown in headless mode
Headless sessions gave no indication of which conversation was created, making it impossible to resume or correlate logs. Now prints
Conversation ID: <id>immediately after creation.Fix 11 – Headless summary missing cost
End-of-run headless summary omitted token usage and cost. Now includes:
Fix 13 – Import-time
DeprecationWarningnoisewarnings.filterwarnings("ignore")andload_dotenv()were called afteropenhands_cliimports, so warnings fired during import. Moved both calls to the top ofentrypoint.py, before anyopenhands_cliimports.Fix 12 – System-prompt collapsible expands when
default_cells_expanded=TrueWhen the user enabled "expand all cells by default", the system-prompt collapsible (which can contain thousands of tokens) expanded too, flooding the conversation view.
_create_system_prompt_collapsiblenow always passescollapsed=Trueregardless of the global setting.Fix 2 –
UnicodeDecodeErrorcrash on non-UTF-8AGENTS.mdAny skill file containing non-UTF-8 bytes (Latin-1, binary data) raised an unhandled
UnicodeDecodeErrorin_build_agent_context, crashing the CLI on startup. Now catches the error, prints a helpful stderr warning with the byte offset, and continues with an empty skill list so the session still starts. (Root cause is in the SDK'sSkill.load; this is a CLI-side guard.)Fix 7 – Permission selector misfires on mouse click
InlineConfirmationPanelused a plainListViewwhose_on_list_item__child_clickedimmediately postedListView.Selected, so a single accidental click anywhere in the list area could accept, reject, or escalate a permission prompt. Introduced_KeyboardOnlyListView: overrides_on_list_item__child_clickedto only update the highlighted index, never postSelected. Mouse clicks navigate; Enter confirms.Commands run
Tests were added for every behaviour change:
tests/test_entrypoint_warnings.py— AST-ordering + functional warning-suppression tests (Fix 13)tests/tui/widgets/test_richlog_visualizer.py::TestSystemPromptCollapsible— 4 new tests (Fix 12)tests/settings/test_skills_loading.py::TestAgentStoreBuildContextUnicodeError— 2 new tests (Fix 2)tests/tui/panels/test_confirmation_panel.py— 2 new tests covering_KeyboardOnlyListView(Fix 7)Before / After (Fix 7 — click misfire)
>highlight; user must press Enter to confirmChecklist
make lint✅make test✅ (1280 passed)🚀 Try this PR