| 2026-05-14 |
Add session search across messages with backend + frontend
...
Backend:
- GET /sessions now accepts `search` query param
- _session_summary computes match_indices and match_preview from messages
- pg_session_store: messages ILIKE added to search_list and count_all
- In-memory store: search_list also filters by message content
Frontend:
- AppSidebar: search toggle icon + debounced input, Ctrl+K shortcut
- SessionItem: highlight matching text, show match_preview from search
- SessionList: pass searchQuery to SessionItem
- SessionsStore: searchQuery/searchActive state, setSearch/clearSearch
- API layer: getSessions accepts search param
- MessageList: scroll to target message + brightness flash animation
- ChatStore: loadSession accepts targetMessageIndex, scrollToMessageIndex ref
- CSS: msg-flash keyframe animation in app.scss
- Tests updated for new getSessions signature
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 14 May
|
Rebuild dist for tool card UX improvements
...
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 14 May
|
Compact and improve tool/thinking/plan card UX
...
- ToolCard: remove emoji header, collapse Arguments behind <details>,
render results with structured JSON (color-coded values) or markdown
detection for string outputs.
- SubagentStep: mirror ToolCard compact layout with same helpers.
- AssistantMessage: fold tool lists when >3 tools — show last 3 + summary
bar with count and toggle icon-button; TransitionGroup for smooth
expand/collapse animations.
- Plan card: switch accent color from info to secondary, compact sizing.
- Thinking card: compact sizing, remove bottom margin.
- app.scss: add details::details-content animation, fix nested chevron
rotation in subagent steps, adjust margins and input-bar padding.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 14 May
|
Markdown images: adaptive 3-column grid, lightbox modal, and broken-image handling
...
- useMarkdown.js: custom marked renderer wraps images in clickable links with
inline onerror for broken-image detection
- app.scss: .msg-assistant-content becomes flex-wrap container; image paragraphs
sized to 3-per-row via calc((100% - 16px) / 3); images are square via
aspect-ratio: 1 / 1 and object-fit: cover
- ImageLightbox.vue: rewritten with proper gnexus-ui-kit .modal/.modal-dialog
DOM structure; broken images show error placeholder inside modal
- AssistantMessage.vue: attachImageLightbox() wired after v-html render
- Broken images: .is-broken class prevents lightbox click; CSS shows 🖼️ icon
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 14 May
|
| 2026-05-13 |
Persist uploaded files in messages, live file tree updates, and UI polish
...
Backend:
- Add `files` field to `Message` model so uploaded file metadata survives page refresh
- Pass `files` through websocket handler → `agent.run_stream` / `agent.run`
- `list_tools`: make `profile_id` required; return error instead of all-tools fallback
Webclient:
- Call `fetchFiles()` after successful file upload for immediate Files tab update
- Live refresh file tree on filesystem (write/edit/append/mkdir/rm/cp/mv), terminal, and code_exec tool calls
- Add manual refresh button (desktop) and pull-to-refresh (mobile) to Files tab
- Fix live link updates: move regex creation inside per-message loop to avoid lastIndex state leak
- Restore full profile name text next to avatar in ChatHeader; hide avatar in header
- Fix mobile ArtifactsPanel: collapse tab text labels so close button fits with 3 tabs
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 13 May
|
Defensive image cleanup in Ollama backend to prevent 'unknown format' errors
...
- _clean_base64_image() strips data URI prefix and validates non-empty result
- _to_ollama_messages() filters out invalid/empty images before sending to Ollama
- Prevents 500 errors when models receive malformed or unsupported image data
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 13 May
|
Fix profile icon class in WelcomeScreen — prepend 'ph' prefix
...
GnAvatar's :icon prop expects the full Phosphor class (e.g. 'ph ph-briefcase'),
not just the icon name. profileIcon() now returns 'ph ${cls}'.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 13 May
|
Add session file directory listing endpoint and Files tab in ArtifactsPanel
...
Backend:
- New GET /sessions/{session_id}/files endpoint (recursive, max depth 10)
- Includes hidden files, returns {path, size, is_dir, modified_at}
- Path traversal protection via resolve() + relative_to(base)
- list_session_files() helper in session_files.py
Webclient:
- Third "Files" tab in ArtifactsPanel alongside Artifacts and Links
- Tree display with depth-based indentation
- File type icons by extension (image, video, code, etc.)
- Download and inline-open actions per file
- Fetch on session load/reload via chatStore.fetchFiles()
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 13 May
|
Fix GnAvatar usage: use props (src/icon/initials) instead of default slot
...
GnAvatar render function ignores default slot content; it only reads
src, icon, and initials props. Fixes broken user avatar image display.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 13 May
|
Migrate avatars to GnAvatar component from gnexus-ui-kit
...
- ProfileBadge.vue: GnBadge → GnAvatar with profile initials
- AppSidebar.vue: custom user-avatar/img → GnAvatar with image or fallback initial
- WelcomeScreen.vue: profile-icon → GnAvatar with Phosphor icon + secondary variant
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 13 May
|
Add Links tab to ArtifactsPanel and restyle to gnexus-ui-kit design system
...
- Extract markdown + bare URLs from assistant messages, deduplicate, show in new Links tab
- Add tab switcher (Artifacts / Links) with counts in header
- Add copy-all and open-all link actions
- Full style migration to gnexus-ui-kit palette:
- surface-page #16161E, borders 2px rgba(192,202,245,0.24)
- accent color #FF9E64, hover/active #7AA2F7
- tabs: uppercase, bold, border-right separators
- list items: 2px transparent border, surface-panel-muted bg
- action buttons: 2px border, electric-blue hover
- zero border-radius throughout
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 13 May
|
Add MCP admin endpoints for config, reconnect, status, test, and profile group management
...
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 13 May
|
Add profile_id support to list_tools
...
ListToolsTool now accepts an optional `profile_id` parameter. When
provided, it returns only the tools enabled for that specific profile
(enabled_tools + user tools + resolved MCP tools). This helps the agent
preview what a profile can do before switching.
- Updated ListToolsTool.execute() with profile-aware filtering
- Patched _profile_registry in build_default_registries
- Patched _mcp_manager in main.py startup loop
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 13 May
|
Fix gnexus-book MCP instructions and add old-format fallback in tool executor
...
- Updated mcp_servers.json gnexus-book instructions to use mcp:gnexus-book:
prefix instead of the old mcp_gnexus-book_ format.
- Added fallback in tool_executor.py for old underscore format
(mcp_server_tool → mcp:server:tool) so transitional models still work.
- Added unit test for the old-format fallback.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 13 May
|
Set browser tab title to active session name or id
...
In App.vue: added computed `documentTitle` and a `watch` that updates
`document.title` whenever the active session changes or its name is
updated. Falls back to session id prefix (8 chars) when unnamed.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 13 May
|
Generate session titles in the user's language
...
Adds "Respond in the same language as the user's messages" to the
session title generator system prompt so titles match the conversation
language instead of defaulting to English.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 13 May
|
Fix profile MCP server groups to use group names instead of tool names
...
Profile configs were listing individual tool names (web_view, http_request)
in mcp_servers.navi-web instead of group names (browse, request). This caused
resolve_group() to return empty results, so MCP tools never appeared in the
profile's resolved tool list.
Also fixes modeler_3d stale tool references in system_prompt.txt.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 13 May
|
Fix agent.py _tool_list to use colon-delimited MCP names
...
The main registry and API routes were migrated, but Agent._tool_list
still built names with the old underscore format. This meant MCP tools
were silently dropped from the tool list passed to the LLM, causing
"tool not found" when the model correctly called mcp:server:tool names.
Also updates stale docstring in McpTools.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 13 May
|
Rename MCP tools to mcp:server:tool format and restore human-readable names
...
- Core naming: mcp_server_tool → mcp:server:tool (colon-delimited)
- navi-web tools: search/view/request → web_search/web_view/http_request
- navi-3d tools: compile_scad/render_stl/lint_scad (unchanged names)
- Updated all profile configs, system prompts, docs, manuals, tests
- Added new lint_scad.md manual
- Fixed modeler_3d prompt stale references (scad_lint, model_3d, render_3d)
- All 240 tests pass
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 13 May
|
Clean up remaining web_search / web_view / http_request references
...
- Deleted stale source files: navi/tools/web_search.py, web_view.py,
http_request.py (no longer imported or registered).
- Updated system_prompt.txt in all profiles (secretary, server_admin,
discuss, modeler_3d subagent) to reference mcp_navi-web_* tool names.
- Updated key_tools in developer, secretary, server_admin config.json.
- Updated docs (tools.md, profiles.md, api.md) to reflect MCP migration.
Tests: 240 passed.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 13 May
|
Rename navi-web MCP tools and compact search output
...
- web_search → search, web_view → view, http_request → request
This removes the redundant 'web' prefix from tool names in the
navi-web MCP server, making them cleaner: mcp_navi-web_search etc.
- Compact search output: output string now contains only
[Source] + [N] Title — URL, without duplicating the body snippet.
Full results with body/description remain in metadata for
programmatic use.
- Updated mcp_servers.json groups and all profile configs.
Tests: 240 passed.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 13 May
|
Migrate web tools (web_search, web_view, http_request) to navi-web MCP server
...
New MCP server: mcp-servers/navi-web/
- app/search.py — SearXNG primary, DDG fallback, Brave tertiary
- app/browse.py — Playwright headless browser page extraction
- app/request.py — httpx raw HTTP requests
- app/mcp_server.py — FastMCP entry point with stdio transport
- pyproject.toml — deps: mcp, httpx, ddgs, playwright, pydantic
Changes:
- Added "navi-web" block to mcp_servers.json (stdio transport)
- Removed web_search, web_view, http_request from built-in registry
- Removed them from navi/tools/__init__.py
- Removed them from enabled_tools / subagent_tools in all profiles
- Added "navi-web": ["search", "browse", "request"] to mcp_servers
in all profiles (developer, secretary, server_admin, tool_developer,
modeler_3d, discuss)
Tests: 240 passed.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 13 May
|
Fix navi-3d MCP tool coroutine serialization error
...
All three tool handlers (compile_scad, render_stl, lint_scad) were
calling async core functions without await from synchronous def bodies.
This caused FastMCP to receive a coroutine object instead of a dict,
which then failed JSON serialization with:
Object of type coroutine is not JSON serializable
Fix: convert tool handlers to async def and await the underlying
compile_scad / render_stl / lint_scad calls before passing to _json().
Tested via stdio_client — lint_scad now returns clean JSON result.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 13 May
|
Fix navi-3d MCP tool name mismatch
...
The MCP server registered tools with `_tool` suffix (e.g. lint_scad_tool)
but mcp_servers.json groups listed bare names (lint_scad). This caused
_tool_list() to look for mcp_navi-3d_lint_scad which never existed in the
registry — the actual registered tool was mcp_navi-3d_lint_scad_tool.
Fix: explicitly set name= on @mcp.tool() decorators so MCP tool names
match the group whitelist in mcp_servers.json.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 13 May
|
Set navi-3d MCP server to stdio transport via env var
...
Adds NAVI_3D_MCP_TRANSPORT=stdio to mcp_servers.json so the server
starts in stdio mode instead of defaulting to SSE (uvicorn).
Prevents uvicorn access logs from leaking into stdout and breaking
JSON-RPC message parsing.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 13 May
|
Fix navi-3d stdio MCP cwd to avoid conflicting app.py import
...
The navi-1 root contains an old app.py (Flask). Without cwd, python -m
app.mcp_server imported that file instead of the navi-3d app package.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 13 May
|
Switch navi-3d MCP to stdio transport (local, no web server)
...
- transport: stdio instead of sse
- command: direct venv python path
- env: SESSION_FILES_DIR pointing to navi-1 session_files
SSE remains available via NAVI_3D_MCP_TRANSPORT=sse for dev/debug.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 13 May
|

