refactor(desktop): 从 Tauri 迁移到 Electrobun

- 移除 Tauri v2 代码 (src-tauri/, copy.ts)
- 添加 Electrobun 配置和入口 (electrobun.config.ts, src/bun/index.ts)
- 更新 package.json 使用 catalog 管理 electrobun 依赖
- 移除 server 中的 @tauri-apps/api 依赖
- 更新 AGENTS.md 文档
This commit is contained in:
2026-02-07 05:04:53 +08:00
parent 9aa3b46ee5
commit 29969550ed
38 changed files with 332 additions and 6296 deletions

View File

@@ -1,51 +1,33 @@
# AGENTS.md - Desktop App Guidelines
Tauri v2 desktop shell - a lightweight wrapper that loads the server app via sidecar.
Electrobun desktop shell - loads the server app in a native window.
## Architecture
- **Type**: Tauri v2 desktop application (shell only)
- **Design**: Tauri provides native desktop APIs; all web logic handled by sidecar
- **Sidecar**: The compiled server binary runs as a child process
- **Type**: Electrobun desktop application
- **Design**: Bun main process + system webview (or CEF)
- **Dev mode**: Connects to `localhost:3000` (requires server dev running)
- **Prod mode**: Automatically starts sidecar binary
**This app has NO frontend src** - it loads the server app entirely.
- **Prod mode**: Embeds server bundle and starts local HTTP server
## Commands
```bash
# Development (from apps/desktop/)
bun dev # Copy sidecar + start Tauri dev
bun dev # Start Electrobun dev mode
# Build
bun build # Copy sidecar + build Tauri installer
# Rust Commands (from src-tauri/)
cargo check # Compile check
cargo clippy # Linter
cargo fmt # Formatter
cargo test # Run tests
cargo test test_name -- --nocapture # Single test with output
bun build # Build canary release
bun build:stable # Build stable release
```
## Directory Structure
```
apps/desktop/
├── src-tauri/ # Rust Tauri code
── src/
── main.rs # Entry point (calls lib::run)
│ │ ├── lib.rs # Core app logic (plugins, commands, state)
│ │ ├── commands/
│ │ │ └── mod.rs # Native desktop commands
│ │ └── sidecar.rs # Sidecar process management
│ ├── binaries/ # Sidecar binaries (copied from server build)
│ ├── capabilities/ # Tauri v2 permission config
│ ├── icons/ # App icons
│ ├── Cargo.toml # Rust dependencies
│ └── tauri.conf.json # Tauri configuration
├── copy.ts # Script to copy server binary to binaries/
├── src/
── bun/
── index.ts # Electrobun main process entry
├── electrobun.config.ts # Electrobun configuration
├── package.json
└── tsconfig.json
```
@@ -53,119 +35,45 @@ apps/desktop/
## Development Workflow
1. **Start server dev first**: `cd ../server && bun dev`
2. **Start Tauri**: `bun dev` (from apps/desktop/)
3. Tauri connects to localhost:3000 with HMR support
2. **Start Electrobun**: `bun dev` (from apps/desktop/)
3. Electrobun connects to localhost:3000
## Rust Code Style
## Electrobun Patterns
### Formatting
- **Indent**: 4 spaces
- **Line width**: 100 chars
- Run `cargo fmt` before commit
### BrowserWindow
### Naming
| Type | Convention | Example |
|------|------------|---------|
| Functions/variables | snake_case | `find_available_port` |
| Types/structs/enums | PascalCase | `SidecarProcess` |
| Constants | SCREAMING_SNAKE | `DEFAULT_PORT` |
```typescript
import { BrowserWindow } from 'electrobun/bun'
### Imports
```rust
// Order: std → external crates → internal modules (separated by blank lines)
use std::sync::Mutex;
use tauri::Manager;
use tauri_plugin_shell::ShellExt;
use crate::sidecar::SidecarProcess;
new BrowserWindow({
title: 'My App',
url: 'http://localhost:3000',
frame: {
x: 100,
y: 100,
width: 1200,
height: 800,
},
})
```
### Error Handling
```rust
// Use expect() with Chinese error messages
let sidecar = app_handle
.shell()
.sidecar("server")
.expect("无法找到 server sidecar");
### Events
// Log with emoji for clear feedback
println!("✓ Sidecar 启动成功!");
eprintln!("✗ Sidecar 启动失败");
```
```typescript
import Electrobun from 'electrobun/bun'
### Async Code
```rust
// Use Tauri's async runtime for spawning
tauri::async_runtime::spawn(async move {
let port = find_available_port(3000).await;
// ...
});
```
## Tauri Patterns
### Command Definition
```rust
#[tauri::command]
fn greet(name: &str) -> String {
format!("Hello, {}!", name)
}
// Register in Builder
.invoke_handler(tauri::generate_handler![commands::greet])
```
### State Management
```rust
struct SidecarProcess(Mutex<Option<CommandChild>>);
// Register state
app.manage(SidecarProcess(Mutex::new(None)));
// Access state
if let Some(state) = app_handle.try_state::<SidecarProcess>() {
*state.0.lock().unwrap() = Some(child);
}
```
### Sidecar Lifecycle
```rust
// Start sidecar with environment
let sidecar = app_handle
.shell()
.sidecar("server")
.expect("无法找到 server sidecar")
.env("PORT", port.to_string());
// Cleanup on exit
match event {
tauri::RunEvent::ExitRequested { .. } | tauri::RunEvent::Exit => {
if let Some(child) = process.take() {
let _ = child.kill();
}
}
_ => {}
}
Electrobun.events.on('will-quit', () => {
console.log('App quitting...')
})
```
## Critical Rules
**DO:**
- Run `cargo fmt` and `cargo clippy` before commit
- Use `expect("中文消息")` instead of `unwrap()`
- Always cleanup sidecar on app exit
- Declare sidecar in `tauri.conf.json``bundle.externalBin`
- Run server dev before desktop dev
- Use `catalog:` for dependencies
- Handle server startup gracefully
**DON'T:**
- Edit `gen/schemas/` (auto-generated)
- Use `unwrap()` in production code without context
- Block the async runtime (use `spawn_blocking`)
## Pre-commit Checklist
- [ ] `cargo fmt` - formatting
- [ ] `cargo clippy` - linting
- [ ] `cargo check` - compiles
- [ ] `cargo test` - tests pass
- [ ] Tauri app starts and exits cleanly
- Hardcode dependency versions (use catalog)
- Block main thread during server wait