Skip to content

Commit 635ea84

Browse files
committed
remove duplicated tools
1 parent d35e680 commit 635ea84

File tree

8 files changed

+306
-570
lines changed

8 files changed

+306
-570
lines changed

src/bin/ash-mcp.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
//!
33
//! Provides tools over MCP protocol (JSON-RPC over stdio or HTTP)
44
5+
use ash::style;
56
use ash::tools;
67
use clap::Parser;
78
use serde::{Deserialize, Serialize};
@@ -109,7 +110,16 @@ async fn run_http(port: u16) -> anyhow::Result<()> {
109110
let actual_port = listener.local_addr()?.port();
110111
// Discovery protocol: gateway reads this line to find the assigned port
111112
eprintln!("LISTENING:{}", actual_port);
112-
eprintln!("MCP HTTP server listening on 0.0.0.0:{}", actual_port);
113+
let ver = env!("CARGO_PKG_VERSION");
114+
eprintln!("{}", style::mcp_banner(ver, "http"));
115+
let tool_count = tools::all_tools().len();
116+
eprintln!(" {} {} tools loaded",
117+
style::ecolor(style::check(), style::GREEN),
118+
tool_count);
119+
eprintln!(" {} listening on {}",
120+
style::ecolor(style::check(), style::GREEN),
121+
style::ecolor(&format!("0.0.0.0:{}", actual_port), style::CYAN));
122+
eprintln!();
113123

114124
loop {
115125
let (stream, peer) = listener.accept().await?;

src/bin/ash.rs

Lines changed: 66 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
use ash::{Tool, ToolResult};
44
use ash::daemon;
5+
use ash::style;
56
use ash::tools;
67
use clap::{Parser, Subcommand};
78
use serde_json::Value;
@@ -49,16 +50,7 @@ enum OutputFormat { Text, Json }
4950
#[derive(Subcommand)]
5051
enum Commands {
5152
// ==================== File Operations ====================
52-
53-
/// Read file with line numbers
54-
View {
55-
file_path: String,
56-
#[arg(short = 'n', long, default_value = "1")]
57-
offset: usize,
58-
#[arg(short, long, default_value = "100")]
59-
limit: usize,
60-
},
61-
53+
6254
/// Search for pattern in files (ripgrep)
6355
Grep {
6456
pattern: String,
@@ -144,10 +136,9 @@ enum Commands {
144136

145137
// ==================== Filesystem ====================
146138

147-
/// Filesystem operations
148-
Fs {
149-
#[command(subcommand)]
150-
op: FsOp,
139+
/// List directory contents
140+
Ls {
141+
path: String,
151142
},
152143

153144
// ==================== Buffer ====================
@@ -409,42 +400,6 @@ enum SessionOp {
409400
},
410401
}
411402

412-
#[derive(Subcommand)]
413-
enum FsOp {
414-
/// List directory contents
415-
Ls { path: String },
416-
/// Get file/directory metadata
417-
Stat { path: String },
418-
/// Write content to file
419-
Write {
420-
path: String,
421-
content: String,
422-
},
423-
/// Create directory
424-
Mkdir {
425-
path: String,
426-
#[arg(long, default_value = "true")]
427-
recursive: bool,
428-
},
429-
/// Remove file or directory
430-
Rm {
431-
path: String,
432-
#[arg(short, long)]
433-
recursive: bool,
434-
},
435-
/// Move/rename file or directory
436-
Mv {
437-
from: String,
438-
to: String,
439-
},
440-
/// Copy file or directory
441-
Cp {
442-
from: String,
443-
to: String,
444-
#[arg(short, long)]
445-
recursive: bool,
446-
},
447-
}
448403

449404
#[derive(Subcommand)]
450405
enum BufferOp {
@@ -601,12 +556,6 @@ async fn main() -> anyhow::Result<()> {
601556
let result = match cli.command {
602557
// ==================== File Operations ====================
603558

604-
Commands::View { file_path, offset, limit } => {
605-
exec_tool(&tools::ViewTool, serde_json::json!({
606-
"file_path": file_path, "offset": offset, "limit": limit
607-
}), &session_id).await
608-
}
609-
610559
Commands::Grep { pattern, path, include, limit } => {
611560
exec_tool(&tools::GrepTool, serde_json::json!({
612561
"pattern": pattern, "path": path, "include": include, "limit": limit
@@ -675,30 +624,8 @@ async fn main() -> anyhow::Result<()> {
675624

676625
// ==================== Filesystem ====================
677626

678-
Commands::Fs { op } => {
679-
match op {
680-
FsOp::Ls { path } => {
681-
exec_tool(&tools::FsListDirTool, serde_json::json!({"path": path}), &session_id).await
682-
}
683-
FsOp::Stat { path } => {
684-
exec_tool(&tools::FsStatTool, serde_json::json!({"path": path}), &session_id).await
685-
}
686-
FsOp::Write { path, content } => {
687-
exec_tool(&tools::FsWriteTool, serde_json::json!({"path": path, "content": content}), &session_id).await
688-
}
689-
FsOp::Mkdir { path, recursive } => {
690-
exec_tool(&tools::FsMkdirTool, serde_json::json!({"path": path, "recursive": recursive}), &session_id).await
691-
}
692-
FsOp::Rm { path, recursive } => {
693-
exec_tool(&tools::FsRemoveTool, serde_json::json!({"path": path, "recursive": recursive}), &session_id).await
694-
}
695-
FsOp::Mv { from, to } => {
696-
exec_tool(&tools::FsMoveTool, serde_json::json!({"from": from, "to": to}), &session_id).await
697-
}
698-
FsOp::Cp { from, to, recursive } => {
699-
exec_tool(&tools::FsCopyTool, serde_json::json!({"from": from, "to": to, "recursive": recursive}), &session_id).await
700-
}
701-
}
627+
Commands::Ls { path } => {
628+
exec_tool(&tools::FsListDirTool, serde_json::json!({"path": path}), &session_id).await
702629
}
703630

704631
// ==================== Buffer ====================
@@ -973,7 +900,8 @@ async fn main() -> anyhow::Result<()> {
973900
match op {
974901
GatewayOp::Start { foreground } => {
975902
if daemon::is_gateway_running() {
976-
println!("Gateway is already running");
903+
println!("{} Gateway is already running",
904+
style::color(style::check(), style::GREEN));
977905
return Ok(());
978906
}
979907

@@ -988,7 +916,9 @@ async fn main() -> anyhow::Result<()> {
988916
.stdout(std::process::Stdio::null())
989917
.stderr(std::process::Stdio::null())
990918
.spawn()?;
991-
println!("Gateway started (pid {})", child.id());
919+
println!("{} Gateway started {}",
920+
style::color(style::check(), style::GREEN),
921+
style::dim(&format!("(pid {})", child.id())));
992922
}
993923
}
994924
GatewayOp::Stop => {
@@ -1004,13 +934,16 @@ async fn main() -> anyhow::Result<()> {
1004934
tokio::time::sleep(std::time::Duration::from_millis(300)).await;
1005935
let _ = std::fs::remove_file(daemon::pid_path());
1006936
let _ = std::fs::remove_file(daemon::socket_path());
1007-
println!("Gateway stopped (pid {})", pid);
937+
println!("{} Gateway stopped {}",
938+
style::color(style::cross(), style::GRAY),
939+
style::dim(&format!("(pid {})", pid)));
1008940
} else {
1009941
eprintln!("Invalid PID file");
1010942
}
1011943
}
1012944
Err(_) => {
1013-
eprintln!("Gateway is not running");
945+
eprintln!("{} Gateway is not running",
946+
style::ecolor(style::cross(), style::GRAY));
1014947
}
1015948
}
1016949
}
@@ -1021,10 +954,15 @@ async fn main() -> anyhow::Result<()> {
1021954
.and_then(|r| r.get("uptime_secs"))
1022955
.and_then(|u| u.as_u64())
1023956
.unwrap_or(0);
1024-
println!("Gateway running (uptime: {}s)", uptime);
957+
println!("{} Gateway {} {}",
958+
style::color(style::check(), style::GREEN),
959+
style::color("running", style::GREEN),
960+
style::dim(&format!("(uptime: {})", style::format_uptime(uptime))));
1025961
}
1026962
None => {
1027-
println!("Gateway is not running");
963+
println!("{} Gateway {}",
964+
style::color(style::cross(), style::GRAY),
965+
style::dim("not running"));
1028966
}
1029967
}
1030968
}
@@ -1034,80 +972,96 @@ async fn main() -> anyhow::Result<()> {
1034972

1035973
Commands::Info => {
1036974
let mut out = String::new();
975+
let ver = env!("CARGO_PKG_VERSION");
1037976

1038-
// Version
1039-
out.push_str(&format!("ash {}\n\n", env!("CARGO_PKG_VERSION")));
977+
// Banner
978+
out.push_str(&format!("\n{}\n", style::banner_line(ver)));
1040979

1041980
// Try gateway for info
1042981
if let Some(resp) = daemon::gateway_call("gateway/info", serde_json::json!({})).await {
1043982
if let Some(info) = resp.get("result") {
1044983
let uptime = info.get("uptime_secs").and_then(|u| u.as_u64()).unwrap_or(0);
1045-
out.push_str(&format!("Gateway: running (uptime: {}s)\n", uptime));
984+
out.push_str(&format!("\n{}\n", style::section("Gateway")));
985+
out.push_str(&format!(" {} {} {}\n",
986+
style::color(style::check(), style::GREEN),
987+
style::color("running", style::GREEN),
988+
style::dim(&format!("uptime {}", style::format_uptime(uptime)))));
1046989

1047990
let local_mcp_port = info.get("local_mcp_port").and_then(|p| p.as_u64());
1048991
if let Some(port) = local_mcp_port {
1049-
out.push_str(&format!("Local ash-mcp: port {}\n", port));
992+
out.push_str(&format!(" {} ash-mcp on port {}\n",
993+
style::color(style::check(), style::GREEN),
994+
style::color(&port.to_string(), style::CYAN)));
1050995
}
1051-
out.push('\n');
1052996

1053997
let docker_ok = info.pointer("/backends/docker").and_then(|v| v.as_bool()).unwrap_or(false);
1054998
let k8s_ok = info.pointer("/backends/k8s").and_then(|v| v.as_bool()).unwrap_or(false);
1055999
let default_backend = info.get("default_backend").and_then(|v| v.as_str()).unwrap_or("local");
10561000

1057-
out.push_str("Backends:\n");
1058-
let docker_mark = if docker_ok { "ok" } else { "--" };
1059-
let k8s_mark = if k8s_ok { "ok" } else { "--" };
1001+
out.push_str(&format!("\n{}\n", style::section("Backends")));
10601002
let docker_default = if default_backend == "docker" { " (default)" } else { "" };
10611003
let k8s_default = if default_backend == "k8s" { " (default)" } else { "" };
1062-
out.push_str(&format!(" docker {}{}\n", docker_mark, docker_default));
1063-
out.push_str(&format!(" k8s {}{}\n", k8s_mark, k8s_default));
1004+
out.push_str(&format!("{}\n", style::status_line(
1005+
&format!("docker{}", docker_default), if docker_ok { "available" } else { "unavailable" }, docker_ok)));
1006+
out.push_str(&format!("{}\n", style::status_line(
1007+
&format!("k8s{}", k8s_default), if k8s_ok { "available" } else { "unavailable" }, k8s_ok)));
10641008

10651009
let sessions = info.get("sessions").and_then(|s| s.as_u64()).unwrap_or(0);
10661010
let routes = info.get("routes").and_then(|r| r.as_u64()).unwrap_or(0);
1067-
out.push_str(&format!("\nSessions: {} ({} routes)\n", sessions, routes));
1068-
10691011
let tool_count = tools::all_tools().len();
1070-
out.push_str(&format!("Tools: {}\n", tool_count));
10711012

1013+
out.push_str(&format!("\n{}\n", style::section("Stats")));
1014+
out.push_str(&format!("{}\n", style::kv("sessions", &format!("{} {}", sessions, style::dim(&format!("({} routes)", routes))))));
1015+
out.push_str(&format!("{}\n", style::kv("tools ", &tool_count.to_string())));
1016+
1017+
out.push('\n');
10721018
print!("{}", out);
10731019
return Ok(());
10741020
}
10751021
}
10761022

10771023
// Fallback: no gateway running
1078-
out.push_str("Gateway: not running\n\n");
1024+
out.push_str(&format!("\n{}\n", style::section("Gateway")));
1025+
out.push_str(&format!(" {} {}\n",
1026+
style::color(style::cross(), style::GRAY),
1027+
style::dim("not running")));
10791028

10801029
use ash::backend::BackendType;
10811030

1082-
out.push_str("Backends:\n");
1031+
out.push_str(&format!("\n{}\n", style::section("Backends")));
10831032
let manager = tools::session::BACKEND_MANAGER.read().await;
10841033
let default_backend = manager.default_backend();
10851034
let local_ok = manager.health_check(BackendType::Local).await.is_ok();
10861035
let docker_ok = manager.health_check(BackendType::Docker).await.is_ok();
10871036
let k8s_ok = manager.health_check(BackendType::K8s).await.is_ok();
10881037
drop(manager);
10891038

1090-
let local_mark = if local_ok { "ok" } else { "--" };
1091-
let docker_mark = if docker_ok { "ok" } else { "--" };
1092-
let k8s_mark = if k8s_ok { "ok" } else { "--" };
10931039
let local_default = if default_backend == BackendType::Local { " (default)" } else { "" };
10941040
let docker_default = if default_backend == BackendType::Docker { " (default)" } else { "" };
10951041
let k8s_default = if default_backend == BackendType::K8s { " (default)" } else { "" };
1096-
out.push_str(&format!(" local {}{}\n", local_mark, local_default));
1097-
out.push_str(&format!(" docker {}{}\n", docker_mark, docker_default));
1098-
out.push_str(&format!(" k8s {}{}\n", k8s_mark, k8s_default));
1042+
out.push_str(&format!("{}\n", style::status_line(
1043+
&format!("local{}", local_default), if local_ok { "available" } else { "unavailable" }, local_ok)));
1044+
out.push_str(&format!("{}\n", style::status_line(
1045+
&format!("docker{}", docker_default), if docker_ok { "available" } else { "unavailable" }, docker_ok)));
1046+
out.push_str(&format!("{}\n", style::status_line(
1047+
&format!("k8s{}", k8s_default), if k8s_ok { "available" } else { "unavailable" }, k8s_ok)));
10991048

11001049
let tool_count = tools::all_tools().len();
1101-
out.push_str(&format!("\nTools: {}\n", tool_count));
1050+
out.push_str(&format!("\n{}\n", style::section("Stats")));
1051+
out.push_str(&format!("{}\n", style::kv("tools", &tool_count.to_string())));
11021052

1053+
out.push('\n');
11031054
print!("{}", out);
11041055
return Ok(());
11051056
}
11061057

11071058
Commands::Tools => {
1108-
for tool in tools::all_tools() {
1109-
println!("{}: {}", tool.name(), tool.description());
1059+
let all = tools::all_tools();
1060+
println!("\n{}", style::section(&format!("Tools ({})", all.len())));
1061+
for tool in all {
1062+
println!("{}", style::tool_entry(tool.name(), tool.description()));
11101063
}
1064+
println!();
11111065
return Ok(());
11121066
}
11131067
};
@@ -1119,7 +1073,8 @@ async fn main() -> anyhow::Result<()> {
11191073
print!("{}", result.output);
11201074
if !result.output.ends_with('\n') { println!(); }
11211075
} else {
1122-
eprintln!("Error: {}", result.error.unwrap_or_default());
1076+
let msg = result.error.unwrap_or_default();
1077+
eprintln!("{} {}", style::ecolor("error:", style::BRIGHT_RED), msg);
11231078
std::process::exit(1);
11241079
}
11251080
}

0 commit comments

Comments
 (0)