| 2026-04-09 |

Live tool visibility: pending cards, sub-agent step log
...
Backend:
- ToolStarted event: emitted before tool execution begins so client
can render a pending card with spinner immediately
- ToolEvent gains is_subagent flag; ToolStarted same
- current_event_sink ContextVar in tools/base.py — run_stream() sets it
to an asyncio.Queue before create_task(); run_ephemeral() reads it and
puts ToolStarted/ToolEvent into the queue as each sub-agent step runs
- run_stream() tool loop: sequential execution via create_task() +
polling drain loop (20ms sleep); yields ToolStarted → sub-agent events
from sink → ToolEvent (completed) for each tool call
- run_ephemeral() rewritten to inline sequential tool execution with
sink emission (replaces _execute_tool_calls gather)
- _run_single_tool() helper extracted for run_stream()
- websocket.py handles tool_started and adds is_subagent to tool_call
Frontend:
- appendPendingToolCard(): creates card with spinner; spawn_agent opens
body immediately to show sub-agent log as it fills
- finalizeToolCard(): fills result, removes spinner, adds toggle; strips
"[Sub-agent result — ...]" reminder prefix from displayed text
- appendSubagentStep() / finalizeSubagentStep(): live step log inside
spawn_agent card — each sub-agent tool call gets a ↳ row
- app.js: tool_started → pending card; tool_call → finalize card;
is_subagent routing to sub-step vs main card; abandonStream() resets
pendingToolCard/pendingSubStep
- CSS: .spinner-inline for card headers; .subagent-log / .subagent-step
for nested step display; .tool-body-open for always-open spawn_agent
body; .tool-card.pending suppresses chevron
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 9 Apr
|
spawn_agent: fix model behavior — synthesis reminder + lower delegation threshold
...
- ToolResult.output now prefixed with explicit reminder that the user
cannot see sub-agent output and the orchestrator must present findings
in its own final response; reminder appears adjacent to the result so
the model reads it in context
- spawn_agent description updated: lowers threshold from "3+" to "2+"
tool calls, makes USER CANNOT SEE warning prominent, tightens wording
- persona.txt DELEGATION section: clearer rule (default to spawning for
multi-step sub-tasks), explicit "never end turn after spawn results",
removed abstract threshold in favour of concrete examples
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 9 Apr
|
Add spawn_agent: sub-agent delegation with isolated context
...
- Agent.run_ephemeral() — runs a sub-agent loop without a persistent
session; accepts exclude_tools to block recursion; logs start/complete
- session_store made Optional in Agent.__init__ (None for ephemeral runs)
- SpawnAgentTool (navi/tools/spawn_agent.py): spawns an isolated Agent
for a focused task; resolves profile from parent session via ContextVar;
blocks spawn_agent recursion via exclude_tools=["spawn_agent"]
- build_default_registries() accepts session_store param; registers
SpawnAgentTool after BackendRegistry is built (patches _backend_registry)
- deps.py passes _session_store to build_default_registries
- All profiles: spawn_agent added to enabled_tools, max_iterations 10→30
- persona.txt: DELEGATION section — when/how to use spawn_agent
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 9 Apr
|
SSH connection pooling: per-session, 20-minute TTL
...
- Pool keyed by session_id:host:port:username — parallel sessions share
no state even when targeting the same server
- Per-key asyncio.Lock prevents concurrent connection creation races
- TTL (20 min) and is_closing() checked on every access; expired/closed
connections are evicted and replaced transparently
- On disconnect error during command execution: evict + retry once with
fresh connection
- current_session_id ContextVar (set by Agent before tool calls) is read
in ssh_exec to build the pool key without changing tool signatures
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 9 Apr
|

