| 2026-06-23 |
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
2 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
2 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
2 days ago
|
Navi Code TUI: extend theme with selection and link colors
...
Add selection (magenta) and link (teal) for cursor line, active selection and URLs.
Tests still green.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
2 days ago
|
Navi Code TUI: add gnexus-ui-kit color theme support
...
- Extract exact gnexus-ui-kit cyberpunk palette from
webclient/vendor/gnexus-ui-kit/src/scss/_palette-colors.scss.
- Add clients/terminal/tui/themes.py with Theme dataclass, ThemeRegistry,
and gnexus-dark / gnexus-light themes.
- Wire theme into NaviCodeTui via _apply_theme() on mount; default is
gnexus-dark.
Tests: 463 passed, 1 skipped (excluded unrelated websocket test).
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
2 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
2 days ago
|
Docs: actualize navi_code tool lists and key_tools
...
- docs/navi_code.md and docs/profiles.md now correctly list native tools,
MCP navi-web tools, and excluded tools.
- image_view is documented as enabled for the agent (loads and describes
images for the model, not shown to the user).
- web_search/http_request are documented as MCP navi-web tools, not native
disabled tools.
- navi/profiles/navi_code/config.json: updated full_description.key_tools to
match actual resolved tool names.
Tests: 459 passed, 1 skipped.
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
2 days ago
|
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
2 days ago
|
Navi Code: Phase 1 — terminal-first profile, default profile mechanism, env/persona, tests
...
- Add navi_code profile (terminal-first coding assistant)
- Add NAVI_DEFAULT_PROFILE_ID setting and POST /sessions default profile fallback
- Add persona_navi_code.txt and .env.navi_code.example
- Add docs/plan_navi_code.md phased plan
- Update tests to verify default-profile selection in no-auth mode
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
2 days ago
|
| 2026-06-22 |
Fix review issues for NAVI_AUTH_ENABLED feature
...
- Return 503 from /auth/login and /auth/callback when NAVI_AUTH_ENABLED=false
- Return model_copy() of _ANONYMOUS_USER to prevent accidental mutation
- Clean up __import__(datetime) in auth DDL
- Reorder FakeChatSession definition before use in tests
- Remove dead monkeypatch code in no-auth integration fixture
- Add unit test for get_current_user_ws in no-auth mode
- Add integration tests rejecting OAuth endpoints in no-auth mode
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
2 days ago
|
Add NAVI_AUTH_ENABLED switch for optional auth
...
- Add navi_auth_enabled setting (default true) to navi/config.py and .env.example
- When disabled, treat every request as anonymous admin user (id='anonymous')
- Create/update fixed anonymous navi_users row on startup
- Bypass OAuth/cookie/API-token resolution in navi/auth/deps.py
- Update /auth/status to return {enabled, configured}
- Log security warning on startup when auth is disabled
- Update webclient: skip fetchMe/login screen, show Local mode footer,
expose /admin link, warn in API keys panel
- Rebuild webclient production bundle
- Add unit and integration tests for no-auth mode
- Update docs: auth.md, config.md, api.md, api_tokens.md, sessions.md,
websocket.md, mechanics.md, index.md
Co-Authored-By: Claude <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
2 days ago
|
| 2026-06-01 |
Fix spawn_agent profile selection: stronger prompt + alias fallback
...
- Rewrite PROFILE SELECTION description to explicitly say: when the
plan specifies a profile, you MUST pass profile_id. Only omit when
the plan does NOT specify a profile.
- Add JSON examples showing correct profile_id usage.
- Add fallback for 'profile' parameter name (models sometimes use
'profile' instead of 'profile_id' when the description says
'Profile to use').\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
24 days ago
|
Fix scratchpad tool: rename op→action, add examples, improve error messages
...
- Rename primary parameter from 'op' to 'action' for consistency with
all other tools (terminal, filesystem, todo, etc.). Legacy 'op' still
works as a fallback to avoid breaking old calls in compressed context.
- Add JSON examples directly in the tool description so the model sees
the exact structure to produce.
- Improve all error messages to include the correct JSON example,
making it obvious what the model did wrong.
- Add manuals/scratchpad.md for tool_manual support.
- Update and expand tests for new syntax and error cases.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
24 days ago
|
Remove offline_access from OAuth scopes
...
gnexus-auth does not support offline_access yet (SUPPORTED scopes are
only openid, email, profile, roles, permissions). Requesting it caused
invalid_scope error and login failures.
Keep refresh token support as-is — tokens are still issued and
refreshed, just bound to the SSO session lifetime.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
24 days ago
|
Fix OAuth callback to handle missing code and error responses
...
FastAPI validated code/state as required query params before the
handler body ran, so any OAuth error response (e.g. invalid_scope
from offline_access, user denied consent) produced an opaque 422
"Field required" instead of a readable error message.
- Make code, state, error, error_description all optional with defaults
- Detect OAuth error responses and return a clear 400 with the error
- Guard state[:8] slicing when state may be None
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
24 days ago
|
Make shared files and published content publicly accessible
...
Remove auth requirements from:
- GET /sessions/{id}/files/{filename} — direct download links (session ID
acts as unguessable capability token)
- GET /sessions/{id}/content — published inline content list
Both endpoints still verify session exists and protect against path
traversal. File upload and file listing remain auth-gated.
Update tests to match new signatures.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
24 days ago
|
Fix frequent OAuth logouts: offline_access scope, transient error handling, fetchMe resilience
...
- Add 'offline_access' to OAuth scopes so gnexus-auth issues offline
refresh tokens instead of SSO-session-bound ones.
- Distinguish TokenRefreshException (invalid/expired refresh token)
from transient network errors during token refresh:
* TokenRefreshException → logout (token genuinely dead)
* Other exceptions → fallback to cached user or API token
- Improve refresh failure logging with exc_type and error message.
- Frontend fetchMe: swallow non-401 errors so transient 5xx/network
failures don't flash the login screen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
24 days ago
|
Fix CompressionWorker: sync context compression with session messages
...
- Mark removed messages as is_context=False so DB reload doesn't resurrect them
- Persist summary_msg in messages (is_display=False) so summary survives reload
- Add is_compression marker with is_context=False
- Set context_token_count to real estimate instead of zero
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
24 days ago
|
| 2026-05-26 |
Fix terminal detail UX: description wrapping, status contrast, close button
...
- Remove `white-space: nowrap` from `.terminal-detail-meta` and
`.terminal-item .artifact-meta` — long descriptions now wrap instead
of being clipped with ellipsis.
- Add `-webkit-line-clamp: 2` to list-item meta so description is
limited to 2 lines with graceful overflow.
- Fix status colour in detail rows: `.terminal-detail-value.status-busy`
etc. added after `.terminal-detail-value` so their colours override
the default #C0CAF5 (was causing light-on-light text).
- Add close button (X) inside `.terminal-detail-header` to dismiss
the detail pane without leaving the tab.
- Make `selectTerminal` toggle: second click on the same item deselects.
- Build webclient and run tests — all pass.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 26 May
|
Add terminals tab to ArtifactsPanel with live output
...
- New "Terminals" tab in ArtifactsPanel showing active terminal sessions
- List view: name, description, status badge (busy/idle/closed)
- Detail view on click: PID, command, CWD, uptime, background flag, live output
- chat.js: capture terminal metadata from tool_start and tool_call events
- Merge terminal metadata (open/status/list/close) into reactive terminals store
- Vue reactivity: immutable updates for terminals map
- Build webclient and verify all backend tests pass
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 26 May
|
Clarify terminal description param and profile prompts
...
- terminal.py: stronger description for the 'description' field so
the model knows it is REQUIRED for action=open and what to write
- server_admin and developer system prompts: add a short section
explaining persistent terminal usage (open/close/list/status/send_input)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 26 May
|
Move terminal_manager to _internal subpackage
...
- terminal_manager is an internal helper, not a tool
- Update imports in terminal.py, container.py, test_terminal.py
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 26 May
|
Add terminal tool manual
...
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 26 May
|
Fix terminal review issues: security, lifecycle, reactivity
...
- TerminalManager.open now accepts exec_tokens to use create_subprocess_exec
for restricted commands instead of always using shell
- Fix kill/terminate order: SIGTERM first, SIGKILL fallback
- Pop closed sessions from _sessions dict to prevent memory leak
- Add terminal_manager.shutdown() to AppContainer.shutdown()
- Wait for reader tasks in foreground open before returning output
- Add _MAX_TERMINALS_PER_SESSION limit (10)
- Wrap cleanup_idle tasks in _close_one_safe with error logging
- send_input catches BrokenPipeError/ConnectionResetError specifically
- Foreground terminals auto-close after gathering output
- Vue reactivity: replace terminals object immutably instead of mutating
- onTerminalClosed marks matching tool card as no longer pending
- Update tests for new behavior (foreground auto-close, max limit)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 26 May
|
Add persistent multi-session terminal tool with background support
...
- New TerminalManager module: named subprocess sessions per Navi session,
background readers, event-sink streaming, idle auto-cleanup
- Refactor terminal tool to multi-action: run, open, close, list,
status, send_input
- Add TerminalOutputDelta and TerminalClosed events for streaming
- Wire TerminalManager into AppContainer, orchestrator, and registry
- Persist session_metadata in Session model and pg_session_store
- Close all session terminals on session delete
- Webclient: handle terminal_output/terminal_closed WS events,
display live terminal output in tool cards
- Update unit tests for new terminal actions
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 26 May
|
Fix dead code in websocket.py — stream_start never sent on first message
...
websocket.py lines 301-308 were indented inside the `except` block after
`raise`, making them unreachable. This meant `stream_start` and
`_stream_to_client` never ran for the initial message send, so the client
saw no response until page reload (when the reconnect path took over).
Fix: dedent lines 301-308 so they execute after the try/except/finally
block on the normal success path.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 26 May
|
Fix reloadSession race that orphans streamingMsg
...
reloadSession checked streaming.value at entry but api.getSession is
async. While awaiting, onStreamStart could set streaming=true and push
the assistant message into messages.value. When reloadSession resumed it
replaced messages.value with the stale server snapshot, evicting the live
streaming message. All subsequent deltas and tool cards went to the orphan
and were invisible.
Fix: re-check streaming.value after the await before mutating messages.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 26 May
|
Fix delta loss during thinking-to-text transition and streaming orphaning
...
Backend:
- agent.py _consume_stream: replace elif with if so a single chunk can
carry both the final thinking fragment AND the first text delta.
Fixes the 'first token lost after tools' bug.
Frontend:
- chat.js reloadSession: bail out early when streaming.value is true.
Replacing messages.value mid-stream orphans streamingMsg, breaking
Vue reactivity for all subsequent deltas and tool cards.
- useWebSocket.js session_sync handler: add !chat.streaming guard
before calling reloadSession.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 26 May
|
| 2026-05-25 |
Add rebuilt webclient dist assets
...
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 25 May
|
Fix streaming message orphaning and duplicate message keys
...
chat.js:
- reloadSession: during an active stream, replace the last built assistant
message with the live streamingMsg instead of discarding it on text match.
This fixes the root cause of invisible first messages and flickering tool
cards when session_sync arrives mid-stream.
- buildMessageList: remove assistantCounter and use firstIdx as the message id
to avoid duplicate Vue keys (e.g. user h_0 and assistant h_0).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 25 May
|