ProxyCast 是基于 Tauri 2.0 构建的跨平台桌面应用。
| 层级 | 技术 |
|---|---|
| 前端 | React + TypeScript + Tailwind CSS |
| 后端 | Rust + Tauri 2.0 |
| 构建 | Vite |
| 包管理 | pnpm |
┌─────────────────────────────────────────────────────────┐
│ Frontend (React) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Dashboard │ │ Settings │ │ Monitoring │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
│ └────────────────┼────────────────┘ │
│ │ │
│ ┌─────▼─────┐ │
│ │ Tauri │ │
│ │ Commands │ │
│ └─────┬─────┘ │
└──────────────────────────┼──────────────────────────────┘
│ IPC
┌──────────────────────────┼──────────────────────────────┐
│ ┌─────▼─────┐ │
│ │ Command │ │
│ │ Handler │ │
│ └─────┬─────┘ │
│ │ │
│ ┌───────────────────────┼───────────────────────┐ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │Provider │ │Credential│ │ Router │ │
│ │ Manager │ │ Pool │ │ │ │
│ └────┬────┘ └────┬────┘ └────┬────┘ │
│ │ │ │ │
│ └──────────────────┼──────────────────────┘ │
│ │ │
│ ┌─────▼─────┐ │
│ │ API Server│ │
│ │ (Axum) │ │
│ └───────────┘ │
│ Backend (Rust) │
└───────────────────────────────────────────────────────┘
前端通过 Tauri Commands 调用后端:
// 前端调用
import { invoke } from '@tauri-apps/api/core';
const result = await invoke('get_credentials');
// 后端处理
#[tauri::command]
async fn get_credentials() -> Result<Vec<Credential>, String> {
// 处理逻辑
}
src-tauri/src/
├── main.rs # 入口
├── lib.rs # 库导出
├── commands/ # Tauri 命令
│ ├── mod.rs
│ ├── config_cmd.rs
│ ├── credential_cmd.rs
│ └── server_cmd.rs
├── credential/ # 凭证管理
│ ├── mod.rs
│ ├── kiro.rs
│ ├── gemini.rs
│ └── qwen.rs
├── provider/ # Provider 实现
│ ├── mod.rs
│ ├── anthropic.rs
│ ├── openai.rs
│ └── gemini.rs
├── router/ # 请求路由
│ ├── mod.rs
│ └── rules.rs
├── converter/ # 协议转换
│ ├── mod.rs
│ ├── openai_to_claude.rs
│ └── claude_to_openai.rs
├── server/ # API Server
│ ├── mod.rs
│ ├── handlers.rs
│ └── middleware.rs
└── config/ # 配置管理
├── mod.rs
└── yaml.rs
负责凭证的加载、刷新和管理:
pub struct CredentialManager {
credentials: Vec<Credential>,
refresh_scheduler: RefreshScheduler,
}
impl CredentialManager {
pub async fn load_credentials(&mut self) -> Result<()>;
pub async fn refresh_token(&mut self, id: &str) -> Result<()>;
pub fn get_available(&self) -> Vec<&Credential>;
}
实现不同 AI 服务的调用:
#[async_trait]
pub trait Provider: Send + Sync {
async fn chat_completion(&self, request: ChatRequest) -> Result<ChatResponse>;
async fn stream_completion(&self, request: ChatRequest) -> Result<impl Stream<Item = StreamChunk>>;
}
根据规则路由请求:
pub struct Router {
rules: Vec<RoutingRule>,
default_provider: String,
}
impl Router {
pub fn route(&self, model: &str) -> RoutingResult;
}
在不同 API 格式之间转换:
pub fn openai_to_claude(request: OpenAIRequest) -> ClaudeRequest;
pub fn claude_to_openai(response: ClaudeResponse) -> OpenAIResponse;
1. 客户端请求 → API Server (Axum)
│
2. 认证检查 ────────┤
│
3. 路由匹配 ────────┤ Router
│
4. 凭证选择 ────────┤ Credential Pool
│
5. 协议转换 ────────┤ Converter
│
6. Provider 调用 ───┤ Provider
│
7. 响应转换 ────────┤ Converter
│
8. 返回响应 ────────┘
后端事件 → Tauri Event → 前端监听 → UI 更新
// 后端发送事件
app.emit("credential-updated", payload)?;
// 前端监听
import { listen } from '@tauri-apps/api/event';
await listen('credential-updated', (event) => {
// 更新 UI
});