Add long-term user memory system
...
Architecture:
- navi/memory/store.py: MemoryStore backed by SQLite (memory_facts,
memory_summary, session_memory_state tables in navi.db)
- navi/memory/extractor.py: LLM-based fact extraction from sessions +
summary regeneration (triggered after session goes idle >30 min)
- Fact upsert uses UNIQUE(category, key) — same key always overwrites,
no duplicates or stale contradictions
- Keyword search across category + key + value (LIKE-based, no extra deps)
Context injection:
- Memory summary injected as an ephemeral system message on every LLM call
via Agent._with_memory() — never persisted to session.context
Tools (all profiles):
- memory_search(query): keyword search against fact DB; persona instructs
model to call it at session start and before personal-context questions
- memory_forget(key, category?): delete a specific fact on user request
Extraction trigger:
- On new session creation, fire-and-forget background task checks all
sessions idle >30 min with unprocessed messages → runs extraction
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 9 Apr
|
Add web_view tool: headless browser with text extraction and screenshot
...
- New built-in tool web_view: opens URL in headless Chromium via Playwright,
strips nav/footer/scripts, returns clean readable text (capped at 20k chars).
Optional screenshot=true returns a PNG injected into context as an image.
Handles JS-rendered pages and SPAs (waits for networkidle by default).
- http_request description updated: explicitly says to use web_view for human-
readable pages, http_request for APIs/JSON/custom auth.
- web_view added to all three profiles.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 9 Apr
|
| 2026-04-08 |
Wire self-extension tools into all profiles; improve tool descriptions
...
All profiles now include write_tool, list_tools, tool_manual, reload_tools.
User tools from enabled.json merged in at runtime via Agent._tool_list().
Built-in tool descriptions rewritten to be more LLM-actionable.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 8 Apr
|
Add self-extension tool system: write_tool, list_tools, tool_manual
...
- loader.py: module-level format (name/description/parameters/execute)
preferred, class-based as fallback; isolated errors per file
- write_tool: validates + writes tools/name.py, reloads registry,
adds to tools/enabled.json in one call
- list_tools: live tool list from registry (prevents hallucination)
- tool_manual: serves manuals/*.md or auto-generates from schema
- reload_tools: hot-reload without server restart
- registry: registry injection pattern for tools that need it;
_builtin_names set to guard against reload overwriting builtins
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 8 Apr
|

Add multimodal image support and client UX improvements
...
Server:
- Add ImageViewTool (load image from file/URL, returns base64)
- Add images field to Message model with created_at timestamp
- Agent run/run_stream accept images param; inject image messages after image_view tool calls
- WebSocket handler accepts images array from client, strips data URI prefix
- All profiles include image_view tool
- Fix tool call serialization (model_dump mode=json for datetime)
- Add no-store cache headers for static files
Client:
- Image attachment: file picker button + clipboard paste + preview strip with remove
- Images rendered in chat bubbles; loaded from history
- Tool cards rebuilt as div+CSS toggle (fixes details/overflow-hidden collapse bug)
- Tool cards appear before response bubble (lazy bubble creation on first stream_delta)
- Typing indicator persists through tool calls, removed only when text starts streaming
- Tool cards restored from history on page reload
- Message timestamps stored via created_at field, shown correctly in history
- Session ID reflected in URL hash for bookmarking; restored on page load
- Remove localStorage session tracking (server last_active used instead)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 8 Apr
|
ssh_exec: accept credentials directly as tool parameters
...
host, username, password, port, key_path are now first-class parameters.
No config file needed — user can pass creds in the chat message.
Ad-hoc connections skip host key verification by default.
Named connections in ssh_hosts.json still work as a shortcut.
Eugene Sukhodolskiy
committed
on 8 Apr
|
Fix SSH password auth: disable key lookup when password is configured
...
asyncssh tried ~/.ssh/* keys before the password, causing PermissionDenied
on hosts that only accept password auth. Now when 'password' is set and no
'client_keys', key auth is disabled entirely.
Eugene Sukhodolskiy
committed
on 8 Apr
|
Filesystem tool: unrestricted mode by default
...
FS_ALLOWED_PATHS=* (default) allows any path, consistent with terminal.
Path check is now lazy (per-request) instead of module-level,
so config is always fresh after restart.
~ expansion added.
Eugene Sukhodolskiy
committed
on 8 Apr
|
Unrestricted terminal mode and SSH tool
...
- Terminal: TERMINAL_ALLOWED_COMMANDS=* (default) runs via shell,
supports pipes, redirects, subshells; allowlist mode still available
- FS_ALLOWED_PATHS expanded to cover /home /etc /var /opt
- New ssh_exec tool: execute commands on remote hosts via asyncssh,
supports named connections (ssh_hosts.json) and inline user@host
- ssh_hosts.json gitignored, ssh_hosts.json.example added as reference
- ssh_exec added to server_admin and smart_home profiles
Eugene Sukhodolskiy
committed
on 8 Apr
|
Initial implementation of the agent system core
...
- FastAPI server with REST API and WebSocket streaming
- Modular LLM backend abstraction (Ollama implemented, OpenAI stub)
- Tool system: web_search (ddgs), filesystem, http_request, code_exec, terminal
- Agent profiles: smart_home, server_admin, secretary
- Tool-calling loop with concurrent tool execution
- In-memory session store with SessionStore ABC for future persistence
- Registry pattern for tools, profiles, and backends
- Orchestrator stub as foundation for multi-agent scenarios
Eugene Sukhodolskiy
committed
on 8 Apr
|