| 2026-07-12 |

navi_code: fix review findings 1-5 in system prompt
...
- spawn_agent default profile: correct the false "omit profile_id to use
this developer profile" — omitting profile_id inherits navi_code (the
parent), not developer; set profile_id explicitly to pick another profile.
- Safety Rules: scope strict confirmation to destructive/irreversible
operations (rm, delete, wholesale write overwrite, drop table, force-push);
state explicitly that routine edit/edit_lines do not require confirmation.
- Workflow Understand: soften the hard "start with docs/index.md" to a soft
"read notes/docs first (see NAVI.md and Documentation sections below)" so
it no longer conflicts with the NAVI.md-first entry point.
- Documentation: add a branch for projects with no docs/ — propose creating
one (with user approval) or record in NAVI.md that docs are absent/not
needed.
- Execution environment: document terminal action="run" for one-off commands
(tests, git status, lint, py_compile); persistent terminals only for
long-running processes.
Findings 6 (subagent briefing toolset), 7 (subagent delegation wording),
8 (planning/context-org tools) deferred for later work.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
6 hours ago
|
navi_code: docs as living spec + NAVI.md hints file
...
Replace the Project knowledge section with two clearer sections:
- Documentation: docs/ is the project's living specification, not just
human reference — keep it current with code, and for non-trivial changes
align docs to the intended end state before implementing (docs-first).
- NAVI.md: a lightweight, pointer-shaped hints file at project root (not a
source of truth) that tells the agent where to look; capped at ~150 lines
with a defined structure (Project / Commands / Where to start / Docs index
/ Gotchas / Open decisions), kept distinct from docs/ (spec) and memory
(global cross-project facts).
Instruction-only: the agent reads NAVI.md via filesystem; no auto-inject.
Applies to navi_code only.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
7 hours ago
|
filesystem edit: render red/green diff in TUI without changing model context
...
edit is now the primary editing method, yet its output was a dry one-line
status ("Edited …: replaced X B with Y B") while edit_lines/smart_edit showed a
highlighted unified diff. Carry the unified diff in ToolResult.metadata["diff"]
(kept out of the model-facing output, so the agent's context is unchanged) and
render it in the TUI: dim summary line plus highlighted diff (green +, red -,
dim @@). Falls back to plain text when no diff metadata is present.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
7 hours ago
|
filesystem: make edit/edit_lines the default, smart_edit a last-resort fallback
...
Agent overused smart_edit (whole-file LLM call, weak context). Rewrite the
FilesystemTool description decision tree so edit (exact text) is the default and
edit_lines (by line numbers) is the deterministic option; smart_edit is reserved
for genuinely semantic changes that cannot be expressed as exact text or line
numbers. Strengthen the old_not_unique hint to steer back to edit/edit_lines
before smart_edit. Add an "Editing policy" section to the navi_code and
developer profile prompts reinforcing the same priority.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
8 hours ago
|
tui: move filesystem tool_started info into the card body
...
Previously the action and primary path were crammed into the title
("→ filesystem read src/main.py") and the body only held the extra args,
so for simple actions (info/delete/mkdir/exists) the card body was empty.
Title is now compact ("→ filesystem <action>"). The body always carries
the information: "path: <path>" (accent) leads, "destination: <dest>"
(accent) follows for move/copy/diff, then the per-action args (range/
content/old+new/operations/instruction/pattern/question …) as before.
The card is never empty.
Tests updated: title carries action only (path is in the body),
destination lands in the body for move/copy/diff, info shows path in body,
path value is styled accent. 42 filesystem-renderer tests total. Full
suite 827 passed, 1 skipped.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
9 hours ago
|

tui: styled filesystem tool_started card — compact args, action in title
...
The generic ToolStartedRenderer dumped all of args as JSON, so filesystem
cards showed "→ filesystem" with no action in the title and the full
content/old/new text for write/edit/smart_edit flooding the card.
New FilesystemToolStartedRenderer (clients/terminal/tui/renderers/filesystem.py):
- Title carries the action and primary path: "→ filesystem read src/main.py";
move/copy/diff also append "→ <destination>".
- Body is a compact per-action summary instead of JSON:
- read: range (offset–limit) + numbered flag
- write/append: content preview (first line + "(+N lines)" hint, not full)
- edit: old + new previews
- edit_lines: operations count + op kinds (replace/delete/insert, first 5)
- smart_edit: instruction preview
- grep: pattern + glob + regex flag
- find/find_up: pattern
- query: question preview
- list: recursive flag
- info/delete/mkdir/exists: empty body (path is in the title)
- Body keys render dim, values in text.
- Sub-agent cards indented, matching ToolStartedRenderer.
Registered before the generic ToolStartedRenderer (first-match wins). The
filesystem tool, WS protocol, and events are untouched.
13 new tests cover accepts, title (action/path/destination), empty body for
info, and per-action body summaries (read/write/edit/edit_lines/grep/
smart_edit/query), content preview truncation, subagent indent, and body key
styling. 42 filesystem-renderer tests total. Full suite 827 passed, 1 skipped.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
9 hours ago
|
tui: styled filesystem find + find_up output — stage 3
...
find: the "[N matches for 'pattern' in path ⠠ …]" header plaque is dim
(warning color on ⠠ truncated); "No matches for …" renders dim; each match
line "{path} ({size})" renders the path in text, " (" and the size in
dim, and the "<dir>" marker in info.
find_up: a resolved path renders in accent; "not found (searched: …)"
renders dim.
Fallback narrowed to write/edit/append/move/copy/delete/mkdir/exists/
query/unknown. 5 new tests (find header/matches/truncated/no-matches,
find_up found/not-found); 29 filesystem-renderer tests total. Full suite
814 passed, 1 skipped.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
10 hours ago
|

tui: styled filesystem read + info output — stage 2
...
read: the "[path | N lines | size]" header plaque is now dim with the
path highlighted in accent (offset/limit plaque "… lines A–B of N …"
likewise); the "⚠ Large file …" warning line renders in warning color; the
file body renders in text (was dim — readable now) with no syntax
highlighting (rejected by design); numbered reads dim the line numbers and
render line content in text. read errors (not_found, file_too_large) render
in tool_error.
info: each "key: value" line highlights the key (incl. colon) in accent,
the alignment padding in dim, and the value in text.
Fallback narrowed to write/edit/append/move/copy/delete/mkdir/exists/find/
find_up/query/unknown (statuses and find/query intentionally untouched).
Diff/list/grep from stage 1 unchanged.
6 new tests (read plaque/offset/warn/numbered/error, info keys+values);
24 filesystem-renderer tests total. Full suite 809 passed, 1 skipped.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
10 hours ago
|

tui: styled filesystem tool output (diff / list / grep) — stage 1
...
The TUI rendered every tool result as a single dim Text in a Panel — no
special handling for filesystem, so unified diffs from edit_lines/smart_edit/
diff were shown as plain grey text (the existing DiffRenderer only fires on
type:"diff", which filesystem never emits), directory listings were an
unaligned text blob, and grep matches had no pattern highlighting.
New FilesystemToolResultRenderer (clients/terminal/tui/renderers/filesystem.py)
intercepts filesystem tool_call events by tool=="filesystem" + args.action:
- diff / edit_lines / smart_edit: reuse a shared highlight_unified_diff()
helper (extracted from DiffRenderer) — + green, - red, @@ dim; the
"Applied …" summary line of edit_lines/smart_edit is separated from the
diff body via a Group; "Files are identical." renders dim.
- list: header plaque dim (warning color on ⚠ truncated); directories
shown as "▸ name/ (n items)" in info color; files as name (text) +
size (accent) + time (dim), preserving the tool's fixed-width alignment;
"?" entries in warning; "(empty directory)" dim.
- grep: header plaque dim; "rel:line:" location dim; matched pattern
occurrences highlighted in accent (case-insensitive, re.escape'd);
"No matches …" dim.
- read / info / write / edit / append / move / copy / delete / mkdir /
exists / find / find_up / query / unknown: plain dim fallback (unchanged
for now — stage 2). Errors (success=False): plain in tool_error color.
Registered before the generic ToolResultRenderer (first-match wins). The
filesystem tool, WS protocol, events, and webclient are untouched.
22 new tests in tests/clients/test_filesystem_renderer.py cover accepts,
diff/edit_lines/identical/error, list (dir/file/truncated), grep
(pattern/no-matches/no-pattern-arg), fallback, title+status, subagent
indent. DiffRenderer behavior unchanged (existing test still passes).
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
10 hours ago
|

docs: index, profiles, tools, api actualization + archive historical docs
...
index.md: expand the file map to reference navi_code, navi_code_cli, store,
context_providers, eval_system, android-client, testing; point at archive/
for historical notes.
profiles.md: add the Compression section (compression_keep_recent /
compression_max_tokens / compression_prompt_file overrides), the
subagent_system_prompt field, and a note that AgentProfile allows unknown
keys (model_config extra=allow).
tools.md: rewrite the user-tools self-extension section — write_tool is
deprecated and removed; write the file via filesystem/code_exec and call
reload_tools instead.
api.md: add missing REST endpoints (GET /sessions/{id}/todos, GET
/sessions/{id}/files list, GET /sessions/{id}/messages/archive, POST
/sessions/{id}/stop) and the admin MCP management block (config CRUD,
reconnect, status, test, profile-mcp mapping, admin recalls); fix the
WS client→server table (type: message|compact, image limits 8/50MB);
add model_info / todo_updated / compression_started events; fix
recall_update action (add skipped), session_sync payload, context_compressed
threshold (70%).
Archive: move plan_01_god_object_agent.md, tech_debt_review_2026-04-29.md,
architecture_weak_spots.md, future_headless_nodes.md into docs/archive/
(historical design notes, no inbound links).
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
11 hours ago
|

docs(navi-code-cli): actualize TUI to current code
...
Rewrite the TUI section for the post-Jul-10 feature avalanche:
- Layout: five regions (ChatPanel + Vertical(StatusPanel, TodoPanel) +
InputBox + bottom StatusBar); SessionsPanel removed, sessions via modal
picker. StatusPanel now shows Profile/Session/Model/Connection/Backend/
Theme/hint (no Tokens/Iter).
- StatusBar: activity indicator + live elapsed timer + context-fill gauge.
- TodoPanel: live, sorted (in_progress → pending → failed/skipped → done),
subagent-isolated.
- Per-message widgets, markdown rendering, bounded history render cost,
session history load on resume, WebSocket auto-reconnect.
- Slash-command hints (Up/Down/Enter/Tab), command palette (Ctrl+P),
permission dialog, !shell passthrough, @file refs.
- Compression summary card, request-duration metadata, model_info display.
- Keybindings table (Ctrl+P / Ctrl+X C|T|Q / Esc).
- Commands: add aliases (clear, resume/continue, exit/q, save); fix /clear
(alias of /new), /sessions (picker), /switch (hybrid); add /compact.
- --resume <session_id> flag + post-exit resume hint.
- Full event rendering list (stream_start/end/stopped, model_info,
todo_updated, compression_started, context_compressed, …).
- Full file map (ws_bridge, chat_model, screens/, permissions, shell_runner,
file_refs, duration, …).
navi_code.md left as-is (already current with bounded autonomy).
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
11 hours ago
|
docs(websocket): /compact control message, new events, fixes
...
- Document the {"type":"compact"} forced-compression control message
(bypasses threshold, no stream_start, rejected if a run is active,
TUI /compact + Ctrl+X C).
- Fix image limits: 8 images, 50 MB total payload (was 10 / 5 MB each).
- tool_started/tool_call: document metadata + tool_call_id fields.
- recall_update action: add skipped (scheduled|cancelled|skipped|fired|
rescheduled).
- session_sync: document the session_id/profile_id payload.
- Add missing events: model_info, todo_updated, terminal_output,
terminal_closed.
- Document close code 4003 (auth/access denied) alongside 4004.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
11 hours ago
|

docs: actualize compression mechanics + real-token baseline
...
mechanics.md: rewrite the Context Compression catalog (adaptive turn
importance, intra-turn fallback, would_compress guard, token-budget
hard-truncate, per-message view truncation, profile-aware overrides,
real-token baseline estimator, meta-summary, archive-on-compress,
CompressionStarted/ContextCompressed events); fix Agent Loop rows
(run() delegates to run_stream, planning entry condition, pre/mid-turn
gates, check_context_size, forced /compact, estimate chars//3 in
compressor.py); fix WS image limits (8 / 50MB) and add /compact control
message; rebuild the Undocumented Mechanics Summary from current ❌ rows;
refresh the cross-reference index.
config.md: LLM_STREAM_FIRST_CHUNK_TIMEOUT 180→90; add
CONTEXT_MESSAGE_TOKEN_BUDGET.
agent.md: run() runs planning; full run_ephemeral signature + compact_stream
entry point; cwd ContextVar; planning entry condition; loop pseudocode
(midturn compression, check_context_size, ModelInfo, real baseline);
streaming guard 90s; workers carry profile; pre-turn estimate-based gate;
per-message view truncation.
sessions.md: full Message flag table (is_context/is_display/is_compression_critical
…); three compression trigger points + forced /compact; real-baseline
estimate; check_context_size guard; expanded algorithm (adaptive partitioning,
intra-turn fallback, meta-summary, 24k cap, 4000-char critical preview,
token-budget hard-truncate fallback, archive-on-compress, baseline clear);
compression events; SessionStore archive methods + list_page profile_id.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
11 hours ago
|
compression: profile-aware worker + real-token baseline estimator
...
Item 2 — thread the active profile into CompressionWorker so
compress_context applies per-profile overrides (compression_keep_recent,
compression_max_tokens, compression_prompt_file). navi_code now compresses
with keep_recent=12 instead of the global 8.
Item 1 — estimate the next LLM call's context from the *real* prompt_tokens
of the previous call (bulk) plus a heuristic delta for messages appended
since, replacing the chars//3 estimate that undercounts code-heavy tool
output and fired midturn compression too late (Navi kept working until the
window was exhausted). Baseline is recorded after each stream and cleared
after compression; check_context_size and the midturn gate use it, with a
heuristic fallback when no baseline exists or the context shrank.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
11 hours ago
|

compression: fix auto-compress no-op on few-huge-messages + honest status
...
Root cause: the compression gate (should_compress) measures tokens, but the
partition measures message/turn count, and CompressionStarted was emitted
before the attempt. For navi_code's "few very large messages" shape (one big
file read = 1 user + assistant + 1 huge tool result, 66k tokens in 3 messages)
the gate fired, the UI showed "compression", but partition returned
to_summarize=[] -> compress_context None -> nothing shrank. The agent kept
going until the window overflowed. It wasn't running "during" compression —
there was no compression, just a no-op the user mistook for one.
A. Per-message head/tail truncation in context_builder.build(): oversized
tool/assistant messages (over context_message_token_budget, 0=num_ctx//6)
are capped head+marker+tail in the LLM view only (model_copy — stored
history and reloads are never affected). A single huge tool result can no
longer alone blow the window; user/system messages are never truncated.
B. Token-budget hard-truncate fallback in compress_session: when partition
no-ops but tokens exceed the threshold, drop oldest turns to num_ctx*0.5.
_hard_truncate is now token-aware (was a fixed message-count floor that
no-oped on <=6 messages even when huge). New would_compress() predicts
compress_session's real outcome with no LLM call.
C. Honest CompressionStarted: _compression_events_midturn/_preturn emit it
only after would_compress() confirms the partition (or token-budget
fallback) can actually shrink the stored context — no more "compression"
status with no ContextCompressed to follow.
Bonus: post-turn CompressionWorker now passes keep_recent_messages=
max(12, context_keep_recent*2), matching the midturn path, so a single long
autonomous turn compresses post-turn too (was always a no-op).
Tests (+14): would_compress agreement, token-budget fallback, token-aware
hard_truncate, build() truncation (preserves user, no mutation, head+tail),
agent no-CompressionStarted-when-nothing-to-compress, worker single-long-turn.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
11 hours ago
|

Navi Code TUI: show context-compression summary in the chat
...
The server already sent the summary text in ContextCompressed.summary, but the
TUI never showed it — forced /compact printed a bare "N → M messages" line and
mid-turn auto-compress produced no chat feedback at all. Now both render a
distinct bordered block headed "Context compressed: N → M messages" with the
summary text (markdown) inside, so the user can see what the compressor kept.
- chat_model: new context_summary kind; context_compressed creates a chat item
carrying the summary + before/after counts (was explicitly ignored).
- renderers/summary: ContextSummaryRenderer — dim bordered panel, markdown body.
- chat_panel: _item_msg mapping for context_summary.
- tui_app: emit the summary item on context_compressed for both forced and
mid-turn cases; drop the now-redundant one-line status (the block header
carries the counts). Spinner start/stop/label logic unchanged.
- Tests: chat_model mapping + renderer (accepts/counts/text/missing-counts).
Summaries are live-only — not rebuilt on session reload (the compressor stores
them is_display=False, same as before for compression events).
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
12 hours ago
|
| 2026-07-11 |

Navi Code: force context compression via typed /compact control message
...
Forced /compact previously sent a chat message, which ran a full agent turn
that only produced summary text instead of running the real context compressor.
Worse, even when wired correctly, forced compact always reported "Nothing to
compact yet — the context is still small" regardless of context size: the typical
navi_code shape is a single long autonomous turn (1 user message + many tool
iterations = one turn), and partition_messages finds nothing to summarize when
turns <= keep_recent. The midturn auto-compress path already bypassed this via
keep_recent_messages (intra-turn split), but compact_stream passed
keep_recent_messages=None, so the fallback was disabled.
Changes:
- WS protocol: {"type":"compact"} control message (distinct from {"type":
"message"}); rejected while an agent turn is active to avoid racing the agent.
- Agent.compact_stream: forced compression that bypasses the token threshold
but still runs the real compressor; passes keep_recent_messages=max(12,
context_keep_recent*2) so a single long turn compresses via intra-turn split
(mirrors midturn auto-compress). Raises NothingToCompactError when context is
genuinely too small.
- Orchestrator.run_compact + clear_run: broadcast agent events to subscribers,
end with done marker, surface NothingToCompactError as an error event.
- Terminal client: ws_client.send accepts str|dict; CompactCommand enqueues
{"type":"compact"}; TUI distinguishes forced compact (no stream_start) from
in-turn auto-compress via the _streaming flag.
- Tests: compact_stream (incl. single-long-turn regression), WS handler
dispatch/rejection, run_compact event/error broadcasting, ws_client send,
compact command.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
23 hours ago
|
tui: remove the useless NaviCodeTui Header bar
...
The default Textual Header just shows the class name — no information value,
and it costs the top screen line. Drop it from compose (and the now-unused
import) so the chat panel starts at the very top.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
1 day ago
|
tui: per-message chat widgets — render only the streaming bubble
...
ChatPanel used to hold a single Static rebuilt via update(Group(...)) on every
event, so a per-token stream_delta re-rendered all visible items (up to 200).
Now each message is its own _ChatItemView(Static); _sync() mounts new widgets at
the end, removes dropped ones, and signature-gated maybe_update re-renders only
the changed widget. On a stream only the streaming bubble repaints — the rest
stay mounted untouched. Public API stays synchronous (mount/remove are sync in
this Textual version), so tui_app is unchanged. Truncation hint is now a
dedicated top widget toggled via styles.display.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
1 day ago
|
tui: fix 'Connection: online online' duplication
...
The status panel renders 'Connection: online {detail}'; the supervisor was
passing detail='online' on a successful connect, so the label read
'online online'. The label already conveys the state — send an empty
detail on success (matching the pre-reconnect behaviour). Reconnecting/offline
details are unaffected since they carry a reason distinct from the label.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
1 day ago
|
tui: auto-reconnect WebSocket with exponential backoff
...
A dropped server socket no longer leaves the TUI stranded. WsBridge now
runs a supervisor that connects, forwards events until the socket closes,
then backs off and reconnects indefinitely — the only thing that ends it is
stop(). The status panel flips to 'reconnecting…' and the next message the
user sends is held in the input queue until a fresh socket is live, so a
brief blip doesn't eat their input (send failures requeue + force a
reconnect; nothing is lost).
Backoff: 1s→2s→4s… cap 30s, reset on success; stop() cancels it promptly.
Interface preserved (start/stop/.client/.connected); an optional client=
param lets tests inject a fake client.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
1 day ago
|

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
|
tui: sort todo panel — in_progress on top, done at bottom
...
Group todo steps by status for display: in_progress → pending →
failed/skipped → done. Original payload order is preserved within each
group (stable sort), and self._tasks is not mutated so step index still
matches the plan — only the on-screen order changes. Unknown statuses
fall in with pending so new work stays visible.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
1 day ago
|

Isolate sub-agent todo + render live todo in TUI side panel
...
Phase 1 — sub-agent todo isolation (backend):
- Add current_todo_session_id ContextVar; subagent_runner scopes it to the
sub-agent's ephemeral run id so its auto-populated plan and todo updates
land in an isolated KV row instead of clobbering the parent session's todo
(which the parent's goal-anchoring reads every iteration).
- todo._sid() and planning.set_tasks prefer current_todo_session_id; the
parent run leaves it unset, so all existing todo consumers (anti-stall,
goal anchor, get_progress_message) behave exactly as before.
Phase 2 — live todo in the TUI right column:
- TodoUpdated event + emit it from the agent loop after planning auto-populate
and after each tool-execution turn.
- GET /sessions/{id}/todos reads the parent session's todo KV row (explicit
user_id/session_id, optional injected kv).
- api.get_todos + TodoList/TodoPanel widgets: status-coloured markers
(pending dim, in_progress accent+bold, done success, failed error, skipped
dim), progress header, scrollable panel below the auto-height info block.
- Hybrid delivery: REST seeds the panel on attach/switch, todo_updated WS
events update it live.
Sub-agent todos as nested sub-lists is deferred to a later phase.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
1 day ago
|
Navi Code TUI: drop broken ctrl+x n / ctrl+x l session keybinds
...
Remove the non-working session-switching keybinds ctrl+x n (New) and
ctrl+x l (Sessions) and their action methods; /new and /sessions are still
reachable by typing them (with the inline hints) or via the palette. The
keybind field is cleared on both commands so hints/palette stop showing
them. ctrl+x q/c/t (quit/compact/thinking) are left intact.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
1 day ago
|
Navi Code TUI: unify session commands on shared workers; /switch hybrid
...
Route /new, /sessions, and /switch through shared app-side logic instead of
each command reimplementing the switch path:
- _open_sessions_picker(): pushes SessionsPickerScreen and wires the select
callback to _switch_session_worker / _create_new_session_worker. Both
/sessions and /switch (no/ambiguous arg) use it.
- /new -> _create_new_session_worker (was: inline create + attach + clear).
- /switch <prefix>: resolve to a single navi_code session (exact id, then
prefix match) and switch directly via _switch_session_worker; no/ambiguous/
unknown arg opens the picker pre-filtered to what was typed. This removes
the latent clear()-after-attach bug from the old SwitchCommand (clear erased
the history that attach_session had just replayed).
- SessionsPickerScreen gains initial_query to open pre-filtered.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
1 day ago
|
Navi Code TUI: sessions picker for /sessions (navi_code, full switch)
...
Replace the chat-printed session list with a modal picker:
- SessionsPickerScreen lists only navi_code-profile sessions (filtered by
settings.default_profile_id), with a filter input, a top "✚ New session"
row, and the current session marked. Up/Down + Enter to pick, Esc cancels.
- /sessions pushes the screen. Selecting an existing session runs
_switch_session_worker (persist via StateManager + attach_session, which
replays history and restarts the WS bridge — no chat_panel.clear() after,
since load_history already replaces the chat and clearing would erase the
replayed history). The "New session" row runs _create_new_session_worker.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
1 day ago
|
Navi Code TUI: interactive slash-command hints (Up/Down + Enter)
...
Make the inline command hints navigable:
- Up/Down move a highlight through the matching commands (wraps around).
- Enter while a hint is open runs the highlighted command (routed through
UserSubmitted as /<name>, so the app's _run_command handles it — not sent
to the agent). Enter with hints closed still submits the raw text.
- Tab completes the input to the highlighted command's canonical name and
stays in the field for typing args (was: always the first match).
CommandHints stays a non-focusable Static (renders the highlighted line with
reverse video); _PromptInput owns all key handling via a sibling reference.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
1 day ago
|
Navi Code TUI: inline slash-command hints + Tab completion
...
Show a non-interactive list of matching commands above the input box while
the user types a '/'-command (no whitespace yet). Tab completes the prefix to
the canonical name of the top match. Enter already routed '/...' through
_run_command, so submitting a typed command executes it instead of sending
it to the agent — unchanged.
- CommandRegistry.match(prefix): case-insensitive prefix match on name and
aliases, exact match sorted first; empty prefix returns all.
- CommandHints(Static): purely visual, never takes focus, hidden by default.
- InputBox composes hints above the prompt and refreshes them on
TextArea.Changed.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
1 day ago
|
Navi Code TUI: remove sessions table from right column
...
Drop the SessionsPanel widget and all dead code wired to it (handlers,
broadcast helper, session-list events, _refresh_sessions worker). The
/new, /sessions, /switch commands are preserved — they already operate
via app.attach_session / chat output rather than the panel.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
1 day ago
|