| 2026-07-11 |

tui: show the changed step's text in the todo update call card
...
The todo update call card (→ todo · #3 → done) now shows the text of the
step being changed, plus the validation when present. The LLM's update args
carry only the index, not the task text, so the text is read from the
current plan row before the tool runs and attached to ToolStarted.metadata
(client-rendering only, backward-compatible).
Backend:
- events.ToolStarted gains a metadata dict (mirrors ToolEvent) → to_wire.
- navi/tools/todo: step_text_for_update(index, ctx) resolves the step text
via _sid/_uid (so sub-agent isolation holds), started_metadata_for_call
wraps it for both emit sites.
- agent.py (parent) and subagent_runner.py (sub-agent) enrich ToolStarted
via the shared helper before emitting.
Renderer:
- TodoStartedRenderer update card reads msg.metadata.step_text → shows the
step text + validation; falls back to 'no validation' on history replay.
- Removed the step-text line from the result card (it now lives in the call
card) — result card is back to the compact 'plan · X/N done' summary.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
1 day ago
|

Navi Code TUI: show request duration (live timer + chat metadata)
...
Live elapsed timer next to the activity indicator (ticks once per second
during a turn, format 2m 16s), driven by the same stream_start/stream_end
hooks as the activity indicator — so it spans the whole turn (all LLM calls,
tool calls, planning, sub-agent steps). On stream_end it syncs to the
backend's authoritative elapsed_seconds before freezing; on stream_stopped/
error/disconnect it freezes at the locally-measured value.
On stream_end the model also appends a turn_meta ChatItem rendered as a dim
"⏱ 2m 16s" line below the answer — the total time the agent spent on the
user's request. The value comes from stream_end.elapsed_seconds, already
measured by the backend over the whole turn, so the TUI needs no timer for
accuracy. stream_stopped/error do not get a metadata line (only completed
requests).
Shared format_duration(): None -> "—", <60s -> "16s", <3600 -> "2m 16s",
>=3600 -> "1h 2m".
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
1 day ago
|
| 2026-07-10 |
tui: render Navi's answers as markdown
...
AssistantMessageRenderer now parses its content as markdown (headings, lists,
bold/italic, inline and fenced code blocks with theme-aware syntax
highlighting) via the existing ThemedMarkdownRenderable — the same renderer
the planning cards already use — instead of plain Text. The formatting
shows live as Navi streams. User messages stay plain text.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
2 days ago
|
| 2026-07-09 |

Navi Code TUI: sub-agent spawn card + nested styling for subagent thinking/planning
...
Sub-agent activity was either rendered as a generic tool card (spawn_agent) or
dropped to raw debug output (turn_thinking was unhandled in the TUI chat model
and the raw CLI). The webclient nests subagent events inside the spawn_agent
card; the TUI is flat, so nesting is conveyed with a distinct spawn card plus
left-indented, dimmed subagent cards.
New renderers/subagent.py:
- SpawnAgentStartedRenderer: "↘ subagent · <profile_id>" card showing the task
(+ briefing dimmed), secondary border. Registered before ToolStartedRenderer.
- SpawnAgentResultRenderer: "↙ subagent · <profile_id> ✓/✗" card with the
result, success/error border. Registered before ToolResultRenderer.
Nested subagent styling (left indent via Padding + dim):
- ThinkingRenderer: is_subagent → "subagent thinking" title, dim border, indented.
- PlanningStatusRenderer / PlanReadyRenderer: is_subagent → indented (label/title
already mark it as subagent).
- ToolStartedRenderer / ToolResultRenderer: is_subagent → indented so inner
tool calls read as nested inside the spawn card.
chat_model handles turn_thinking → thinking_block item with is_subagent meta;
chat_panel._refresh forwards is_subagent to the thinking renderer. Raw CLI
render.py prints turn_thinking as a [thinking] block (with "(subagent)" prefix).
Tests: spawn card shows profile/task and status; subagent thinking/planning/tool
cards are indented and labeled; non-subagent tool card is not indented;
turn_thinking creates a subagent thinking_block. 593 passed, 1 skipped.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
3 days ago
|

Navi Code: render planning as a progress line + plan card, not raw events
...
planning_status and plan_ready events were unhandled in the TUI chat model and
the raw CLI renderer, so they fell through to raw debug output (TUI:
"plan_ready: {...}" status lines; raw CLI: "[event: plan_ready] {msg}").
TUI:
- New renderers/planning.py: PlanningStatusRenderer renders a "⚙ Planning ·
<label>" line (info color; dim + "(subagent)" prefix for subagent planning);
PlanReadyRenderer renders the plan as a Panel wrapping themed Markdown, titled
"Plan" with an accent border ("subagent plan" + dim border for subagents).
- Registered both in default_registry().
- chat_model handles the events: non-subagent planning_status rolls in place
(Analysis → Execution plan → Plan review share one line instead of stacking);
plan_ready consumes the pending planning line and appends the plan card;
subagent planning is appended as its own dim line/card so it does not bleed
into the parent turn's indicator (matching the webclient).
- chat_panel._refresh maps the new kinds to the registry.
Raw CLI (render.py): planning_status prints "[planning] <label>"; plan_ready
prints a "[plan] … [/plan]" block with the plan text.
Tests: renderer accepts/render (label, subagent prefix, plan title/content);
chat_model rolling-in-place, plan_ready consumes indicator, subagent separation.
584 passed, 1 skipped.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
3 days ago
|
| 2026-06-26 |
Navi Code TUI: fix input box layout, command palette duplicate IDs, status renderer, and WS input loop
...
- clients/terminal/tui/widgets/input_box.py: switch Horizontal to Vertical with width: 100% for Input so it renders and accepts input in real terminals; add refresh on Input.Changed.
- clients/terminal/tui/screens/command_palette.py: remove fixed ListItem IDs to avoid DuplicateIds on fast filter.
- clients/terminal/tui/chat_model.py + renderers/status.py + widgets/chat_panel.py: render backend status events as dim system messages instead of raw dicts.
- clients/terminal/tui/ws_bridge.py: start NaviWebSocketClient.input_loop so enqueued user messages are actually sent to the backend.
- clients/terminal/tui/tui_app.py: focus InputBox synchronously in on_mount so typing works immediately.
- tests/clients/test_tui_app.py: regression test for visible input text.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
16 days ago
|
| 2026-06-23 |
Navi Code TUI: fix Phase 4 review critical/medium issues
...
- PermissionEngine: always-deny returns None via check(); is_always_deny() exposed for explicit rejection; default rules for code_exec/ssh_exec/shell; extract_target() made public.
- ShellRunner: set ShellResult.truncated when output is actually truncated.
- File refs: restrict paths to base_dir/home, block sensitive files/dirs, skip binary, support glob brackets, shared guess_language.
- Permission dialog: deny now renders synthetic tool_call before stopping; shell ! commands require permission with always-allow/deny persistence.
- Tests: add permission tests, fix file_refs/shell tests, add __init__.py to fix pytest name collisions, update websocket integration for AgentSessionOrchestrator.
504 passed, 1 skipped. Ruff clean.
Signed-off-by: Eugene Sukhodolskiy <eugene.sukhodolskiy@gmail.com>
Eugene Sukhodolskiy
committed
18 days ago
|
Navi Code TUI: complete Phase 4
...
- @ file references with glob/dir support and size limits
- ! shell commands with timeout and output truncation
- inline permission dialog for destructive tool calls
- diff and artifact renderers with theme-aware highlighting
Tests: 40 client tests passing
Eugene Sukhodolskiy
committed
19 days ago
|
Navi Code TUI: command palette and themed markdown
...
- Add CommandPaletteScreen modal with fuzzy filtering and keyboard navigation.
- Bind Ctrl+P to push the palette; selected commands execute via registry.
- Make MarkdownRenderer theme-aware: headings, inline code, links, and code blocks use gnexus palette.
- Pick dracula/github-light code theme based on active theme brightness.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
19 days ago
|
Navi Code TUI: apply gnexus theme to widgets and renderers
...
- Register Navi themes as Textual themes so $tui-* CSS variables resolve.
- Update ChatPanel, StatusPanel, InputBox to use palette colors.
- Update all content renderers to draw from the active theme.
- Add set_active_theme/get_active_theme helpers for runtime color access.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
19 days ago
|
Navi Code: Phase 3 — Textual TUI skeleton (OpenCode-style)
...
- Add clients/terminal/tui package with micro-architecture:
- events, context, chat_model, ws_bridge, permissions engine.
- widgets: ChatPanel, StatusPanel, InputBox.
- renderers: user/assistant messages, thinking, tool calls, errors,
markdown, plain — registry-based and extensible.
- slash commands: /help, /new, /sessions, /switch, /profile, /thinking,
/compact, /quit — registry-based and extensible.
- Wire navi-code to launch TUI by default; keep click-CLI via --raw.
- Add textual>=0.70 dependency.
- Add TUI smoke tests via Textual Pilot.
- Add docs/plan_navi_code_tui.md with full Phase 4/5 roadmap.
Tests: 463 passed, 1 skipped (excluded unrelated websocket test).
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
19 days ago
|