fix(desktop): consolidate sidebar, i18n, stale-build, session fixes#42951
Closed
OmarB97 wants to merge 27 commits into
Closed
fix(desktop): consolidate sidebar, i18n, stale-build, session fixes#42951OmarB97 wants to merge 27 commits into
OmarB97 wants to merge 27 commits into
Conversation
added 25 commits
June 9, 2026 06:40
…Live sidebar - hermes_cli/session_presence.py: core presence records with TTL/dedup - tui_gateway/server.py: publishes on session init/activate/activity, clears on finalize, session.presence_list RPC - tests: 5 passing (3 unit + 2 integration) - Desktop: atom, useSessionPresence hook, Live sidebar section - Sidebar: grouped by host/OS/profile/client with search filter, OS icons, This Device badge - Styles: text-sidebar-foreground utilities for visible button text - sidebar.tsx: base text color on menu buttons (fixes invisible labels) Fixes #session-presence
- Remove orphaned JSX block from bad merge - Inline Live presence section, Pinned, and Recents sections - Live section shows at top with accent dot indicator grouped by device - Pinned sessions in middle section - Recents/sessions in scrollable section below - Fixes invisible sidebar button labels (already committed) - Fixes build failure from missing SidebarSectionsWithLive component
…ions - Add device-nickname.ts: hostname → friendly nickname resolver (Omars-MacBook-Pro-3.local → Mac Pro, Taro → Taro, etc.) - Replace profile source badges with device nickname badges on session rows - Thread presenceBySession map through sidebar → sections → rows - Parallelize profile DB queries with ThreadPoolExecutor - Reduce per-profile fetch cap from 500 to 100 - Add in-flight request guard + skip autoArchive on cascade - Remove redundant refreshSessions call in desktop-controller
…debar layout - Fix streaming text not rendering until focus change: add 100ms setTimeout safety net in syncSessionStateToView as fallback when requestAnimationFrame is throttled (background tab, compositor stall) - Change compression threshold default from 0.50 to 0.85 across all code paths (agent_init, context_compressor, config, setup, tips) so context compression only fires at 85% window capacity - Sidebar: merge Live/Sessions into unified list with 2-line rows (device/OS context on line 2, session title on line 1) to fix truncation and improve visual hierarchy
…ions - Add device-nickname.ts: hostname → friendly nickname resolver (Omars-MacBook-Pro-3.local → Mac Pro, Taro → Taro, etc.) - Replace profile source badges with device nickname badges on session rows - Thread presenceBySession map through sidebar → sections → rows - Parallelize profile DB queries with ThreadPoolExecutor - Reduce per-profile fetch cap from 500 to 100 - Add in-flight request guard + skip autoArchive on cascade - Remove redundant refreshSessions call in desktop-controller
…debar layout - Fix streaming text not rendering until focus change: add 100ms setTimeout safety net in syncSessionStateToView as fallback when requestAnimationFrame is throttled (background tab, compositor stall) - Change compression threshold default from 0.50 to 0.85 across all code paths (agent_init, context_compressor, config, setup, tips) so context compression only fires at 85% window capacity - Sidebar: merge Live/Sessions into unified list with 2-line rows (device/OS context on line 2, session title on line 1) to fix truncation and improve visual hierarchy
…t SQL UI fixes: - Increase session row min-height from 1.625rem to 2.375rem (fits two lines) - Change items-center to items-start with self-center on dot (proper alignment) - Increase button padding py-0.5 → py-1 (vertical breathing room) - Increase source line top padding pt-0.5 → pt-[3px] (gap between lines) - Show device nickname for remote sessions (from presence record) - Show source type for local sessions (Terminal, API, Cron, etc.) - Add srcMap for platform names (telegram, discord, slack, etc.) Performance: - Add covering indexes for last_active and preview subqueries - Replace correlated subqueries in chain_max CTE with pre-aggregated msg_max CTE - Replace correlated subquery in outer SELECT with msg_max reference - Same optimization applied to non-recursive query path
- Group sessions by source (Terminal, Cron, Hermes Desktop, etc.) under PINNED and SESSIONS sections with collapsible sub-group headers - Fix pinned section flex layout: flex-1 → flex-none to prevent 50/50 vertical split with Sessions section - Always render pinned section header with empty state placeholder instead of conditional rendering that causes layout shift - Add source icon + label + count to sub-group headers using Codicons - Suppress per-row source badge when inside source groups (header already shows the source) - Update SessionSourceLine with full source→label mapping (tui, cron, desktop, api_server, telegram, discord, etc.) - Order source groups by activity: working/active groups first, then alphabetically
- Add device_name column to sessions table, populated at creation time - Device name resolution: config device.name → MeshBoard devices.json labels → socket.gethostname() fallback - Expose device_name in gateway API session response - Sidebar groups sessions by device name (ko-mac, Taro, etc.) - Source badge still shown on each row (Terminal, Cron, Desktop) - Toggle switches between device and workspace grouping; line 2 adapts to avoid showing duplicate info - Virtual session list updated with showDeviceBadge support
…le integration - Fix MeshBoard device matching: compare by lan_hint IP, host-id marker file, MESHBOARD_LOCAL_HOST env var, ssh_alias (case-insensitive), and device id — instead of comparing platform.node() against device id which never matches (e.g. 'Omars-MacBook-Pro-3' != 'ko-mac') - Add Tailscale integration as fallback: runs tailscale status --json and extracts self HostName - Cross-platform IP detection: hostname -I (Linux) + ifconfig (macOS) - Resolution chain: config.yaml device.name → MeshBoard → Tailscale → hostname - All integrations are opt-in and gracefully degrade when unavailable
- Auto-detect fork remote in resolveUpdateTarget: when HEAD tracks a non-origin remote (e.g., fork/main), prefer that remote for update checks instead of origin/main. Prevents false 'N behind' notifications and protects unmerged fork PRs from being overwritten. - Add 'remote' field to desktop update config (updates.json) alongside 'branch'. Users can explicitly set update remote via getRemote/setRemote. - Add hermes:updates:remote:get and hermes:updates:remote:set IPC handlers. - Extend preload bridge with getRemote/setRemote for renderer access. - Update TypeScript types for bridge (getBranch/setBranch now return remote alongside branch, plus getRemote/setRemote methods).
Sessions are grouped by device, so the device name is already the group header. Line 2 now only shows the source/client (Terminal, Cron, Hermes Desktop, etc.) instead of 'MacBook Pro · Terminal'.
- Add idx_sessions_sidebar composite index (archived, message_count, started_at DESC) to avoid full table scans on the sidebar session list query and auto-archive queries - Replace list_sessions_rich(limit=100000) in archive_old_sessions with targeted SQL that only finds candidate IDs eligible for archiving — avoids materializing the entire session list through expensive recursive CTEs - Add _surfaced_session_filter_sql() shared helper to ensure archive_old_sessions and list_sessions_rich agree on surfaced session definition - Bump SCHEMA_VERSION to 16 with v16 migration for the new index Before: list_sessions_rich(100K) on every boot walked all sessions through recursive CTEs (seconds on large DBs) After: targeted SQL queries using composite index (7ms on 2GB DB)
Desktop-created sessions were labeled as "tui" (terminal) instead of "desktop", causing incorrect source attribution in the sidebar and session history.
…eded When source changes (merge, local edits) leave the running .app behind, the update UI now shows an actionable 'rebuild needed' state instead of 'all set'. The checkUpdates IPC handler compares the embedded install-stamp commit (baked into the .app at build time) against git HEAD. When they differ, it sets rebuildNeeded: true, which the UI surfaces as a rebuild prompt with the same 'Update now' button flow. Changes: - main.cjs: compare running app stamp vs git HEAD in checkUpdates() - global.d.ts: add rebuildNeeded? to DesktopUpdateStatus - en.ts: new i18n strings for rebuild-needed state (3 sections) - updates-overlay.tsx: show rebuild prompt when behind=0 & rebuildNeeded - about-settings.tsx: show rebuild status line and Rebuild Now button - use-statusbar-items.tsx: highlight version badge for rebuild
…dits Move rebuildNeeded detection ahead of git fetch so it works offline and add git diff --name-only HEAD -- apps/desktop/ to catch local uncommitted edits that don't change the commit SHA. Bug 1: rebuildNeeded was gated behind git fetch success. If fetch failed (offline, unreachable remote), the function returned early with error: 'fetch-failed' and never set rebuildNeeded. Bug 2: Only git commit SHA was compared, so local edits were invisible to the stale-build indicator. Now detects stale builds in ALL scenarios: - git pull / merge (commit SHA changes) - git checkout / branch switch (commit SHA changes) - local uncommitted edits (git diff shows changes) - offline / fetch-failed (detection runs before the fetch)
…r threshold regression When the auxiliary compression model has smaller context than the main model's compression threshold, Hermes auto-lowers the threshold to fit the aux model's context. This can silently override the user's explicit config and drag compression from 0.85 down to ~0.50. New config option: compression.min_threshold: 0.0 This acts as a floor for the auto-lowered ratio. Setting, for example, min_threshold: 0.75 would clamp auto-lowering to at most 75% of the main model's context, even if the aux model is smaller. Users can set this explicitly in config.yaml to defend their preferred threshold across app updates or model switches (which lose the previous per-session override). Default 0.0 preserves current behavior for users who don't set it.
Inject usage dict into tool.start and tool.complete callbacks so the frontend can update the context bar mid-turn instead of waiting for message boundaries. Changes: - agent/tool_executor.py: construct usage dict with context stats (used/max/percent) in both concurrent and sequential execution paths, pass as usage= kwarg to tool_start/complete callbacks - tui_gateway/server.py: accept usage kwarg in _on_tool_start/complete, forward to payload; update callback lambdas and preview restart callbacks - apps/desktop: read payload.usage on tool.start/complete events, merge into current usage state - cli.py, api_server.py, gateway/run.py: add **kwargs to all callback implementations for forward compatibility
- Remove device grouping from sidebar, flatten to simple list - Remove 2nd line (device/source badge) from session rows - Show right-aligned timestamps always visible (not just on hover) - Add agent.reasoning_effort to settings enum options for 'none' value - Pass custom_providers to get_model_context_length in gateway - Fixes context window showing 256k instead of 131072 for custom providers
store@0.2.14 dropped tapClientResource export and requires tap@^0.6.0 which lacks ./react-shim. Pin to last compatible versions.
Contributor
Author
|
Fork PR: OmarB97#123 |
# Conflicts: # apps/desktop/src/app/chat/sidebar/index.tsx # apps/desktop/src/app/chat/sidebar/session-row.tsx # apps/desktop/src/app/desktop-controller.tsx # apps/desktop/src/store/session.ts # scripts/release.py
372da63 to
1d7b88b
Compare
- i18n: add missing update copy keys (en, zh), fix TypeScript build errors - stale build detection: detect stale build before git fetch, rebuildNeeded - electron/main.cjs: stale build detection + fork remote auto-detect - sidebar: always-visible age, presence, source labels; remove device grouping - session-row: fix timestamp overlap, vertical center alignment - session actions: archive helpers, presence-aware discovery - session presence hook + state cache improvements - yolo session, session eligibility, statusbar backend version - layout: persist cron open state; keybinds, profiles, model picker fixes
Contributor
Author
|
Closing to recreate as a clean, focused PR with only our changes. Reopening as a single-commit branch on upstream/main to eliminate fork divergence noise. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Consolidated desktop fixes — i18n, stale build detection, sidebar improvements, session management.
Changes
i18n & build
electron/main.cjs
Sidebar
Session management
Other
Cleanup
device-nickname.ts(device grouping deprecated)session-source.ts(replaced with upstream handoffOriginSource)showDeviceBadgeprops throughout sidebarWhy
PR 3 of consolidated rebased set replacing the 9 overlapping PRs flagged by @austinpickett. Clean diff against current upstream/main.