Migrate 3D modeling tools to standalone MCP server navi-3d
...
Phase 0 — Fix MCP error propagation:
- McpClient.call_tool now returns (output, is_error) tuple
- McpTool.execute sets success=False when MCP reports isError=True
- Fixes silent failures where MCP errors looked like success
Phase 1 — Create mcp-server-navi-3d:
- New standalone MCP server in mcp-servers/navi-3d/
- Tools: compile_scad, render_stl, lint_scad
- Session-scoped path resolution via SESSION_FILES_DIR env
- Anti-escape validation for security
- Includes tests/unit/test_scad_analyze.py
Phase 2 — Remove from Navi core:
- Deleted navi/tools/{model_3d,render_3d,scad_lint}.py
- Removed from registry.py builtins and navi/tools/__init__.py
- Updated pyproject.toml testpaths to exclude mcp-servers/
Phase 3 — Wire into Navi config:
- Added navi-3d block to mcp_servers.json (SSE on :8002)
- Updated modeler_3d profile: mcp_servers + updated system_prompt
- All old tool names replaced with mcp_navi-3d_* equivalents
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 13 May
|
Increase max_iterations across all profiles
...
- developer: 45 → 100
- discuss: 12 → 30
- modeler_3d: 50 → 70
- secretary: 35 → 70
- server_admin: 40 → 100
- tool_developer: 35 → 100
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 13 May
|
Add absolute rule: gnexus-book must be edited only through MCP tools
...
- persona.txt: add EXTERNAL KNOWLEDGE BASES block with absolute prohibition
on filesystem/terminal/code_exec for gnexus-book; only MCP tools allowed
- mcp_servers.json: add ABSOLUTE RULE section to gnexus-book instructions
with explicit tool mapping and NEVER clause for direct file access
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 13 May
|