#![allow(dead_code)]
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct IdeAtMentioned {
pub file_path: String,
pub line_start: Option<u64>,
pub line_end: Option<u64>,
}
const NOTIFICATION_METHOD: &str = "at_mentioned";
#[derive(Debug, Clone, Serialize, Deserialize)]
struct AtMentionedNotification {
method: String,
params: AtMentionedParams,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
struct AtMentionedParams {
#[serde(rename = "filePath")]
file_path: String,
#[serde(rename = "lineStart")]
line_start: Option<u64>,
#[serde(rename = "lineEnd")]
line_end: Option<u64>,
}
pub trait McpServerConnection: Send + Sync {
fn name(&self) -> &str;
fn is_connected(&self) -> bool;
fn is_pending(&self) -> bool;
}
pub trait ConnectedMcpServer: McpServerConnection {
fn set_at_mentioned_handler(
&self,
handler: Box<dyn Fn(IdeAtMentioned) + Send + Sync>,
);
}
fn get_connected_ide_client(
clients: &[Box<dyn McpServerConnection>],
) -> Option<Box<dyn ConnectedMcpServer>> {
clients
.iter()
.find(|c| c.name() == "ide" && c.is_connected())
.map(|c| {
None
})
.flatten()
}
pub fn ide_at_mentioned_init(
mcp_clients: &[Box<dyn McpServerConnection>],
on_at_mentioned: impl Fn(IdeAtMentioned) + Send + Sync + 'static,
) {
let ide_client = mcp_clients
.iter()
.find(|c| c.name() == "ide" && c.is_connected());
if let Some(client) = ide_client {
let on_at_mentioned = std::sync::Arc::new(on_at_mentioned);
let _ = (client, on_at_mentioned);
}
}
pub fn parse_at_mentioned_notification(
json: &str,
) -> Result<IdeAtMentioned, Box<dyn std::error::Error>> {
let notification: AtMentionedNotification = serde_json::from_str(json)?;
if notification.method != NOTIFICATION_METHOD {
return Err(format!("Unexpected notification method: {}", notification.method).into());
}
let line_start = notification.params.line_start.map(|l| l + 1);
let line_end = notification.params.line_end.map(|l| l + 1);
Ok(IdeAtMentioned {
file_path: notification.params.file_path,
line_start,
line_end,
})
}