Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions src/cortex-cli/src/agent_cmd/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@
#[cfg(test)]
mod tests {
use crate::agent_cmd::cli::{CopyArgs, ExportArgs};
use crate::agent_cmd::loader::{
load_builtin_agents, parse_frontmatter, read_file_with_encoding,
};
use crate::agent_cmd::loader::{load_builtin_agents, parse_frontmatter};
use crate::agent_cmd::types::AgentMode;
use crate::utils::file::read_file_with_encoding;

#[test]
fn test_read_file_with_utf8() {
Expand Down
7 changes: 2 additions & 5 deletions src/cortex-cli/src/mcp_cmd/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use anyhow::{Result, bail};
use cortex_engine::create_default_client;

use super::config::{get_mcp_server, get_mcp_servers};
use super::ellipsize_for_display;
use super::types::{AuthCommand, AuthListArgs, AuthSubcommand, LogoutArgs};
use super::validation::validate_server_name;

Expand Down Expand Up @@ -104,11 +105,7 @@ async fn run_auth_list(args: AuthListArgs) -> Result<()> {
};

// Truncate URL if too long
let display_url = if url.len() > 38 {
format!("{}...", &url[..35])
} else {
url.to_string()
};
let display_url = ellipsize_for_display(url, 38);

println!("{name:<20} {display_status:<18} {display_url:<40}");
}
Expand Down
13 changes: 3 additions & 10 deletions src/cortex-cli/src/mcp_cmd/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use std::io::{self, BufRead, Write};

use super::auth::{get_auth_status_for_display, remove_auth_silent};
use super::config::{get_mcp_server, get_mcp_servers};
use super::ellipsize_for_display;
use super::types::{
AddArgs, AddMcpSseArgs, AddMcpStreamableHttpArgs, AddMcpTransportArgs, DisableArgs, EnableArgs,
GetArgs, ListArgs, RemoveArgs, RenameArgs,
Expand Down Expand Up @@ -80,11 +81,7 @@ pub(crate) async fn run_list(args: ListArgs) -> Result<()> {
.and_then(|v| v.as_str())
.unwrap_or("?");
// Truncate long commands with ellipsis indicator
let transport_str = if cmd.len() > 22 {
format!("stdio: {}...", &cmd[..19])
} else {
format!("stdio: {cmd}")
};
let transport_str = format!("stdio: {}", ellipsize_for_display(cmd, 22));
(transport_str, "N/A".to_string())
}
"http" => {
Expand All @@ -94,11 +91,7 @@ pub(crate) async fn run_list(args: ListArgs) -> Result<()> {
.await
.unwrap_or_else(|_| "Unknown".to_string());
// Truncate URL if too long with ellipsis indicator
let transport_str = if url.len() > 25 {
format!("http: {}...", &url[..22])
} else {
format!("http: {url}")
};
let transport_str = format!("http: {}", ellipsize_for_display(url, 25));
(transport_str, auth)
}
_ => (transport_type.to_string(), "N/A".to_string()),
Expand Down
55 changes: 55 additions & 0 deletions src/cortex-cli/src/mcp_cmd/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,21 @@ use anyhow::Result;
// Re-export public types
pub use types::{McpCli, McpSubcommand};

pub(super) fn ellipsize_for_display(text: &str, max_chars: usize) -> String {
let char_count = text.chars().count();
if char_count <= max_chars {
return text.to_string();
}

let ellipsis_chars = "...".chars().count();
if max_chars <= ellipsis_chars {
return ".".repeat(max_chars);
}

let prefix: String = text.chars().take(max_chars - ellipsis_chars).collect();
format!("{prefix}...")
}

impl McpCli {
/// Run the MCP command.
pub async fn run(self) -> Result<()> {
Expand All @@ -42,3 +57,43 @@ impl McpCli {
}
}
}

#[cfg(test)]
mod tests {
use super::ellipsize_for_display;

#[test]
fn test_ellipsize_for_display_preserves_short_text() {
assert_eq!(
ellipsize_for_display("https://example.com", 25),
"https://example.com"
);
}

#[test]
fn test_ellipsize_for_display_matches_ascii_byte_slice_output() {
let url = "https://example.com/some/very/long/path";
assert_eq!(ellipsize_for_display(url, 25), "https://example.com/so...");
assert_eq!(
ellipsize_for_display(url, 38),
"https://example.com/some/very/long/..."
);
}

#[test]
fn test_ellipsize_for_display_handles_utf8_boundaries() {
let url = "http://例え.jp/path/to/endpoint";
let display = ellipsize_for_display(url, 25);

assert!(display.ends_with("..."));
assert!(display.len() <= url.len());
assert!(display.is_char_boundary(display.len()));
}

#[test]
fn test_ellipsize_for_display_handles_small_limits() {
assert_eq!(ellipsize_for_display("hello", 3), "...");
assert_eq!(ellipsize_for_display("hello", 2), "..");
assert_eq!(ellipsize_for_display("hello", 0), "");
}
}