Claw 项目完整结构提交

This commit is contained in:
zqm
2026-03-16 15:47:55 +08:00
parent ca4970bcbf
commit fb0aeb6ca2
118 changed files with 28648 additions and 281 deletions

View File

@@ -0,0 +1,19 @@
[package]
name = "smartclaw"
version = "0.1.0"
edition = "2024"
[dependencies]
actix-web = "^4.0"
tokio = { version = "^1.0", features = ["full"] }
serde = { version = "^1.0", features = ["derive"] }
serde_json = "^1.0"
reqwest = { version = "^0.11", features = ["json"] }
# mini-redis = "0.4" # 使用自定义嵌入式Redis实现
tokio-tungstenite = "^0.18"
shared = { path = "../shared" }
env_logger = "^0.10"
awc = { version = "^3.0", features = ["rustls"] }
futures-util = "^0.3"
chrono = "^0.4"
# heed = "^0.20" # 暂时移除后续实现HeedDB功能

View File

@@ -0,0 +1,501 @@
use actix_web::{web, App, HttpRequest, HttpResponse, HttpServer, Responder, middleware::Logger};
use std::env;
use shared::{TaskRequest, TaskResponse, HealthResponse, utils};
mod websocket_client;
use websocket_client::WebSocketClientManager;
/// 智能控制核心服务
struct SmartClawService;
impl SmartClawService {
/// 处理来自网关服务的任务
async fn process_task(task: TaskRequest) -> TaskResponse {
println!("🤖 SmartClaw 收到任务:");
println!(" 用户ID: {}", task.user_id);
println!(" 任务类型: {}", task.task_type);
println!(" 内容长度: {} 字符", task.content.len());
println!(" 优先级: {}", task.priority);
// 记录任务开始时间
let start_time = std::time::Instant::now();
// 根据任务类型进行不同的处理
let result = match task.task_type {
shared::TaskType::TextProcessing => {
Self::process_text_task(&task.content).await
},
shared::TaskType::DataAnalysis => {
Self::process_data_analysis_task(&task.content).await
},
shared::TaskType::AIChat => {
Self::process_ai_chat_task(&task.content).await
},
shared::TaskType::FileProcessing => {
Self::process_file_task(&task.content).await
},
shared::TaskType::Custom(ref custom_type) => {
Self::process_custom_task(&task.content, custom_type).await
},
};
let processing_time = start_time.elapsed().as_millis() as u64;
match result {
Ok(response_data) => {
println!("✅ 任务处理成功,耗时: {}ms", processing_time);
let mut response = utils::create_success_response(
"任务处理成功",
Some(utils::generate_task_id(&task.user_id)),
Some(response_data)
);
response.processing_time = Some(processing_time);
response
},
Err(error_message) => {
println!("❌ 任务处理失败: {}", error_message);
let mut response = utils::create_error_response(
"任务处理失败",
Some(error_message)
);
response.processing_time = Some(processing_time);
response
}
}
}
/// 处理文本处理任务
async fn process_text_task(content: &str) -> Result<serde_json::Value, String> {
println!("📝 处理文本任务");
// TODO: 集成 LMStudio 进行文本处理
// 模拟处理过程
tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
let word_count = content.split_whitespace().count();
let char_count = content.chars().count();
Ok(serde_json::json!({
"task_type": "text_processing",
"word_count": word_count,
"char_count": char_count,
"processed_content": format!("[已处理] {}", content),
"lmstudio_result": "TODO: 集成 LMStudio 处理结果"
}))
}
/// 处理数据分析任务
async fn process_data_analysis_task(content: &str) -> Result<serde_json::Value, String> {
println!("📊 处理数据分析任务");
// TODO: 集成 LMStudio 进行数据分析
// 模拟数据处理
tokio::time::sleep(tokio::time::Duration::from_millis(200)).await;
// 简单的数据分析示例
let lines: Vec<&str> = content.lines().collect();
let line_count = lines.len();
Ok(serde_json::json!({
"task_type": "data_analysis",
"line_count": line_count,
"data_summary": {
"total_lines": line_count,
"sample_data": lines.iter().take(5).collect::<Vec<_>>()
},
"lmstudio_analysis": "TODO: 集成 LMStudio 分析结果"
}))
}
/// 处理 AI 对话任务
async fn process_ai_chat_task(content: &str) -> Result<serde_json::Value, String> {
println!("💬 处理 AI 对话任务");
// TODO: 集成 LMStudio 进行 AI 对话
// 模拟 AI 处理
tokio::time::sleep(tokio::time::Duration::from_millis(500)).await;
let response = format!("这是一个模拟的 AI 回复,您的消息是: {}", content);
Ok(serde_json::json!({
"task_type": "ai_chat",
"user_message": content,
"ai_response": response,
"lmstudio_response": "TODO: 集成 LMStudio 对话结果"
}))
}
/// 处理文件处理任务
async fn process_file_task(content: &str) -> Result<serde_json::Value, String> {
println!("📁 处理文件任务");
// TODO: 集成 LMStudio 进行文件内容处理
// 模拟文件处理
tokio::time::sleep(tokio::time::Duration::from_millis(300)).await;
Ok(serde_json::json!({
"task_type": "file_processing",
"file_info": {
"content_preview": content.chars().take(100).collect::<String>() + "...",
"content_length": content.len()
},
"processing_result": "文件内容已接收并处理",
"lmstudio_processing": "TODO: 集成 LMStudio 文件处理结果"
}))
}
/// 处理自定义任务
async fn process_custom_task(content: &str, custom_type: &str) -> Result<serde_json::Value, String> {
println!("🔧 处理自定义任务: {}", custom_type);
// 根据自定义类型进行不同的处理
match custom_type {
"translation" => {
Self::process_translation_task(content).await
},
"summarization" => {
Self::process_summarization_task(content).await
},
_ => {
// 默认处理
Ok(serde_json::json!({
"task_type": format!("custom_{}", custom_type),
"content": content,
"result": format!("自定义任务 '{}' 已处理", custom_type),
"note": "这是默认的自定义任务处理结果"
}))
}
}
}
/// 处理翻译任务
async fn process_translation_task(content: &str) -> Result<serde_json::Value, String> {
println!("🌐 处理翻译任务");
// TODO: 集成 LMStudio 进行翻译
let translated = format!("[翻译结果] {}", content);
Ok(serde_json::json!({
"task_type": "custom_translation",
"original_text": content,
"translated_text": translated,
"source_language": "auto",
"target_language": "zh-CN",
"lmstudio_translation": "TODO: 集成 LMStudio 翻译结果"
}))
}
/// 处理摘要任务
async fn process_summarization_task(content: &str) -> Result<serde_json::Value, String> {
println!("📋 处理摘要任务");
// TODO: 集成 LMStudio 进行文本摘要
let summary = format!("这是文本的摘要: {}", content.chars().take(50).collect::<String>());
Ok(serde_json::json!({
"task_type": "custom_summarization",
"original_text": content,
"summary": summary,
"summary_length": summary.len(),
"lmstudio_summary": "TODO: 集成 LMStudio 摘要结果"
}))
}
/// 获取服务状态
fn get_service_status() -> serde_json::Value {
serde_json::json!({
"service": "smartclaw",
"status": "running",
"version": env!("CARGO_PKG_VERSION"),
"capabilities": [
"text_processing",
"data_analysis",
"ai_chat",
"file_processing",
"custom_tasks"
],
"lmstudio_status": "TODO: 检查 LMStudio 连接状态",
"active_tasks": 0, // TODO: 统计当前活跃任务数
"queue_length": 0 // TODO: 统计队列长度
})
}
}
/// 健康检查处理器
async fn health_check() -> impl Responder {
let response = HealthResponse {
status: "healthy".to_string(),
service: "smartclaw".to_string(),
timestamp: utils::current_timestamp(),
version: env!("CARGO_PKG_VERSION").to_string(),
extra: Some(SmartClawService::get_service_status()),
};
HttpResponse::Ok().json(response)
}
/// 任务处理处理器
async fn handle_task(task: web::Json<TaskRequest>) -> impl Responder {
let response = SmartClawService::process_task(task.into_inner()).await;
HttpResponse::Ok().json(response)
}
/// 系统状态处理器
async fn system_status() -> impl Responder {
HttpResponse::Ok().json(SmartClawService::get_service_status())
}
/// LMStudio 状态检查
async fn lmstudio_status() -> impl Responder {
// TODO: 实现 LMStudio 连接状态检查
HttpResponse::Ok().json(serde_json::json!({
"lmstudio": {
"connected": false,
"status": "not_implemented",
"message": "LMStudio 集成尚未实现"
},
"timestamp": utils::current_timestamp()
}))
}
/// WebSocket 断开连接处理器(用于测试)
async fn websocket_disconnect(ws_manager: web::Data<WebSocketClientManager>) -> impl Responder {
println!("🔌 收到WebSocket断开连接请求");
// 获取客户端实例
let client = ws_manager.get_client();
if client.is_connected() {
println!("🔗 WebSocket客户端当前已连接准备断开...");
// 断开连接
client.disconnect();
println!("✅ WebSocket客户端已断开连接");
HttpResponse::Ok().json(serde_json::json!({
"status": "disconnected",
"message": "WebSocket客户端已断开连接",
"timestamp": utils::current_timestamp()
}))
} else {
println!("⚠️ WebSocket客户端当前未连接");
HttpResponse::Ok().json(serde_json::json!({
"status": "not_connected",
"message": "WebSocket客户端当前未连接",
"timestamp": utils::current_timestamp()
}))
}
}
/// WebSocket 停止管理器处理器(用于测试)
async fn websocket_stop(ws_manager: web::Data<WebSocketClientManager>) -> impl Responder {
println!("🛑 收到WebSocket停止管理器请求");
// 停止管理器
ws_manager.stop();
println!("✅ WebSocket客户端管理器已停止");
HttpResponse::Ok().json(serde_json::json!({
"status": "stopped",
"message": "WebSocket客户端管理器已停止",
"timestamp": utils::current_timestamp()
}))
}
/// WebSocket 连接处理器(用于与网关服务通信)
async fn websocket_handler(req: HttpRequest, _stream: web::Payload) -> impl Responder {
// TODO: 实现 WebSocket 通信
// 这将用于接收来自网关服务的实时任务
println!("📡 WebSocket 连接请求: {:?}", req);
// 获取WebSocket客户端实例用于测试和演示
let gateway_url = env::var("GATEWAY_URL").unwrap_or_else(|_| "http://localhost:8000".to_string());
let ws_manager = WebSocketClientManager::new(gateway_url);
// 获取客户端实例(用于测试)
let client = ws_manager.get_client();
// 检查连接状态(用于演示)
if client.is_connected() {
println!("🔗 WebSocket客户端已连接");
// 测试发送消息(用于演示)
let test_message = serde_json::json!({
"type": "test",
"message": "来自SmartClaw的测试消息",
"timestamp": utils::current_timestamp()
}).to_string();
match client.send_message(test_message).await {
Ok(_) => {
println!("✅ 测试消息发送成功");
},
Err(e) => {
println!("⚠️ 测试消息发送失败: {}", e);
}
}
// 测试发送任务响应(用于演示)
let test_response = shared::TaskResponse {
success: true,
message: "测试响应".to_string(),
task_id: Some("test_task_123".to_string()),
result: Some(serde_json::json!({
"test_data": "这是测试数据",
"websocket_status": "connected"
})),
processing_time: Some(100),
error: None,
};
match client.send_task_response(test_response).await {
Ok(_) => {
println!("✅ 测试任务响应发送成功");
},
Err(e) => {
println!("⚠️ 测试任务响应发送失败: {}", e);
}
}
} else {
println!("⚠️ WebSocket客户端未连接");
}
// 暂时返回不支持的消息
HttpResponse::NotImplemented().json(serde_json::json!({
"error": "WebSocket not implemented",
"message": "WebSocket 功能正在开发中",
"websocket_status": if client.is_connected() { "connected" } else { "disconnected" }
}))
}
/// 任务队列状态
async fn queue_status() -> impl Responder {
// TODO: 实现任务队列状态查询
HttpResponse::Ok().json(serde_json::json!({
"queue": {
"length": 0,
"pending": 0,
"processing": 0,
"completed": 0,
"failed": 0
},
"timestamp": utils::current_timestamp()
}))
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
// 初始化日志
env_logger::init_from_env(
env_logger::Env::new().default_filter_or("info,actix_web=info")
);
let port = env::var("PORT").unwrap_or_else(|_| "3001".to_string());
let bind_address = format!("0.0.0.0:{}", port);
// 获取网关服务地址
let gateway_url = env::var("GATEWAY_URL").unwrap_or_else(|_| "http://localhost:8000".to_string());
println!("🚀 SmartClaw 服务启动中...");
println!("📍 绑定地址: {}", bind_address);
println!("🔗 网关服务: {}", gateway_url);
println!("📝 日志级别: info");
println!("🔧 版本: {}", env!("CARGO_PKG_VERSION"));
println!("🎯 环境: {}", env::var("ENVIRONMENT").unwrap_or_else(|_| "development".to_string()));
// 创建 WebSocket 客户端管理器
let ws_manager = WebSocketClientManager::new(gateway_url.clone());
// 启动 WebSocket 连接(在后台任务中)
let ws_manager_for_spawn = ws_manager.clone();
std::thread::spawn(move || {
let rt = tokio::runtime::Runtime::new().unwrap();
rt.block_on(async {
println!("🔄 正在启动 WebSocket 客户端连接...");
match ws_manager_for_spawn.start().await {
Ok(_) => {
println!("✅ WebSocket 客户端连接成功");
}
Err(e) => {
println!("❌ WebSocket 客户端连接失败: {}", e);
// 这里可以添加重试逻辑
}
}
});
});
let ws_manager_for_server = ws_manager.clone();
let server = HttpServer::new(move || {
App::new()
.app_data(web::Data::new(ws_manager_for_server.clone()))
.wrap(Logger::default())
.service(
web::scope("/api/v1")
// 健康检查
.route("/health", web::get().to(health_check))
// 系统状态
.route("/system", web::get().to(system_status))
// 任务处理
.route("/task", web::post().to(handle_task))
// LMStudio 状态
.route("/lmstudio/status", web::get().to(lmstudio_status))
// 队列状态
.route("/queue/status", web::get().to(queue_status))
// WebSocket 连接(用于与网关服务通信)
.route("/websocket", web::get().to(websocket_handler))
// WebSocket 断开连接(用于测试)
.route("/websocket/disconnect", web::post().to(websocket_disconnect))
// WebSocket 停止管理器(用于测试)
.route("/websocket/stop", web::post().to(websocket_stop))
)
})
.bind(&bind_address)?
.run();
println!("✅ SmartClaw 服务已启动在 {}", bind_address);
println!("🔍 可用接口:");
println!(" GET /api/v1/health - 健康检查");
println!(" GET /api/v1/system - 系统状态");
println!(" POST /api/v1/task - 处理任务");
println!(" GET /api/v1/lmstudio/status - LMStudio 状态");
println!(" GET /api/v1/queue/status - 队列状态");
println!(" GET /api/v1/websocket - WebSocket 连接");
println!(" POST /api/v1/websocket/disconnect - WebSocket 断开连接(测试)");
println!(" POST /api/v1/websocket/stop - WebSocket 停止管理器(测试)");
println!("💡 WebSocket 客户端已配置,连接到: {}", gateway_url);
// 启动优雅关闭处理
let ws_manager_clone = ws_manager.clone();
tokio::spawn(async move {
// 监听关闭信号(这里简化处理,实际应该监听系统信号)
match tokio::signal::ctrl_c().await {
Ok(_) => {
println!("🛑 收到关闭信号,开始优雅关闭...");
graceful_shutdown(ws_manager_clone).await;
std::process::exit(0);
},
Err(e) => {
println!("⚠️ 监听关闭信号失败: {}", e);
}
}
});
server.await
}
/// 优雅关闭处理
async fn graceful_shutdown(ws_manager: WebSocketClientManager) {
println!("🛑 开始优雅关闭...");
// 停止WebSocket客户端
ws_manager.stop();
println!("🔌 WebSocket客户端已停止");
// 等待一段时间确保所有连接都已关闭
tokio::time::sleep(tokio::time::Duration::from_secs(2)).await;
println!("✅ 优雅关闭完成");
}

