fix: resolve Windows compilation errors and warnings

- Add Manager trait import for windows_startup_cmd.rs
- Add explicit type annotations for PathBuf in windows_startup_cmd.rs
- Fix unused import warning in screenshot_capture_service.rs
- Prefix unused variables with underscore in runner.rs and aster_agent_cmd.rs
- Update package.json with Node.js engine requirement
This commit is contained in:
coso
2026-03-10 09:20:40 +08:00
parent 276e2064c2
commit 2adf8c2bc2
33 changed files with 1484 additions and 305 deletions
@@ -13,12 +13,12 @@ navigation:
### 前置要求
| 工具 | 版本 |
|------|------|
| Node.js | >= 18 |
| pnpm | >= 8 |
| Rust | >= 1.70 |
| Tauri CLI | >= 2.0 |
| 工具 | 版本 |
| --------- | ------- |
| Node.js | >= 22 |
| pnpm | >= 8 |
| Rust | >= 1.70 |
| Tauri CLI | >= 2.0 |
### 安装依赖
+23 -18
View File
@@ -17,10 +17,12 @@ navigation:
```bash
# 使用 nvm 安装
nvm install 18
nvm use 18
nvm install 22
nvm use 22
```
Windows 用户请使用 Node.js 官方安装器安装 22.x,并重新打开终端后通过 `node -v` 确认版本。
2. **安装 pnpm**
```bash
@@ -40,15 +42,18 @@ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
4. **安装 Tauri 依赖**
**macOS:**
```bash
xcode-select --install
```
**Windows:**
- 安装 Visual Studio Build Tools
- 安装 WebView2(开发模式必需;对外分发时建议使用带离线 WebView2 的 NSIS 安装器)
**Linux:**
```bash
sudo apt install libwebkit2gtk-4.1-dev build-essential curl wget file libssl-dev libayatana-appindicator3-dev librsvg2-dev
```
@@ -64,6 +69,7 @@ pnpm tauri dev
```
开发模式特性:
- 前端热重载
- Rust 代码变更自动重新编译
- 开发者工具可用
@@ -111,11 +117,11 @@ pnpm tauri build --debug
### 构建产物
| 平台 | 产物位置 |
|------|----------|
| macOS | `src-tauri/target/release/bundle/dmg/` |
| 平台 | 产物位置 |
| ------- | --------------------------------------- |
| macOS | `src-tauri/target/release/bundle/dmg/` |
| Windows | `src-tauri/target/release/bundle/nsis/` |
| Linux | `src-tauri/target/release/bundle/deb/` |
| Linux | `src-tauri/target/release/bundle/deb/` |
### 跨平台构建
@@ -141,7 +147,6 @@ pnpm tauri build --target x86_64-pc-windows-msvc --config src-tauri/tauri.window
> 建议对外分发 `-setup.exe`,不要把默认 `.msi` 作为首选下载项。
#### Linux 构建
```bash
@@ -195,12 +200,12 @@ git push origin v1.0.1
### 构建矩阵
| 平台 | 架构 | Runner |
|------|------|--------|
| macOS | arm64 | macos-latest |
| macOS | x64 | macos-13 |
| Windows | x64 | windows-2022 |
| Linux | x64 | ubuntu-latest |
| 平台 | 架构 | Runner |
| ------- | ----- | ------------- |
| macOS | arm64 | macos-latest |
| macOS | x64 | macos-13 |
| Windows | x64 | windows-2022 |
| Linux | x64 | ubuntu-latest |
## 调试
@@ -217,11 +222,11 @@ RUST_LOG=debug pnpm tauri dev
### 日志位置
| 平台 | 路径 |
|------|------|
| macOS | `~/Library/Logs/ProxyCast/` |
| Windows | `%APPDATA%\ProxyCast\logs\` |
| Linux | `~/.local/share/proxycast/logs/` |
| 平台 | 路径 |
| ------- | -------------------------------- |
| macOS | `~/Library/Logs/ProxyCast/` |
| Windows | `%APPDATA%\ProxyCast\logs\` |
| Linux | `~/.local/share/proxycast/logs/` |
## 常见问题
+3
View File
@@ -1,5 +1,8 @@
{
"name": "proxycast-docs",
"engines": {
"node": ">=22.0.0"
},
"scripts": {
"dev": "nuxt dev --extends docus",
"build": "nuxt build --extends docus",
+77 -65
View File
@@ -5,6 +5,7 @@
## 概述
E2E 测试模拟真实用户操作,验证从前端到后端的完整流程。ProxyCast 使用 Tauri 框架,E2E 测试需要覆盖:
- 桌面应用启动和初始化
- 用户界面交互
- API 代理完整流程
@@ -28,13 +29,13 @@ npm run test:e2e
```javascript
// playwright.config.ts
import { defineConfig } from '@playwright/test';
import { defineConfig } from "@playwright/test";
export default defineConfig({
testDir: './tests/e2e',
testDir: "./tests/e2e",
timeout: 30000,
use: {
baseURL: 'tauri://localhost',
baseURL: "tauri://localhost",
},
});
```
@@ -44,23 +45,23 @@ export default defineConfig({
### 1. 应用启动流程
```typescript
import { test, expect } from '@playwright/test';
import { test, expect } from "@playwright/test";
test.describe('应用启动', () => {
test('应用正常启动并显示主界面', async ({ page }) => {
test.describe("应用启动", () => {
test("应用正常启动并显示主界面", async ({ page }) => {
// 等待应用加载
await page.waitForSelector('[data-testid="main-layout"]');
// 验证核心组件存在
await expect(page.locator('[data-testid="sidebar"]')).toBeVisible();
await expect(page.locator('[data-testid="content-area"]')).toBeVisible();
});
test('首次启动显示欢迎引导', async ({ page }) => {
test("首次启动显示欢迎引导", async ({ page }) => {
// 清除本地存储模拟首次启动
await page.evaluate(() => localStorage.clear());
await page.reload();
await expect(page.locator('[data-testid="welcome-modal"]')).toBeVisible();
});
});
@@ -69,35 +70,37 @@ test.describe('应用启动', () => {
### 2. 凭证管理流程
```typescript
test.describe('凭证管理', () => {
test('添加 Kiro 凭证', async ({ page }) => {
test.describe("凭证管理", () => {
test("添加 Kiro 凭证", async ({ page }) => {
// 打开凭证管理
await page.click('[data-testid="credentials-tab"]');
await page.click('[data-testid="add-credential-btn"]');
// 选择 Provider
await page.click('[data-testid="provider-kiro"]');
// 上传凭证文件
const fileInput = page.locator('input[type="file"]');
await fileInput.setInputFiles('./tests/fixtures/test-credential.json');
await fileInput.setInputFiles("./tests/fixtures/test-credential.json");
// 验证凭证添加成功
await expect(page.locator('[data-testid="credential-item"]')).toBeVisible();
await expect(page.locator('text=test@example.com')).toBeVisible();
await expect(page.locator("text=test@example.com")).toBeVisible();
});
test('删除凭证', async ({ page }) => {
test("删除凭证", async ({ page }) => {
// 假设已有凭证
await page.click('[data-testid="credentials-tab"]');
// 删除凭证
await page.click('[data-testid="credential-menu"]');
await page.click('[data-testid="delete-credential"]');
await page.click('[data-testid="confirm-delete"]');
// 验证凭证已删除
await expect(page.locator('[data-testid="credential-item"]')).not.toBeVisible();
await expect(
page.locator('[data-testid="credential-item"]'),
).not.toBeVisible();
});
});
```
@@ -105,33 +108,38 @@ test.describe('凭证管理', () => {
### 3. API 代理流程
```typescript
test.describe('API 代理', () => {
test('启动代理服务器', async ({ page }) => {
test.describe("API 代理", () => {
test("启动代理服务器", async ({ page }) => {
await page.click('[data-testid="server-tab"]');
await page.click('[data-testid="start-server-btn"]');
// 等待服务器启动
await expect(page.locator('text=服务器运行中')).toBeVisible();
await expect(page.locator('[data-testid="server-port"]')).toContainText('8080');
await expect(page.locator("text=服务器运行中")).toBeVisible();
await expect(page.locator('[data-testid="server-port"]')).toContainText(
"8080",
);
});
test('代理请求成功', async ({ page, request }) => {
test("代理请求成功", async ({ page, request }) => {
// 启动服务器
await page.click('[data-testid="start-server-btn"]');
await page.waitForSelector('text=服务器运行中');
await page.waitForSelector("text=服务器运行中");
// 发送测试请求
const response = await request.post('http://localhost:8080/v1/chat/completions', {
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer test-key',
const response = await request.post(
"http://localhost:8080/v1/chat/completions",
{
headers: {
"Content-Type": "application/json",
Authorization: "Bearer test-key",
},
data: {
model: "gpt-4",
messages: [{ role: "user", content: "Hello" }],
},
},
data: {
model: 'gpt-4',
messages: [{ role: 'user', content: 'Hello' }],
},
});
);
expect(response.ok()).toBeTruthy();
});
});
@@ -140,28 +148,30 @@ test.describe('API 代理', () => {
### 4. Agent 对话流程
```typescript
test.describe('Agent 对话', () => {
test('发送消息并接收响应', async ({ page }) => {
test.describe("Agent 对话", () => {
test("发送消息并接收响应", async ({ page }) => {
await page.click('[data-testid="agent-tab"]');
// 输入消息
await page.fill('[data-testid="message-input"]', '你好,请介绍一下自己');
await page.fill('[data-testid="message-input"]', "你好,请介绍一下自己");
await page.click('[data-testid="send-btn"]');
// 等待响应
await expect(page.locator('[data-testid="assistant-message"]')).toBeVisible({
timeout: 30000,
});
await expect(page.locator('[data-testid="assistant-message"]')).toBeVisible(
{
timeout: 30000,
},
);
});
test('流式响应正确显示', async ({ page }) => {
test("流式响应正确显示", async ({ page }) => {
await page.click('[data-testid="agent-tab"]');
await page.fill('[data-testid="message-input"]', '写一首短诗');
await page.fill('[data-testid="message-input"]', "写一首短诗");
await page.click('[data-testid="send-btn"]');
// 验证流式显示(内容逐渐增加)
const messageEl = page.locator('[data-testid="assistant-message"]');
let prevLength = 0;
for (let i = 0; i < 5; i++) {
await page.waitForTimeout(500);
@@ -193,20 +203,22 @@ tests/
```typescript
// tests/mocks/api-server.ts
import { setupServer } from 'msw/node';
import { rest } from 'msw';
import { setupServer } from "msw/node";
import { rest } from "msw";
export const mockServer = setupServer(
rest.post('*/v1/chat/completions', (req, res, ctx) => {
rest.post("*/v1/chat/completions", (req, res, ctx) => {
return res(
ctx.json({
id: 'test-id',
choices: [{
message: { role: 'assistant', content: 'Mock response' },
}],
})
id: "test-id",
choices: [
{
message: { role: "assistant", content: "Mock response" },
},
],
}),
);
})
}),
);
```
@@ -239,21 +251,21 @@ jobs:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '20'
node-version: "22"
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
- name: Install dependencies
run: npm ci
- name: Build app
run: npm run build
- name: Run E2E tests
run: npm run test:e2e
```