| 2026-05-14 |
Rebuild dist for search UX polish
...
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 14 May
|
Rebuild dist for session search feature
...
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
|
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
|
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
|
| 2026-05-12 |
Rebuild dist after resolving merge conflicts
...
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 12 May
|
ready dist
Eugene Sukhodolskiy
committed
on 12 May
|
Wire gnexus-ui-kit v0.2.0 Vue 3 adapter and migrate Wave 1 components.
...
- Update vendor/gnexus-ui-kit to v0.2.0 (Vue components + composables)
- Add Vite aliases for gnexus-ui-kit/vue and gnexus-ui-kit/css
- Install GnexusUiVue plugin in main.js + GnToastProvider in App.vue
- Migrate ProfileBadge → GnBadge
- Migrate ErrorMessage → GnAlert
- Migrate ConfirmDialog → GnConfirmDialog
- Migrate raw <button> elements → GnButton / GnIconButton in:
WelcomeScreen, LoginScreen, ChatArea, ChatHeader, AppSidebar,
ArtifactsPanel, UserMessage, AssistantMessage, SelectionToolbar
Build and tests pass (51/51).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 12 May
|
| 2026-05-11 |
Add deterministic line-based file editing (edit_lines), rating UI fix, and session refresh
...
- filesystem.py: add edit_lines action (deterministic line ops via operations array)
+ numbered param for read (1-based line numbers in output)
+ clarify four editing modes in tool description
- chat.js: fix rating IDs for streaming messages (assign h_ ID on stream_end)
- SessionList.vue: mobile pull-to-refresh with PTR_THRESHOLD=80
- AppSidebar.vue: desktop refresh button next to Conversations header
- planning.py: knowledge source assessment in Phase 1
- debug panel: MCP servers tab + resolved tools per profile
- NAVI.md: reposition as neutral quick-reference
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 11 May
|
| 2026-05-10 |
Rebuild webclient and fix showWelcome condition
...
- Rebuild dist/ after removing erroneous vue-router
- Fix App.vue showWelcome to use chatStore.loading (prevents flicker
to WelcomeScreen during session load)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 10 May
|
| 2026-05-09 |
Open admin panel in new browser tab from Android and webclient
...
Android:
- Add /admin path to shouldOpenExternally so admin links open in
the system browser instead of the WebView.
Webclient:
- Add target="_blank" and rel="noopener noreferrer" to the admin
link in AppSidebar.vue so it opens in a new tab.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 9 May
|
Add Android deep-link OAuth bridge for WebView auth
...
Problem: Android WebView opens OAuth in external browser (Chrome).
After successful login, cookie stays in Chrome and WebView remains
unauthenticated because cookies are not shared between apps.
Solution: bridge page flow that avoids cookies entirely for mobile.
Backend:
- /auth/login accepts ?platform=android and ?return_to params
- /auth/callback detects android via state metadata, skips cookie,
redirects to /auth/mobile-done?sid=<session_id>
- /auth/mobile-done renders HTML that deep-links to navi://auth/callback
Webclient:
- login() detects NaviAndroid UA and adds ?platform=android
Android:
- MainActivity: handle incoming navi:// intent in onCreate and onNewIntent,
set cookie via CookieManager, reload WebView
- AndroidManifest: add intent-filter for navi://auth/callback and
singleTask launchMode
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 9 May
|
| 2026-05-08 |
Compact admin/logout buttons in sidebar footer
...
In sidebar-footer-actions, replace text+icon Admin and Logout buttons
with icon-only btn-icon buttons (shield-check and sign-out icons).
Add without-hover class to suppress the default icon rotation hover
animation. Keep the Login button unchanged (text + icon as before).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 8 May
|
Add pagination, search, and sorting to admin sessions
...
Backend:
- Add count_all and search_list abstract methods to SessionStore
- Implement count_all and search_list in PgSessionStore (SQL with ILIKE)
- Implement count_all and search_list in InMemorySessionStore
- Update /admin/sessions to accept limit, offset, search, sort_by, sort_order
- Return {total, limit, offset, items} from /admin/sessions
Frontend:
- Add search input for sessions in admin panel
- Add clickable sortable column headers with asc/desc toggle
- Add pagination controls (prev/next, page size selector, item count)
- Debounce search input (300ms)
Tests:
- Add integration tests for pagination, offset, search, and sorting
- All 217 tests pass
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 8 May
|
| 2026-05-04 |
Dark login screen: #111 overlay, transparent card
...
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 4 May
|
Add full-screen login overlay for unauthenticated users
...
- Backend: new endpoint GET /auth/status returns {configured: bool}
- Webclient auth store: add authConfigured ref + fetchStatus()
- LoginScreen.vue: centered card with logo, title, and login button
- App.vue: show LoginScreen overlay when auth is configured but
user is not authenticated (z-index 9999, blocks all UI)
- App.vue onMounted: fetch auth status before trying to resolve user
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 4 May
|
Add avatar display and gnexus-auth profile link
...
Backend:
- User model: add avatar_url field
- auth/deps.py: extract avatar_url from auth_user.profile (picture/avatar_url)
- auth.py /auth/me: return avatar_url + computed profile_url
- config.py: add gnauth_profile_path setting
- .env.example: document GNAUTH_PROFILE_PATH
Frontend:
- AppSidebar.vue: show user avatar (or initial fallback) next to name
- Clicking user info opens gnexus-auth profile in new tab
- Rebuild dist/
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 4 May
|
Rebuild webclient dist with btn-primary fix
...
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 4 May
|
| 2026-05-03 |
Multi-user auth via gnexus-auth OAuth + hybrid role/permission model
...
- Integrate gnexus-auth-client-py (GAuthClient) for OAuth flow, token refresh,
and webhook parsing
- Add navi/auth/ package: User model, Fernet encryptor, client singleton,
deps (get_current_user, require_admin, require_permission)
- New tables: navi_users, user_auth_sessions (auto-created on startup)
- Session/memory isolation by user_id with legacy NULL support
- Cookie-based auth proxy: /auth/login, /callback, /logout, /me
- Webhook receiver /webhooks/gnexus-auth handling user events, global logout,
session revocation, role/permission changes
- Admin endpoints (/admin/*) gated by role + permissions
- Webclient auth store with isAdmin/hasPermission guards
- Admin-only profile filtering in /agents/profiles
- 200/200 tests passing
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 3 May
|
| 2026-05-02 |
Paginate session list loading
Eugene Sukhodolskiy
committed
on 2 May
|
| 2026-04-30 |
Improve artifacts workspace controls
Eugene Sukhodolskiy
committed
on 30 Apr
|
Add artifact source previews
Eugene Sukhodolskiy
committed
on 30 Apr
|
Reduce spawn agent running indicators
Eugene Sukhodolskiy
committed
on 30 Apr
|
Restore original scrollbar appearance
Eugene Sukhodolskiy
committed
on 30 Apr
|
Normalize scrollbar styling
Eugene Sukhodolskiy
committed
on 30 Apr
|
Improve content publishing UX
Eugene Sukhodolskiy
committed
on 30 Apr
|
| 2026-04-29 |

Stability fixes batch — tech debt review 2026-04-29
...
Critical:
- Concurrent WS run race guard (#1)
- Tool task cancellation on generator teardown (#2)
- StopAsyncIteration kills fallback chain (#3)
- Session loading race with _lastLoadId guard (#4)
- ContentCard .match() crash on non-string result (#5)
- Image data type guard in buildMessageList (#6)
High:
- Cap WS replay buffer at 500 events (#7)
- Deduplicate memory extraction task with asyncio.Lock (#9)
- TTL-based fallback blacklisting (5 min) (#10)
- Subagent tool exception isolation (#11)
- Inline image size/count validation on WS (#12)
- Clean up orphaned file on DB insert failure (#13)
- Deep watch streamingMsg for auto-scroll (#14)
- WS_SCHEME wss:// support for HTTPS (#15)
- Sending guard against duplicate message sends (#16)
- Global unhandledrejection listener in API layer (#17)
Medium:
- Cap planning_logs at 20 entries (#22)
- Store cleanup_loop task reference (#23)
- BaseException → Exception in _run_with_sentinel (#24)
- Propagate SystemExit in agent loop (#25)
- Configurable output_reserve_tokens (#26)
- Always reloadSession on session_sync (#30)
- FIFO queue for confirm dialogs (#31)
- Reset body.overflow on ImageLightbox unmount (#32)
- try/finally in fallback copy (#33)
- _isConnecting guard in WS send() (#34)
Low:
- Lazy-init deps.py singletons (#36)
- Replace __import__ with direct imports (#38)
- Preserve token count 0 in ollama.py (#39)
- Clear orphaned streamingMsg on reconnect reload (#43)
- Escape single quote in UserMessage (#44)
- Polyfill-free findLast replacement (#48)
- Match <table> tags with attributes in markdown (#49)
- Attach copy buttons only when msg.done (#50)
- Fix hasMeta falsy-0 bug (#53)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 29 Apr
|
| 2026-04-28 |
Fix system prompt leakage into chat history; polish content cards
...
Backend:
- websocket.py + agent.py: separate user-visible display_message from
LLM user_message. System hints (image/file attachments) no longer leak
into session.messages and appear after page reload.
- main.py: add ensure_tables() on startup so session_content table is
created before first publish.
- profiles: add kimi-k2.6:cloud to all model lists as fallback.
Frontend:
- ContentCard.vue: remove border-radius, add scrollbar styles, fix
metadata fallback parsing so cards survive page reload.
- content-viewers/*.html: add matching scrollbar styles.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 28 Apr
|
Add content hosting system with inline viewers
...
Backend:
- Add navi/content/ directory for published files
- Add content_store.py with publish/list/delete/cleanup functions
- Add content_publish tool for publishing files as viewable content
- Add /content static file mount in main.py
- Add /content-viewers mount for viewer pages
- Extend ToolEvent with metadata field
- Forward metadata through websocket tool_call events
- Update Agent to include metadata in ToolEvent
Frontend:
- Add ContentCard.vue component for displaying published content
- Add viewer pages: stl.html (Three.js), svg.html, html.html, pdf.html
- Update AssistantMessage.vue to render ContentCard for content_publish
- Update chat store to preserve metadata in tool cards
- Update websocket protocol docs with metadata field
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eugene Sukhodolskiy
committed
on 28 Apr
|