feat: 从 Tauri 迁移到 Electron + Rust Daemon 架构#13
Merged
Conversation
- I-1: Route cmd_inspect/cmd_processes through daemon API instead of
per-instance SandboxClient (which fails for daemon-managed sandboxes
with port:0). Added GET /sandbox/{id}/processes endpoint to daemon
router, plus daemon_inspect/daemon_processes client functions.
- I-2: Replace std::thread::sleep with tokio::time::sleep in async
cmd_start_daemon polling loop to avoid blocking the runtime.
- I-3: cargo fmt --all applied.
- M-1: Replace .map().flatten() with .and_then() in find_daemon_binary
to satisfy clippy.
pkill -f 'sandbox' matches Electron apps (VSCode, Feishu, Chrome) whose command lines contain --no-sandbox or --enable-sandbox. Now reads daemon.json for exact daemon PID, uses pkill -x for exact name matches.
- Add POST /sandbox/{id}/pty/write for direct PTY stdin input
- Uses ProcessManager::send_input() for writing to PTY process
- Update release.sh to build and include sandbox-daemon binary
- Fixes release.sh cleanup to use PID-based approach (avoids killing unrelated apps)
Previously, sandbox type --pty and sandbox key --pty were ignored in
daemon mode — both always routed through CGEvent. Now when --pty is
specified, the commands use the daemon's /sandbox/{id}/pty/write endpoint
to write directly to PTY stdin, which is required for CLI processes
like Claude Code that use raw terminal mode.
macOS caches code signatures by file path. When cp replaces a binary at the same path, the cached signature may not match the new ad-hoc signature, causing dyld to reject loading (process enters UE state). Adding codesign --force --sign - after copy ensures the signature is refreshed.
7-task plan covering: electron-vite scaffold, daemon spawning, requestSingleInstanceLock, tab manager (WebContentsView), xterm.js renderer with standard term.write(), CLI integration, end-to-end testing.
- Update release.sh to build Electron app instead of Tauri - Fix electron-builder paths (daemon resource, output dir) - Fix package.json main field (dist/ -> out/) - CLI always spawns Electron (triggers second-instance for tab sync) - Add ELECTRON_MIRROR for Chinese network Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Redesign renderer with single-instance architecture - Add macOS-style title bar, tab bar, terminal, status bar - Add dark/light/system theme toggle with CSS variables - Use SF Pro font and macOS-native color palette - Add xterm.js terminal with refined color scheme - Poll daemon for sandbox list and auto-refresh tabs - Remove WebContentsView tab manager (simplified) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add /sandbox/{id}/ui/inspect (by sandbox id), /sandbox/{id}/ui/find,
and /sandbox/{id}/ui/value routes to the daemon. These expose the
existing AXUIElement inspection functions via HTTP.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add CLI commands for AXUIElement UI inspection via daemon HTTP API. Commands: sandbox ui-inspect --id <id>, sandbox ui-find --id <id> --role <role>, sandbox ui-value --id <id> --element-id <eid>. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- recorder.rs: JSONL action recording with timing - player.rs: async playback of recorded action sequences - diff.rs: pixel-by-pixel screenshot comparison with diff image output Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- sandbox diff --a <png> --b <png>: pixel-by-pixel screenshot comparison - sandbox record/playback: stub commands showing action details Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
4 tests covering identical images, different images, threshold sensitivity, and diff image generation. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Add periodic cleanup of dead sandboxes (30s interval)
- Add POST /sandbox/{id}/window endpoint for window_id propagation
- Use InstanceRegistry::update_status/update_window_id for lifecycle
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Add createSandbox, takeScreenshot, closeSandbox, setWindowId to api.ts - Create AppPanel component for APP mode screenshot preview - Add New Sandbox dialog with CLI/App mode selection - Add dialog and app panel CSS styles Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds `sandbox mcp-serve` command that implements JSON-RPC over stdio for agent integration. Supports tools: list_sandboxes, start_sandbox, close_sandbox, screenshot_sandbox, type_text, press_key, inspect_ui. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Tests health endpoint, list empty, create with bad mode, close/screenshot nonexistent sandbox, and unknown routes using tower oneshot. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Update CLAUDE.md and README.md to reflect the new single-daemon + Electron architecture, replacing the old Tauri multi-instance model. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
CLI sandboxes now get the Electron window_id set on creation via ScreenCapture::find_window_by_title. A background task also discovers the window 2 seconds after daemon start for sandboxes created before the Electron app launches. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Use spawn_app_with_window in the app/spawn endpoint to discover and store the app's window_id for subsequent screenshots. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds GET /sandbox/{id}/screenshot/region?x=&y=&width=&height= for
capturing a sub-region of the sandbox window.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The daemon's cleanup_dead_sandboxes was calling libc::kill(pty_pid, 0) to check if PTY processes were alive. But pty_pid is the internal tracked_id (1000+), not the actual OS PID, so the check always failed and all CLI sandboxes were immediately cleaned up. Changes: - Add os_pid field to ProcessInfo for actual OS PID tracking - Add ProcessManager::is_session_alive() to check SESSIONS HashMap - Update daemon cleanup to use session existence check - Add implementation plans for phases 3-8 - Update release README and test docs Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Remove src-tauri/ and sandbox-web/ directories as the project has fully migrated to Electron + daemon architecture. Update Cargo.toml workspace members and fix ProcessInfo tests for os_pid field. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Replace &PathBuf with &Path in player.rs and main.rs (clippy::ptr_arg) - Use output.as_deref() instead of output.as_ref() for Option<&Path> coercion - Add #[allow(dead_code)] to unused daemon_set_window_id and find_running_electron - Update ci.yml frontend test job: sandbox-web → electron-app - Apply cargo fmt formatting fixes Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Add vitest and @vitest/coverage-v8 as devDependencies - Create vitest.config.ts for electron-app - Add unit tests for daemon API client pure functions - Add test and test:unit scripts to package.json Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
🔒 门禁检查结果
Rust 测试覆盖率
前端测试覆盖率
✅ 所有检查通过,可以合入
|
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
架构迁移:Tauri → Electron + Rust Daemon
本 PR 是一次重大架构变更,将项目从 Tauri (WKWebView) 迁移到 Electron (Chromium) + 独立 Rust daemon 的架构。核心动机是解决 Tauri WKWebView 在终端渲染中的已知问题(setTimeout 失效、渲染残留、无 DevTools),参见 架构设计文档。
主要变更:
sandbox-daemon:独立 Rust daemon 进程,管理所有沙箱实例(PTY + macOS 应用),通过单一 HTTP API 对外服务electron-app:Electron 应用作为 GUI 前端,提供 tab 管理、xterm.js 终端和截图预览src-tauri/和sandbox-web/(旧 Tauri 前端)os_pid字段:ProcessInfo增加os_pid字段和ProcessManager::is_session_alive()方法架构对比
Test plan
cargo check --all-targets构建通过🤖 Generated with Claude Code