| 2026-07-13 |

tui: minor correctness/perf fixes (Etap 5)
...
The last batch from the code review — real bugs and edge cases, not cosmetics:
- tui_app._resolve_session: read session_id with .get and return None when a
malformed server response omits it, instead of KeyError slipping past the
api-call except (5.B3).
- cli /switch: surface the original error cause (404 vs network vs server) on
a non-unique prefix match instead of swallowing it into a generic "not found"
(6.B2).
- input_box _complete_command: a bare "/" with no hint list available no longer
auto-picks the first command in the registry (3.B3).
- filesystem _render_grep: when the grep ran in regex mode, highlight with the
actual regex so marked spans match what the server found — a literal highlight
of a regex pattern would mark nothing (2.B2).
- file_refs _collect_files: filter sensitive entries out in the generator before
sorted() so a huge directory is not fully materialized only to be mostly
discarded (5.P1).
- renderers/tool ToolResultRenderer: cap a generic tool result at 200 lines
(tail + marker) so a non-filesystem tool with huge output does not flood the
chat bubble — filesystem has its own renderer (2.P3).
Tests: malformed-response /switch error surfacing, bare-slash no-auto-pick,
grep regex highlight, sensitive-subdir skip, tool-result truncation. Full
suite: 953 passed, 1 skipped.
Eugene Sukhodolskiy
committed
5 hours ago
|

tui: async REST api client — stop blocking the event loop (Etap 3)
...
The terminal client's REST helpers were synchronous (httpx.Client); every
caller inside the Textual event loop (attach/switch/resume/profile/stop) blocked
the whole TUI for the duration of each network round-trip — the spinner froze,
input stopped responding, the screen did not repaint. Move the network layer to
async and a shared pooled client:
- api.py: all 7 helpers are now `async def` over a single lazily-created
httpx.AsyncClient (connection pooling) — awaits yield the loop while a request
is in flight, so the TUI never blocks on the network.
- tui_app.py + commands/builtin.py: every `api.*` call site is now `await`-ed
(all already ran in async workers / execute). _stop_stream_worker drops the
dead `iscoroutine` check (api.stop_session is async, the await is real).
- cli.py: _resolve_session_id and _handle_command await api.*; _run_raw wraps
the resolve + run in asyncio.run(_run_raw_async) so the sync click entrypoint
stays unchanged. Removed the now-unused _run_one_shot wrapper.
- sessions_picker.on_mount: list_sessions runs in a worker (run_worker) instead
of blocking on_mount — a slow/unreachable backend no longer hangs the modal;
the input is focusable immediately and the list populates when the request
returns.
Tests: every api mock across 6 client test files is now an `async def` fake
(test_tui_app, test_chat_panel, test_sessions_picker, test_terminal_client,
test_tui_export, test_input_box); the sessions picker tests use an async
_raise_not_found helper for the 404 path. Full suite: 939 passed, 1 skipped.
Eugene Sukhodolskiy
committed
6 hours ago
|

tui: code-review Etap 1 — crash/injection/reconnect fixes + drop artifact renderer
...
Point fixes from the full TUI/terminal-client code review (docs/code_review_tui.md),
each with a covering test:
- command_palette: guard on_list_view_selected against IndexError when the
filter is empty and the placeholder row is selected.
- cli /profile: read session_id (not the absent "id") from the server — the
handler no longer KeyErrors.
- todo_list: escape task text/validation/index/milestone before interpolating
into rich markup so a task like "fix [bug]" no longer breaks the line styling.
- builtin /help: drop bold markup tags from status content — StatusRenderer
builds a literal Text() that would show the tags as literal square brackets.
- tui_app on_user_submitted: always enqueue when a bridge exists (the input loop
buffers across reconnect) instead of dropping the message on connected=False.
- chat_model stream_start: also reset _current_thinking so a dropped turn (no
thinking_end) does not glue the next turn's reasoning onto the old block.
- todo renderer update: coerce validation to str before .strip() so a non-string
JSON value does not AttributeError.
- renderers: remove the unused ArtifactRenderer (no production path emits
type=artifact — TUI shows files via the OS); keep the diff renderer test.
Full suite: 937 passed, 1 skipped.
Eugene Sukhodolskiy
committed
7 hours ago
|
| 2026-07-11 |

tui: add --resume <session_id> and print resume hint on TUI close
...
Closing Navi Code now tells the user the session id and the exact command to
continue it, so a session is one re-run away instead of lost to state lookup.
- cli.py: add --resume <session_id> (mutex with --new-session). Raw and TUI
paths resolve the given id via api.get_session; a bad id is a hard error,
not a silent new session. After app.run() returns and the terminal is
restored, print "Session <id>" / "Resume with: navi-code --resume <id>"
when a session is attached.
- tui_app._resolve_session: make the explicit-id branch strict — a failed
get_session surfaces an error event and returns None instead of falling
through to creating a new session (a --resume typo used to silently start
a fresh session). Saved-state resume stays lenient.
- tests: resume-flag resolve/bad-id/mutex + hint format; tui strict-on-bad
explicit id and explicit-id resume.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
2 days ago
|
| 2026-07-09 |
navi-code CLI: make -h show help instead of sending it to the model
...
The CLI uses ignore_unknown_options=True so a prompt can contain flag-like
text, but that also meant the short -h flag was not recognized as the help
flag — it fell through to the PROMPT argument and was sent to Navi as a
message ("you've asked for help again..."). --help already worked because
Click auto-generates the long form.
Add help_option_names=["-h", "--help"] to context_settings so -h is a known
help option, parsed before the ignore-unknown fallback.
Test: -h via CliRunner exits 0 and shows usage. 577 passed, 1 skipped.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
4 days ago
|
| 2026-06-26 |
Navi Code: stop via Esc + project cwd propagation
...
- TUI: Esc stops active stream cooperatively via POST /sessions/{id}/stop
- TUI: render stream_stopped as status message
- CLI/WebSocket: send shell cwd in client->server message field
- Orchestrator stores cwd in session.session_metadata
- ContextBuilder injects [Working directory] into LLM context
- Agent sets current_working_directory ContextVar per turn
- tools/base: ToolContext gains cwd field
- filesystem/terminal/code_exec resolve relative paths against session cwd
- Add bin/navi-code wrapper for PATH symlink; document in README.md
- Update docs/websocket.md and tests
Full pytest: 544 passed, 1 skipped.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
17 days ago
|
| 2026-06-24 |
Navi Code TUI: review fixes for Phase 5
...
- Fix raw CLI session API fields (session_id/name/preview)
- Add --mouse/--no-mouse flags and persistent TUI settings coercion
- Make attach_session/apply_theme public, add ChatPanel.clear()
- Deduplicate session selection handlers and editor error handling
- Update docs and tests
Eugene Sukhodolskiy
committed
20 days ago
|
| 2026-06-23 |
Navi Code: Phase 2 — CLI terminal client, tests, docs
...
- Add clients/terminal package: config, state, REST API wrappers, WebSocket
client, renderer, and click-based interactive CLI.
- Wire navi-code console script via pyproject.toml.
- Add unit and WebSocket integration tests for the terminal client.
- Update docs/profiles.md, docs/config.md, README.md with navi_code profile
and default-profile instructions.
- Add docs/navi_code.md setup guide and docs/navi_code_cli.md usage reference.
- Fix lint in new test files and test_auth_disabled.py.
Tested: 459 passed, 1 skipped (excluded unrelated websocket test).
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
21 days ago
|