feat(desktop): React frontend + Tauri shell + bridge rewrite#684
Open
abraxas914 wants to merge 81 commits into
Open
feat(desktop): React frontend + Tauri shell + bridge rewrite#684abraxas914 wants to merge 81 commits into
abraxas914 wants to merge 81 commits into
Conversation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…e/file injection, streaming Major rewrite of desktop_bridge.py for the React desktop frontend: - Per-session file persistence (individual JSON files, O(1) write) - submit_prompt: file path injection into agent_prompt for file_read access - _patch_chat_for_images: monkey-patch backend.ask for base64 image injection - Vision MIME whitelist (png/jpeg/gif/webp); SVG falls back to path reference - Thread-safe run_agent_turn with sess.id scoping (no cross-thread sid leak) - Ring buffer self-log capture (bridge_print → deque(maxlen=500)) - turn_segs streaming: per-turn structured output for frontend rendering - Model profile CRUD: /model-profiles endpoints - Session model binding (llm_no per session) - Service lifecycle management via /services/* endpoints - Bridge exit endpoint with graceful shutdown - WebSocket hub for real-time state sync - plan_state.py: plan mode path utilities for desktop sessions Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…nd lifecycle hooks - Improved error classification and productized error messages - Graceful start/stop with proper signal handling - Bridge-visible status transitions for frontend service panel Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… routing Complete React + TypeScript desktop frontend built on Vite: - App shell: layout system (TopBar, LeftPanel, RightPanel, Resizer) - State management: Zustand stores (bridge connection, services, UI state) - Bridge HTTP/WS client with auto-reconnect and offline detection - Plan mode UI (PlanCard, QuickPlan components) - Session CRUD (new/delete/rename/pin/drag-sort) - Font, appearance, and log modal infrastructure - Dev tooling: vitest config, tsconfig, ESLint - Asset pipeline: provider logos, channel icons, app icons - Loading screen with i18n-aware progress messages - Documentation: adaptation notes, white-screen debug, gap analysis Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Complete chat experience for the React desktop: - Composer: rich editor with IME handling, file/image upload, model selector - MessageList: user/assistant messages with action bars - SessionList: search, pin, rename, drag-sort, contextual actions - ChannelList: multi-channel routing (WeChat, DingTalk, Discord, etc.) - Plan mode: QuickPlan widget, auto/manual toggle - AttachmentStrip: file preview with remove action - Chat service layer: prompt submission, cancel, message polling Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…serTurnRail Structured multi-turn rendering with hardened markdown processing: - Thread component: turn_segs-based rendering with stale-part fallback - Markdown pipeline: scrubBacktickNoise, normalizeFenceBlocks, KaTeX LRU memo - DiffLines renderer for ```diff fenced blocks - Prism.js syntax highlighting integration - UserTurnRail: smooth scroll navigation between user turns - AssistantActionBar: copy, retry, model badge - Streaming: opacity layering for in-progress turns - Tests: markdown preprocessing, streaming, thread grouping Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…profiles Complete settings system for the React desktop: - Settings modal: appearance, language, font size sections - Model CRUD: add/edit/delete with protocol-aware validation - Provider presets: Claude, GPT, DeepSeek, Qwen, Gemini, etc. - Model profiles: named configurations saved to bridge - ModelSelector dropdown in Composer with per-session binding - mykey.py integration: read/write via bridge /services/mykey endpoints - Stress tests for settings store Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…pagination Token usage analytics UI: - TokenPage with windowed pagination for large histories - TokenFilter: time-range selector with date normalization - TokenTable: model-aware cost estimation display - ConductorTab: conductor-specific token breakdown - IME composition guard on filter inputs - Tests: token filter date normalization Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ine overlay Real-time feedback layer: - NotificationStack: queued toast with auto-dismiss and severity levels - ConnectingOverlay: bridge disconnect detection with retry countdown - Notification store (Zustand) with queue drain and dedup - Stress tests for notification store edge cases Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…h/en) Visual identity and localization: - CSS custom properties (--bg, --fg, --accent, --divider, etc.) - Dark/light theme toggle persisted in settings - i18n: complete zh/en translation files - Navigator.language-aware loading screen text - Legacy i18n.js for non-React loading pages Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…s, installers Native desktop application layer: - Tauri v2 configuration: capabilities, permissions, bridge command bindings - src/lib.rs: Tauri command handlers for bridge lifecycle - Packaging scripts: macOS (DMG), Linux (AppImage + install.sh), Windows (portable + PS1) - install/uninstall scripts for all three platforms - Cargo static-link config for MSVC CRT (Windows portability) - Conductor store + stress tests - titleBarStyle fix for Tauri v2 (camelCase required) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Automated cross-platform build and release pipeline: - Trigger: tag push (desktop-portable-*) or manual workflow_dispatch - Matrix: Windows (MSVC static CRT), macOS (universal), Linux (AppImage) - Rust/Node caching for fast rebuilds - upload-artifact v7 for CI artifacts - GitHub Release creation on tag push with platform-specific assets - Platform-selective manual dispatch for testing individual targets Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…tch, utils Comprehensive pytest test suite for desktop_bridge.py: - test_bridge_submit: scope isolation guards (sid vs sess.id), image patch existence - test_bridge_sessions: session CRUD, persistence, concurrent access - test_bridge_uploads: file/image upload flow, path injection verification - test_bridge_model_switch: model binding, profile CRUD - test_bridge_utils: normalize_prompt, strip_final_info_marker, utility functions - Source-parsing guards to prevent regression on critical code patterns Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… layout Tauri's create-dmg leaves .VolumeIcon.icns, .background/, and .fseventsd visible when users resize the Finder window. Instead of trying to hide these files (SetFile/chflags don't work reliably), repackage the DMG from scratch: extract .app, generate .DS_Store with ds_store lib (540x380 window, 128px icons, centered positions), and create a fresh UDZO DMG. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…lay with Tauri startDragging The previous `::before` full-width `-webkit-app-region: drag` overlay was swallowing click events for titlebar buttons on macOS/WKWebView. CSS drag regions proved unreliable in Tauri v2 (both full-width and carve-out strip approaches failed in packaged builds). New approach: Hermes-style carve-out drag strips that trigger `window.getCurrentWindow().startDragging()` on mousedown. This keeps drag and click on separate channels — DOM events for buttons, Tauri IPC for window movement — eliminating compositor-level hit conflicts. Changes: - Delete `::before` full-width drag overlay - Add shell geometry CSS variables (--ga-titlebar-height, etc.) - Add two scoped drag strip divs (left gap + main gap) - Programmatic drag via Tauri window API on mousedown - Add `core:window:allow-start-dragging` capability - Clear native window title (remove redundant "GenericAgent" text) - Align fold button with traffic lights (top: 5px) Verified: build passes, 248 tests pass, packaged .app drag works. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…r panel click - Adjust --ga-titlebar-controls-top from 5px to 6px for vertical center alignment with macOS traffic lights - Add position: relative + z-index: 60 to .collab-worker-panel-head so the Agents panel collapse button sits above the drag strip (z:50) and receives click events Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…rag on Conductor top bar Panel no longer unmounts on collapse; it shrinks to 2.5rem with the toggle button staying in the same DOM position. This prevents the button from relocating to WorkerRail (which required z-index elevation that blocked drag). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…llapse border cleanup
- Add trafficLightPosition {x:13, y:22} to align traffic lights with fold buttons
- Add position:relative + z-index:1 on .ga-app-body to isolate Semi's internal
z-indexes from competing with TitlebarControls (fixes intermittent click failures)
- Change TitlebarControls from fixed to absolute (same visual effect, better
stacking behavior in WKWebView)
- Unify panel-head/rail height to --ga-titlebar-height for vertical alignment
- Match collapse button size (28x28) with sidebar toggle
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…lebar clearance Drag strips (absolute divs with z-index) caused cascading stacking context conflicts with panel buttons. Replace with mousedown handler on .ga-app-layout that checks y < 38px and filters interactive elements — eliminates all z-index contention between drag and click. - Remove .ga-drag-strip divs and CSS - useDragWindow() now delegates on layout root with hit-test filtering - Remove z-index hacks from panel-head and rail-toggle - Add titlebar clearance padding only to .ga-main-full in collapsed sidebar (services/token pages), not globally Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… conflict @lobehub/fluent-emoji@4 requires react@^19, but we use react@18. Local installs work because node_modules already exist; CI fails on fresh `npm install` without this override. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The post-dmg.sh script uses the ds_store package to set Finder icon positions in the DMG. CI runners don't have it pre-installed. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ismatch) pip3 installs to Homebrew site-packages but post-dmg.sh calls python3 which may resolve to a different interpreter on GitHub Actions runners. Using python3 -m pip ensures the package lands in the correct env. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
python-build-standalone dynamically links the Universal CRT but does not bundle it. Win10/11 have UCRT in-box, but stripped/older images lack it, causing python.exe to fail on launch. Copy the redistributable UCRT DLLs from the Windows SDK on the runner into the portable python/ directory. Ported from dd3xp/GenericAgent_Desktop workflow. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…itecture Replace drag-strip-based spec with event delegation pattern. Document the z-index war that made strips untenable and why delegation eliminates it. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
feat(desktop): React + Tauri desktop application
selectedModelNo was a global Zustand state persisted to localStorage,
causing Session 1 to display Session 2's model after switching.
- Rename selectedModelNo → defaultModelNo (new-session default only)
- Add sessionModelNo to chat store, populated from poll model.llmNo
- ModelSelector reads sessionModelNo ?? defaultModelNo
- Model mutation goes through POST /session/{sid}/model with
optimistic update + rollback
- Remove unused llmNo param from sendPrompt (bridge ignores it)
- Add 8 acceptance tests for session-binding logic
Bridge backend unchanged — it already implements correct per-session
model binding via sess.llm_no.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
GaSourceBlock passed { path: picked } but the Rust command expects
{ dir: picked }. Tauri deserializes by param name, so the call
always failed with a missing-argument error.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add DataSection with import/export mykey (browser), import memory and connect GA source directory (Tauri-only). Extract mykey operations from FeatureSection, fix modal.features i18n key. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove abstraction leaks: mykey → 密钥配置, 源目录 → 本地仓库 - Replace inline descriptions with tooltip (Layer 2: explanation-level) - Rename all data.* i18n keys to match new naming convention - Remove .ga-data-row-desc CSS (no longer rendered) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
ResizeObserver was re-evaluating clamped state while expanded, causing the collapse button to vanish when content fit within 40dvh. Use a ref to skip measurement while expanded. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
macOS .app bundles are discoverable via Spotlight and Launchpad, so the desktop-shortcut prompt is only useful on Windows/Linux. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
….app - Remove config-level `decorations: false` (killed traffic lights on macOS); apply it at runtime on Windows only via set_decorations() - Replace the blanket `trust_settings = false` for .app bundles with a validation check: settings are trusted when the saved project_dir still contains frontends/desktop_bridge.py. This fixes the DMG "stuck on loading" bug — the app couldn't find the project path, so bridge never started. - Remove unused `running_inside_app_bundle()` function Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The function was called unconditionally in get_or_discover_config() but gated to macOS only — a leftover from the deleted running_inside_app_bundle(). This broke Linux and Windows builds. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…cycle gaps Bridge _live_model now uses sess.llm_no as SSOT instead of agent.llm_no which is stale during agent initialization. Frontend poll callback no longer overwrites sessionModelNo during active turns. Model selection in empty state (no session) is preserved and synced on session creation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…estart run_agent_turn previously created a fresh agent without restoring the persisted conversation history, causing LLM "amnesia" after bridge or app restarts. Now injects sess.llm_history immediately after make_agent, matching the existing restore_context logic. Adds 5 tests covering history injection, empty/null cases, model preservation, and persist/reload roundtrip. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Introduce shared log components inspired by Hermes' dual-component pattern: - LogTail: follow-the-tail scrolling, hover copy, three-state (loading/empty/data) - LogView: lightweight static log container Refactor BridgeMenuPanel to use LogView with noise filtering and timestamp trimming. Refactor ChannelLogModal to use LogTail, replacing raw <pre> rendering. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…opy button on clamped messages - ChannelLogModal: give LogTail a bounded max-height so overflow-y produces a scrollbar - BridgeMenuPanel: replace event-summary with real process log tabs (bridge/conductor/scheduler), poll from bridge HTTP API, show truncation count + "View all" link - ConductorMenuPanel: use LogView component, remove manual scroll logic - UserMessage: change bubble overflow-y from auto to visible, fixing copy button hit-testing on clamped messages Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…losure, and visual language Consolidates established patterns from code and existing trellis specs into a single DESIGN.md for team and agent reference. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
fix: isolate Session and Conductor model routing
- Remove internal tool/project references from DESIGN.md - Copy microcopy, local-repo-connection, and memory-import specs to docs/spec/ - Move HANDOFF-white-screen-debug.md into docs/ for tidiness Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ntend/backend separation Documents the authoritative model selection contract: frontend reads and requests, bridge owns truth, per-session binding with global fallback, conductor independently configured. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Move specs from docs/spec/ to spec/ (the canonical location) - Delete docs/hermes-reference/ (4 files, all Hermes-saturated) - Delete docs/ADAPTATION-NOTES.md and docs/session-row-action-menu.md - Update DESIGN.md appendix paths to spec/ - Retain clean debug docs (THREAD-BLEED, WHITE-SCREEN, HANDOFF) in docs/ Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ode) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
v0.2.0 is a stable release, not pre-release. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat(desktop): add isolated e2e control interfaces * test(desktop): add WebdriverIO automation harness * ci(desktop): gate deterministic desktop journeys * ci(desktop): harden release gates * fix(ci): install Tauri libraries for Rust contracts * fix(e2e): wait past stale Windows retry state * fix(packaging): retry transient DMG creation * fix(release): emit portable Windows checksums
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
Complete desktop client implementation for GenericAgent — a React + Tauri hybrid app providing native GUI access to the agent system.
What's included
Frontend (frontends/desktop/)
Tauri shell (frontends/desktop/src-tauri/)
Bridge & backend (frontends/)
CI (.github/workflows/)
Docs & specs (frontends/desktop/spec/, DESIGN.md)
Testing
Notes