9.0 KiB
9.0 KiB
@ai-assistant/desktop
AI Terminal Assistant 的原生桌面应用 - 基于 Tauri 构建,实现跨平台支持。
📦 安装
# 安装依赖
pnpm install
# 开发
pnpm dev
# 构建当前平台版本
pnpm build
# 构建所有平台版本
pnpm build:all
🌟 功能特性
- 原生性能 - 使用 Rust 和 Tauri 构建,速度极快
- 跨平台 - 支持 Windows、macOS 和 Linux
- 小体积 - ~10MB 安装包,~30MB 安装后大小
- 系统集成 - 原生菜单、通知和系统托盘
- 默认安全 - 沙盒化,最小权限
- 自动更新 - 内置更新机制
- 本地存储 - 使用 SQLite 存储离线数据
- 基于 WebView - 现代 Web UI 配合原生包装
- 全局快捷键 - 系统级键盘快捷键
- 文件系统访问 - 原生文件对话框和操作
🏗️ 架构
src-tauri/
├── src/
│ ├── main.rs # 主入口点
│ ├── app.rs # 应用设置
│ ├── commands/ # Tauri 命令
│ │ ├── chat.rs # 对话操作
│ │ ├── file.rs # 文件操作
│ │ ├── system.rs # 系统集成
│ │ └── window.rs # 窗口管理
│ ├── menu.rs # 原生菜单设置
│ ├── tray.rs # 系统托盘
│ ├── updater.rs # 自动更新逻辑
│ ├── store.rs # 本地数据存储
│ └── utils/ # 工具函数
├── Cargo.toml # Rust 依赖
├── tauri.conf.json # Tauri 配置
└── icons/ # 应用图标
src/
├── App.tsx # React 应用入口
├── components/ # UI 组件(与 web 共享)
├── hooks/ # 自定义 Hooks
├── services/ # 桌面特定服务
│ ├── ipc.ts # Tauri IPC 通信
│ ├── storage.ts # 本地存储
│ └── shortcuts.ts # 键盘快捷键
└── styles/ # 桌面特定样式
🚀 快速开始
前置要求
- Node.js 18+ 和 pnpm
- Rust 1.70+(从 rustup.rs 安装)
- 平台工具:
- Windows:Visual Studio C++ 生成工具
- macOS:Xcode 命令行工具
- Linux:
build-essential、libwebkit2gtk-4.0-dev、libssl-dev
开发设置
# 克隆仓库
git clone <repository-url>
cd ai-terminal-assistant/packages/desktop
# 安装依赖
pnpm install
# 启动开发服务器
pnpm dev
# 应用将自动打开,支持热重载
生产构建
# 构建当前平台
pnpm build
# 构建特定平台
pnpm build:windows
pnpm build:mac
pnpm build:linux
# 构建 macOS 通用二进制文件
pnpm build:mac-universal
# 构建并签名(需要证书)
pnpm build:signed
🖥️ 平台功能
Windows
- 安装程序类型:MSI、NSIS、便携版
- 系统启动时自动启动
- Windows Store 分发就绪
- 原生通知
- 跳转列表集成
macOS
- 格式:DMG、App Bundle
- 代码签名和公证
- macOS App Store 就绪
- Touch Bar 支持
- 原生菜单栏
Linux
- 包格式:AppImage、Deb、RPM
- 系统托盘支持
- 桌面条目创建
- Snap/Flatpak 就绪
- Wayland/X11 兼容
⚙️ 配置
Tauri 配置
src-tauri/tauri.conf.json:
{
"package": {
"productName": "AI Terminal Assistant",
"version": "1.0.0"
},
"tauri": {
"allowlist": {
"all": false,
"shell": {
"execute": true,
"open": true
},
"fs": {
"all": true,
"scope": ["$HOME/**", "$RESOURCE/**"]
},
"http": {
"all": true,
"scope": ["http://localhost/*", "https://api.anthropic.com/*"]
},
"notification": {
"all": true
},
"globalShortcut": {
"all": true
}
},
"windows": [{
"title": "AI Terminal Assistant",
"width": 1200,
"height": 800,
"resizable": true,
"fullscreen": false
}],
"systemTray": {
"iconPath": "icons/icon.png",
"menuOnLeftClick": false
},
"updater": {
"active": true,
"endpoints": ["https://updates.example.com/check"]
}
}
}
🔌 Tauri 命令
IPC 通信
// 前端(TypeScript)
import { invoke } from '@tauri-apps/api/tauri';
// 调用 Rust 命令
const result = await invoke('send_message', {
message: '来自前端的消息'
});
// 监听事件
import { listen } from '@tauri-apps/api/event';
const unlisten = await listen('chat-update', (event) => {
console.log('新消息:', event.payload);
});
// 后端(Rust)
#[tauri::command]
fn send_message(message: String) -> Result<String, String> {
// 处理消息
Ok(format!("收到: {}", message))
}
// 发送事件
app.emit_all("chat-update", Payload {
message: "新更新"
}).unwrap();
🎨 原生功能
系统托盘
import { createTray } from './services/tray';
const tray = await createTray({
icon: '/icons/tray.png',
menu: [
{ label: '显示', action: () => showWindow() },
{ label: '隐藏', action: () => hideWindow() },
{ separator: true },
{ label: '退出', action: () => app.quit() }
]
});
全局快捷键
import { register } from '@tauri-apps/api/globalShortcut';
// 注册全局热键
await register('CommandOrControl+Shift+A', () => {
console.log('快捷键触发!');
window.show();
});
文件操作
import { open, save } from '@tauri-apps/api/dialog';
import { readTextFile, writeFile } from '@tauri-apps/api/fs';
// 打开文件对话框
const selected = await open({
multiple: false,
filters: [{
name: '文本',
extensions: ['txt', 'md']
}]
});
// 读取文件
const content = await readTextFile(selected);
// 保存文件对话框
const savePath = await save({
filters: [{ name: '文本', extensions: ['txt'] }]
});
await writeFile(savePath, '内容');
通知
import { sendNotification } from '@tauri-apps/api/notification';
await sendNotification({
title: 'AI Assistant',
body: '任务成功完成!',
icon: '/icons/icon.png'
});
🔐 安全
权限
- 最小权限模型
- 限定范围的文件系统访问
- 受控的 Shell 执行
- 强制 CSP 头
代码签名
# macOS
codesign --deep --force --verify --verbose \
--sign "Developer ID Application: Your Name" \
target/release/bundle/osx/AI\ Terminal\ Assistant.app
# Windows(使用 SignTool)
signtool sign /a /tr http://timestamp.digicert.com \
/td SHA256 /fd SHA256 \
target/release/bundle/msi/AI_Terminal_Assistant.msi
🚢 分发
自动更新
// src-tauri/src/updater.rs
use tauri::updater::builder::UpdateBuilder;
pub fn check_for_updates(app: &tauri::App) {
let update = UpdateBuilder::new()
.current_version(&app.package_info().version)
.url("https://updates.example.com/check")
.build()
.unwrap();
if update.should_update {
update.download_and_install().unwrap();
}
}
GitHub 发布
# .github/workflows/release.yml
name: Release
on:
push:
tags: ['v*']
jobs:
release:
strategy:
matrix:
platform: [macos-latest, ubuntu-latest, windows-latest]
runs-on: ${{ matrix.platform }}
steps:
- uses: actions/checkout@v3
- uses: tauri-apps/tauri-action@v0
with:
tagName: v__VERSION__
releaseName: 'v__VERSION__'
releaseBody: '查看 CHANGELOG.md'
releaseDraft: true
prerelease: false
🧪 测试
# 单元测试(Rust)
cd src-tauri
cargo test
# 集成测试
pnpm test:integration
# 使用 WebDriver 的端到端测试
pnpm test:e2e
📊 性能
优化技巧
- 懒加载 - 按需加载功能
- IPC 批处理 - 批量处理多个命令
- 资源优化 - 压缩图片/字体
- 内存管理 - 清理监听器
- 后台任务 - 使用 Web Workers
基准测试
| 指标 | 值 |
|---|---|
| 启动时间 | < 500ms |
| 内存使用 | ~50MB 空闲 |
| 包大小 | ~10MB 压缩 |
| CPU 使用 | < 5% 空闲 |
🐛 调试
开发工具
# 启用开发工具
pnpm dev -- --features devtools
# Rust 调试
RUST_LOG=debug pnpm dev
# WebView 调试
# 在应用窗口中按 F12
日志记录
// Rust 日志
use log::{info, error};
info!("应用已启动");
error!("加载失败: {}", error);
// 前端日志
import { info, error } from '@tauri-apps/api/log';
await info('应用已启动');
await error(`加载失败: ${error}`);
🤝 贡献
请查看主仓库的贡献指南了解详情。
📄 许可证
MIT 许可证 - 查看 LICENSE 了解详情。