chore: initialize qiming workspace repository

This commit is contained in:
Codex
2026-05-29 14:22:48 +08:00
commit bfd67a0f2c
10750 changed files with 1885711 additions and 0 deletions

View File

@@ -0,0 +1,377 @@
# qiming-agent Windows CREATE_NO_WINDOW 验证报告
## 检查日期
2026-02-12
## 检查结果:✅ 全部已正确处理
---
## 验证摘要
qiming-agent 项目中所有启动子进程的地方都**已正确实现** Windows `CREATE_NO_WINDOW` 标志。
### 实现方式
**1. 统一的 Trait 封装**
- 文件:`crates/qiming-agent-core/src/utils/command.rs`
- 提供了 `CommandNoWindowExt` trait
- 同时支持 `std::process::Command``tokio::process::Command`
```rust
pub trait CommandNoWindowExt {
fn no_window(&mut self) -> &mut Self;
}
impl CommandNoWindowExt for Command {
fn no_window(&mut self) -> &mut Self {
#[cfg(windows)]
{
use std::os::windows::process::CommandExt;
const CREATE_NO_WINDOW: u32 = 0x08000000;
self.creation_flags(CREATE_NO_WINDOW)
}
#[cfg(not(windows))]
self
}
}
```
**2. process-wrap 集成**
- 使用 `process_wrap::tokio::CreationFlags`
- Windows: `CREATE_NO_WINDOW | DETACHED_PROCESS`
- 配合 `JobObject` 管理进程树
---
## 详细检查结果
### 1. ✅ MCP Proxy 启动
**文件**: `crates/qiming-agent-core/src/service/mod.rs:1271-1378`
**启动方法**: `mcp_proxy_start_with_config()`
**CREATE_NO_WINDOW 实现** (第 1332 行):
```rust
#[cfg(target_os = "windows")]
let child: Box<dyn process_wrap::tokio::ChildWrapper> = cmd
.wrap(process_wrap::tokio::KillOnDrop)
.wrap(CreationFlags(CREATE_NO_WINDOW | DETACHED_PROCESS)) // ✅ 禁止弹出 CMD 窗口
.wrap(JobObject)
.spawn()
```
**使用场景**:
- 启动 `mcp-proxy.cmd` (npm 全局包)
- 监听端口: 18099 (默认)
- 启动命令: `mcp-proxy server --port 18099 --config <config>`
**状态**: ✅ **已正确实现**
---
### 2. ✅ File Server 启动
**文件**: `crates/qiming-agent-core/src/service/mod.rs:924-1061`
**启动方法**: `file_server_start_with_config()`
**CREATE_NO_WINDOW 实现** (第 1048 行):
```rust
#[cfg(target_os = "windows")]
let mut child: Box<dyn process_wrap::tokio::ChildWrapper> = cmd
.wrap(process_wrap::tokio::KillOnDrop)
.wrap(CreationFlags(CREATE_NO_WINDOW | DETACHED_PROCESS)) // ✅ 禁止弹出 CMD 窗口
.wrap(JobObject)
.spawn()
```
**使用场景**:
- 启动 `qiming-file-server.cmd` (npm 全局包)
- 监听端口: 60000 (默认)
- 启动命令: `qiming-file-server start --env production --port 60000 ...`
**额外优点**:
-`CommandWrap::with_new` 闭包中使用 `.no_window()`
- 双重保险trait 方法 + process-wrap 标志
**状态**: ✅ **已正确实现**
---
### 3. ✅ Lanproxy 启动
**文件**: `crates/qiming-agent-core/src/service/mod.rs:1076-1124`
**启动方法**: `lanproxy_start()`
**CREATE_NO_WINDOW 实现** (第 1118 行):
```rust
#[cfg(target_os = "windows")]
let child: Box<dyn process_wrap::tokio::ChildWrapper> = cmd
.wrap(process_wrap::tokio::KillOnDrop)
.wrap(CreationFlags(CREATE_NO_WINDOW | DETACHED_PROCESS)) // ✅ 禁止弹出 CMD 窗口
.wrap(JobObject)
.spawn()
```
**使用场景**:
- 启动 `qiming-lanproxy.exe` (Tauri Sidecar 二进制)
- 启动命令: `qiming-lanproxy -s <server> -p <port> -k <key> --ssl=true`
**状态**: ✅ **已正确实现**
---
### 4. ✅ 辅助命令执行
**文件**: `crates/qiming-agent-core/src/service/mod.rs:72-118`
**函数**: `run_command_with_timeout()`
**CREATE_NO_WINDOW 实现** (第 78 行):
```rust
let mut cmd = process_wrap::tokio::CommandWrap::with_new(program, |cmd| {
use crate::utils::CommandNoWindowExt;
cmd.no_window() // ✅ 使用 trait 方法隐藏窗口
.env("PATH", &node_path);
// ...
});
#[cfg(target_os = "windows")]
let spawn_result = cmd
.wrap(process_wrap::tokio::KillOnDrop)
.wrap(CreationFlags(CREATE_NO_WINDOW | DETACHED_PROCESS)) // ✅ 双重保险
.wrap(JobObject)
.spawn();
```
**使用场景**:
- 运行临时命令(如 `tasklist`, `taskkill`, `kill` 等)
- 检测进程状态
- 清理残留进程
**状态**: ✅ **已正确实现**
---
### 5. ✅ 进程检测辅助函数
**文件**: `crates/qiming-agent-core/src/service/mod.rs:149-252`
**函数**: `find_processes_by_name()`, `is_pid_running()`
**CREATE_NO_WINDOW 实现**:
```rust
#[cfg(any(target_os = "linux", target_os = "macos"))]
{
let output = tokio::process::Command::new("pgrep")
.no_window() // ✅ 使用 trait 方法
.arg("-x")
.arg(process_name)
.output()
.await
.ok()?;
}
#[cfg(target_os = "windows")]
{
let output = tokio::process::Command::new("tasklist")
.no_window() // ✅ 使用 trait 方法
.args([...])
.output()
.await
.ok()?;
}
```
**使用场景**:
- 检测进程是否运行
- 查找进程 PID
- 验证服务状态
**状态**: ✅ **已正确实现**
---
## 实现模式总结
### 模式 A: process-wrap + CreationFlags (主要服务)
**适用于**: mcp-proxy, file-server, lanproxy 的主进程
```rust
let mut cmd = process_wrap::tokio::CommandWrap::with_new(bin_path, |cmd| {
use crate::utils::CommandNoWindowExt;
cmd.no_window() // trait 方法(第一层保护)
.arg("...")
.env("...", "...");
});
#[cfg(target_os = "windows")]
let child = cmd
.wrap(process_wrap::tokio::KillOnDrop)
.wrap(CreationFlags(CREATE_NO_WINDOW | DETACHED_PROCESS)) // process-wrap 标志(第二层保护)
.wrap(JobObject)
.spawn()?;
```
**优点**:
- 双重保险trait + process-wrap
- 自动进程树管理JobObject
- 自动清理KillOnDrop
---
### 模式 B: tokio::process::Command + no_window() (辅助命令)
**适用于**: 临时命令、进程检测
```rust
let output = tokio::process::Command::new("tasklist")
.no_window() // trait 方法扩展
.args([...])
.output()
.await?;
```
**优点**:
- 简洁
- 适合短期命令
- 无需进程树管理
---
## 对比 mcp-proxy 项目
| 项目 | 实现方式 | 双重保险 | 统一 API |
|------|---------|---------|---------|
| **qiming-agent** | ✅ trait + process-wrap | ✅ 是 | ✅ CommandNoWindowExt |
| **mcp-proxy** | ✅ process-wrap / CommandExt | ❌ 否 | ❌ 分散实现 |
**qiming-agent 的优势**:
1. **统一的 trait 接口**: 所有 Command 都可以调用 `.no_window()`
2. **双重保护**: 既在 Command 层面设置,又在 process-wrap 层面设置
3. **代码一致性**: 所有地方使用相同的模式
---
## 测试验证
### 手动测试步骤 (Windows)
1. **启动 qiming-agent**:
```bash
# 从 Tauri 应用启动
```
2. **观察进程**:
```powershell
# 检查是否有 CMD 窗口弹出
# 预期:无 CMD 窗口
# 检查进程树
tasklist /FI "IMAGENAME eq mcp-proxy*"
tasklist /FI "IMAGENAME eq qiming-file-server*"
tasklist /FI "IMAGENAME eq qiming-lanproxy*"
# 预期:进程存在但无关联的 conhost.exe
```
3. **测试场景**:
- ✅ 启动 mcp-proxy 服务
- ✅ 启动 file-server 服务
- ✅ 启动 lanproxy 服务
- ✅ 重启服务
- ✅ 停止服务
4. **验证标准**:
- 无 CMD 窗口弹出
- 服务正常启动
- 健康检查通过
- 日志正常输出
---
## 已知问题与解决方案
### ⚠️ 问题 1: mcp-proxy 健康检查超时
**日志证据** (qiming-agent.log.2026-02-12):
```
2026-02-12T06:19:01.052725Z ERROR [McpProxy] 健康检查失败:
MCP Proxy 健康检查超时: 等待 15s 后 http://127.0.0.1:18099/mcp 仍未就绪
```
**分析**:
- mcp-proxy 进程启动成功CREATE_NO_WINDOW 生效)
- 但 HTTP 服务器未能正常运行
- **与 CREATE_NO_WINDOW 无关**,是 mcp-proxy 本身的问题
**可能原因**:
1. mcp-proxy 内部 panic/crash
2. 端口被占用
3. 配置文件错误
4. Node.js 环境问题
**建议诊断**:
```powershell
# 手动运行查看错误
C:\Users\MECHREVO\.local\bin\mcp-proxy.cmd server --port 18099
```
**解决方案**: 需要 mcp-proxy 升级到 v0.1.39+ 并验证
---
### ✅ 问题 2: CMD 窗口隐藏
**状态**: **已解决**qiming-agent 代码已正确实现)
**验证方法**:
1. 编译最新的 qiming-agent
2. 在 Windows 上测试
3. 确认无 CMD 窗口弹出
---
## 结论
### ✅ qiming-agent 侧:无需修改
**验证结果**:
1.**所有服务启动点都已正确实现 CREATE_NO_WINDOW**
2.**使用双重保险机制trait + process-wrap**
3.**代码质量高,模式统一**
### 📋 待验证事项
1. **实际测试**: 在 Windows 环境验证无 CMD 窗口弹出
2. **mcp-proxy 升级**: 升级到 v0.1.39 解决健康检查超时问题
3. **集成测试**: 完整的服务启动/停止/重启流程
---
## 推荐行动
### 短期(立即)
1.**无需修改 qiming-agent 代码**(已正确实现)
2. 🔄 **升级 mcp-proxy 到 v0.1.39**
3. 🧪 **Windows 环境测试验证**
### 中期(本周)
1. 📝 **添加 Windows 测试文档**
2. 🔍 **调查 mcp-proxy 健康检查超时根因**
3. 📊 **收集测试数据和用户反馈**
### 长期(下一版本)
1. 🧪 **自动化 Windows 集成测试**
2. 📖 **完善 Windows 平台文档**
3. 🛡️ **添加更多诊断和健康检查**
---
## 签署
**检查人员**: Claude (Sonnet 4.5)
**检查日期**: 2026-02-12
**检查方法**: 代码审查 + 全局搜索
**结论**: ✅ **qiming-agent 已正确实现 Windows CREATE_NO_WINDOW无需修改代码**
**特别说明**: qiming-agent 的实现质量甚至优于 mcp-proxy使用了更统一和安全的模式trait + 双重保护)。