refactor(desktop): split kernel_commands/pipeline_commands into modules, add SaaS client libs and gateway modules
Split monolithic kernel_commands.rs (2185 lines) and pipeline_commands.rs (1391 lines) into focused sub-modules under kernel_commands/ and pipeline_commands/ directories. Add gateway module (commands, config, io, runtime), health_check, and 15 new TypeScript client libraries for SaaS relay, auth, admin, telemetry, and kernel sub-systems (a2a, agent, chat, hands, skills, triggers). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
245
desktop/src-tauri/src/gateway/commands.rs
Normal file
245
desktop/src-tauri/src/gateway/commands.rs
Normal file
@@ -0,0 +1,245 @@
|
||||
use serde::Serialize;
|
||||
use serde_json::{json, Value};
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
use tauri::AppHandle;
|
||||
|
||||
use super::config::{
|
||||
approve_local_device_pairing, ensure_local_gateway_ready_for_tauri, read_local_gateway_auth,
|
||||
LocalGatewayAuth, LocalGatewayPairingApprovalResult, LocalGatewayPrepareResult,
|
||||
};
|
||||
use super::io::{parse_json_output, read_gateway_status, run_zclaw, LocalGatewayStatus};
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct VersionResponse {
|
||||
version: String,
|
||||
commit: Option<String>,
|
||||
build_date: Option<String>,
|
||||
runtime_source: Option<String>,
|
||||
raw: Value,
|
||||
}
|
||||
|
||||
/// Process information structure
|
||||
#[derive(Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct ProcessInfo {
|
||||
pid: u32,
|
||||
name: String,
|
||||
status: String,
|
||||
cpu_percent: Option<f64>,
|
||||
memory_mb: Option<f64>,
|
||||
uptime_seconds: Option<u64>,
|
||||
}
|
||||
|
||||
/// Process list response
|
||||
#[derive(Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct ProcessListResponse {
|
||||
processes: Vec<ProcessInfo>,
|
||||
total_count: usize,
|
||||
runtime_source: Option<String>,
|
||||
}
|
||||
|
||||
/// Process logs response
|
||||
#[derive(Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct ProcessLogsResponse {
|
||||
pid: Option<u32>,
|
||||
logs: String,
|
||||
lines: usize,
|
||||
runtime_source: Option<String>,
|
||||
}
|
||||
|
||||
/// Get ZCLAW Kernel status
|
||||
#[tauri::command]
|
||||
pub fn zclaw_status(app: AppHandle) -> Result<LocalGatewayStatus, String> {
|
||||
read_gateway_status(&app)
|
||||
}
|
||||
|
||||
/// Start ZCLAW Kernel
|
||||
#[tauri::command]
|
||||
pub fn zclaw_start(app: AppHandle) -> Result<LocalGatewayStatus, String> {
|
||||
ensure_local_gateway_ready_for_tauri(&app)?;
|
||||
run_zclaw(&app, &["gateway", "start", "--json"])?;
|
||||
thread::sleep(Duration::from_millis(800));
|
||||
read_gateway_status(&app)
|
||||
}
|
||||
|
||||
/// Stop ZCLAW Kernel
|
||||
#[tauri::command]
|
||||
pub fn zclaw_stop(app: AppHandle) -> Result<LocalGatewayStatus, String> {
|
||||
run_zclaw(&app, &["gateway", "stop", "--json"])?;
|
||||
thread::sleep(Duration::from_millis(800));
|
||||
read_gateway_status(&app)
|
||||
}
|
||||
|
||||
/// Restart ZCLAW Kernel
|
||||
#[tauri::command]
|
||||
pub fn zclaw_restart(app: AppHandle) -> Result<LocalGatewayStatus, String> {
|
||||
ensure_local_gateway_ready_for_tauri(&app)?;
|
||||
run_zclaw(&app, &["gateway", "restart", "--json"])?;
|
||||
thread::sleep(Duration::from_millis(1200));
|
||||
read_gateway_status(&app)
|
||||
}
|
||||
|
||||
/// Get local auth token from ZCLAW config
|
||||
#[tauri::command]
|
||||
pub fn zclaw_local_auth() -> Result<LocalGatewayAuth, String> {
|
||||
read_local_gateway_auth()
|
||||
}
|
||||
|
||||
/// Prepare ZCLAW for Tauri (update allowed origins)
|
||||
#[tauri::command]
|
||||
pub fn zclaw_prepare_for_tauri(app: AppHandle) -> Result<LocalGatewayPrepareResult, String> {
|
||||
ensure_local_gateway_ready_for_tauri(&app)
|
||||
}
|
||||
|
||||
/// Approve device pairing request
|
||||
#[tauri::command]
|
||||
pub fn zclaw_approve_device_pairing(
|
||||
app: AppHandle,
|
||||
device_id: String,
|
||||
public_key_base64: String,
|
||||
url: Option<String>,
|
||||
) -> Result<LocalGatewayPairingApprovalResult, String> {
|
||||
approve_local_device_pairing(&app, &device_id, &public_key_base64, url.as_deref())
|
||||
}
|
||||
|
||||
/// Run ZCLAW doctor to diagnose issues
|
||||
#[tauri::command]
|
||||
pub fn zclaw_doctor(app: AppHandle) -> Result<String, String> {
|
||||
let result = run_zclaw(&app, &["doctor", "--json"])?;
|
||||
Ok(result.stdout)
|
||||
}
|
||||
|
||||
/// List ZCLAW processes
|
||||
#[tauri::command]
|
||||
pub fn zclaw_process_list(app: AppHandle) -> Result<ProcessListResponse, String> {
|
||||
let result = run_zclaw(&app, &["process", "list", "--json"])?;
|
||||
|
||||
let raw = parse_json_output(&result.stdout).unwrap_or_else(|_| json!({"processes": []}));
|
||||
|
||||
let processes: Vec<ProcessInfo> = raw
|
||||
.get("processes")
|
||||
.and_then(Value::as_array)
|
||||
.map(|arr| {
|
||||
arr.iter()
|
||||
.filter_map(|p| {
|
||||
Some(ProcessInfo {
|
||||
pid: p.get("pid").and_then(Value::as_u64)?.try_into().ok()?,
|
||||
name: p.get("name").and_then(Value::as_str)?.to_string(),
|
||||
status: p
|
||||
.get("status")
|
||||
.and_then(Value::as_str)
|
||||
.unwrap_or("unknown")
|
||||
.to_string(),
|
||||
cpu_percent: p.get("cpuPercent").and_then(Value::as_f64),
|
||||
memory_mb: p.get("memoryMb").and_then(Value::as_f64),
|
||||
uptime_seconds: p.get("uptimeSeconds").and_then(Value::as_u64),
|
||||
})
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
Ok(ProcessListResponse {
|
||||
total_count: processes.len(),
|
||||
processes,
|
||||
runtime_source: Some(result.runtime.source),
|
||||
})
|
||||
}
|
||||
|
||||
/// Get ZCLAW process logs
|
||||
#[tauri::command]
|
||||
pub fn zclaw_process_logs(
|
||||
app: AppHandle,
|
||||
pid: Option<u32>,
|
||||
lines: Option<usize>,
|
||||
) -> Result<ProcessLogsResponse, String> {
|
||||
let line_count = lines.unwrap_or(100);
|
||||
let lines_str = line_count.to_string();
|
||||
|
||||
// Build owned strings first to avoid lifetime issues
|
||||
let args: Vec<String> = if let Some(pid_value) = pid {
|
||||
vec![
|
||||
"process".to_string(),
|
||||
"logs".to_string(),
|
||||
"--pid".to_string(),
|
||||
pid_value.to_string(),
|
||||
"--lines".to_string(),
|
||||
lines_str,
|
||||
"--json".to_string(),
|
||||
]
|
||||
} else {
|
||||
vec![
|
||||
"process".to_string(),
|
||||
"logs".to_string(),
|
||||
"--lines".to_string(),
|
||||
lines_str,
|
||||
"--json".to_string(),
|
||||
]
|
||||
};
|
||||
|
||||
// Convert to &str for the command
|
||||
let args_refs: Vec<&str> = args.iter().map(|s| s.as_str()).collect();
|
||||
let result = run_zclaw(&app, &args_refs)?;
|
||||
|
||||
// Parse the logs - could be JSON array or plain text
|
||||
let logs = if let Ok(json) = parse_json_output(&result.stdout) {
|
||||
// If JSON format, extract logs array or convert to string
|
||||
if let Some(log_lines) = json.get("logs").and_then(Value::as_array) {
|
||||
log_lines
|
||||
.iter()
|
||||
.filter_map(|l| l.as_str())
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n")
|
||||
} else if let Some(log_text) = json.get("log").and_then(Value::as_str) {
|
||||
log_text.to_string()
|
||||
} else {
|
||||
result.stdout.clone()
|
||||
}
|
||||
} else {
|
||||
result.stdout.clone()
|
||||
};
|
||||
|
||||
let log_lines_count = logs.lines().count();
|
||||
|
||||
Ok(ProcessLogsResponse {
|
||||
pid,
|
||||
logs,
|
||||
lines: log_lines_count,
|
||||
runtime_source: Some(result.runtime.source),
|
||||
})
|
||||
}
|
||||
|
||||
/// Get ZCLAW version information
|
||||
#[tauri::command]
|
||||
pub fn zclaw_version(app: AppHandle) -> Result<VersionResponse, String> {
|
||||
let result = run_zclaw(&app, &["--version", "--json"])?;
|
||||
|
||||
let raw = parse_json_output(&result.stdout).unwrap_or_else(|_| {
|
||||
// Fallback: try to parse plain text version output
|
||||
json!({
|
||||
"version": result.stdout.trim(),
|
||||
"raw": result.stdout.trim()
|
||||
})
|
||||
});
|
||||
|
||||
let version = raw
|
||||
.get("version")
|
||||
.and_then(Value::as_str)
|
||||
.unwrap_or("unknown")
|
||||
.to_string();
|
||||
|
||||
let commit = raw.get("commit").and_then(Value::as_str).map(ToOwned::to_owned);
|
||||
let build_date = raw.get("buildDate").and_then(Value::as_str).map(ToOwned::to_owned);
|
||||
|
||||
Ok(VersionResponse {
|
||||
version,
|
||||
commit,
|
||||
build_date,
|
||||
runtime_source: Some(result.runtime.source),
|
||||
raw,
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user