View File

@@ -0,0 +1,214 @@
use tokio_tungstenite::{connect_async, tungstenite::Message};
use futures_util::{SinkExt, StreamExt};
use serde_json::json;
use std::sync::Arc;
use tokio::sync::mpsc;
use tokio::time::{interval, Duration};
use shared::{TaskRequest, TaskResponse};
/// WebSocket 客户端连接管理器
pub struct WebSocketClient {
gateway_url: String,
sender: Arc<std::sync::Mutex<Option<mpsc::Sender<String>>>>,
is_connected: Arc<std::sync::Mutex<bool>>,
}
impl WebSocketClient {
/// 创建新的 WebSocket 客户端
pub fn new(gateway_url: String) -> Self {
Self {
gateway_url,
sender: Arc::new(std::sync::Mutex::new(None)),
is_connected: Arc::new(std::sync::Mutex::new(false)),
}
}
/// 连接到网关服务
pub async fn connect(&self) -> Result<(), Box<dyn std::error::Error>> {
println!("🔌 正在连接到网关服务: {}", self.gateway_url);
let ws_url = format!("{}/ws", self.gateway_url.replace("http://", "ws://").replace("https://", "wss://"));
println!("🔗 WebSocket URL: {}", ws_url);
// 建立 WebSocket 连接
let (ws_stream, _) = connect_async(&ws_url).await?;
println!("✅ WebSocket 连接建立");
// 设置连接状态
*self.is_connected.lock().unwrap() = true;
// 分割流
let (mut write, mut read) = ws_stream.split();
// 创建消息通道
let (tx, mut rx) = mpsc::channel::<String>(100);
*self.sender.lock().unwrap() = Some(tx);
// 启动消息发送循环
let _write_handle = tokio::spawn(async move {
while let Some(msg) = rx.recv().await {
if let Err(e) = write.send(Message::Text(msg)).await {
println!("❌ 发送消息失败: {}", e);
break;
}
}
});
// 启动消息接收循环
let is_connected_clone = self.is_connected.clone();
let _read_handle = tokio::spawn(async move {
while let Some(msg) = read.next().await {
match msg {
Ok(Message::Text(text)) => {
println!("📨 收到消息: {}", text);
if let Ok(parsed) = serde_json::from_str::<serde_json::Value>(&text) {
Self::handle_incoming_message(parsed).await;
}
}
Ok(Message::Close(_)) => {
println!("🔚 收到关闭消息");
*is_connected_clone.lock().unwrap() = false;
break;
}
Ok(_) => {}
Err(e) => {
println!("❌ 接收消息错误: {}", e);
*is_connected_clone.lock().unwrap() = false;
break;
}
}
}
});
// 启动心跳机制
let _heartbeat_handle = {
let is_connected = self.is_connected.clone();
tokio::spawn(async move {
let mut heartbeat_interval = interval(Duration::from_secs(30));
loop {
heartbeat_interval.tick().await;
let connected = *is_connected.lock().unwrap();
if !connected {
println!("💔 心跳检测到连接已断开");
break;
}
let _heartbeat_msg = json!({
"type": "heartbeat",
"service": "smartclaw",
"timestamp": chrono::Utc::now().timestamp()
}).to_string();
// 这里需要重新获取 sender因为生命周期问题
println!("💓 心跳发送");
}
})
};
// 发送连接确认消息
let connect_msg = json!({
"type": "connect",
"service": "smartclaw",
"version": env!("CARGO_PKG_VERSION"),
"timestamp": chrono::Utc::now().timestamp()
}).to_string();
if let Some(sender) = &*self.sender.lock().unwrap() {
let _ = sender.send(connect_msg).await;
}
println!("🚀 WebSocket 客户端已启动");
Ok(())
}
/// 处理接收到的消息
async fn handle_incoming_message(message: serde_json::Value) {
match message.get("type").and_then(|t| t.as_str()) {
Some("task") => {
// 处理任务消息
if let Ok(task_request) = serde_json::from_value::<TaskRequest>(message) {
println!("📝 收到任务请求: {:?}", task_request);
// 这里可以调用任务处理逻辑
}
}
Some("heartbeat") => {
println!("💓 收到心跳响应");
}
Some("ack") => {
println!("✅ 收到确认消息");
}
Some(msg_type) => {
println!("❓ 收到未知消息类型: {}", msg_type);
}
None => {
println!("❓ 收到无类型消息");
}
}
}
/// 发送消息
pub async fn send_message(&self, message: String) -> Result<(), Box<dyn std::error::Error>> {
if let Some(sender) = &*self.sender.lock().unwrap() {
sender.send(message).await.map_err(|e| Box::new(e) as Box<dyn std::error::Error>)?;
Ok(())
} else {
Err("WebSocket 连接未建立".into())
}
}
/// 发送任务响应
pub async fn send_task_response(&self, response: TaskResponse) -> Result<(), Box<dyn std::error::Error>> {
let message = json!({
"type": "task_response",
"task_id": response.task_id,
"data": response,
"timestamp": chrono::Utc::now().timestamp()
}).to_string();
self.send_message(message).await
}
/// 检查连接状态
pub fn is_connected(&self) -> bool {
*self.is_connected.lock().unwrap()
}
/// 断开连接
pub fn disconnect(&self) {
*self.is_connected.lock().unwrap() = false;
*self.sender.lock().unwrap() = None;
println!("🔌 WebSocket 连接已断开");
}
}
/// WebSocket 客户端管理器
#[derive(Clone)]
pub struct WebSocketClientManager {
client: Arc<WebSocketClient>,
}
impl WebSocketClientManager {
/// 创建新的管理器
pub fn new(gateway_url: String) -> Self {
Self {
client: Arc::new(WebSocketClient::new(gateway_url)),
}
}
/// 启动客户端连接
pub async fn start(&self) -> Result<(), Box<dyn std::error::Error>> {
self.client.connect().await
}
/// 获取客户端实例
pub fn get_client(&self) -> Arc<WebSocketClient> {
self.client.clone()
}
/// 停止客户端
pub fn stop(&self) {
self.client.disconnect();
}
}