use aion_mcp::tools::service::{ToolFailure, ToolOutcome};
use serde_json::{Value, json};
use crate::ServerState;
use crate::awl::{CheckRequest, check_source_in_workspace, workspace};
use super::caller::AssistantSessionCaller;
pub(crate) async fn assistant_document_check(
state: &ServerState,
caller: &AssistantSessionCaller,
) -> Result<ToolOutcome, ToolFailure> {
let latest = state
.assistant_sessions()
.latest_context(caller.session_id())
.await
.map_err(|error| {
ToolFailure::new(
format!(
"the shared document could not be read for this conversation: {error}. This \
does NOT mean nothing is open — the server could not read it."
),
json!({ "code": "context_unreadable" }),
)
})?;
let Some(document) = latest.and_then(|context| context.document) else {
return Err(ToolFailure::new(
"there is no document to check: the operator has not shared one from an editor. \
Call `assistant_context` to see what they have shared."
.to_owned(),
json!({ "code": "no_document" }),
));
};
let root = workspace::workspace_root(state).map_err(|error| {
ToolFailure::new(
format!("the workspace root could not be resolved, so the check cannot run: {error}"),
json!({ "code": "workspace_unresolved" }),
)
})?;
let checked = check_source_in_workspace(
&root,
&CheckRequest {
source: document.text,
path: Some(document.path.clone()),
},
)
.await
.map_err(|error| {
ToolFailure::new(
format!("the check could not run: {error}"),
json!({ "code": "check_failed" }),
)
})?;
let diagnostics: Vec<Value> = checked
.diagnostics
.iter()
.map(|diagnostic| {
json!({
"line": diagnostic.line,
"column": diagnostic.column,
"message": diagnostic.message,
})
})
.collect();
let summary = if checked.deploys_green {
format!("`{}` checks clean.", document.path)
} else {
format!(
"`{}` has {} diagnostic{} — fix them with `assistant_document_edit` and check again.",
document.path,
diagnostics.len(),
if diagnostics.len() == 1 { "" } else { "s" },
)
};
Ok(ToolOutcome {
structured: json!({
"ok": checked.deploys_green,
"diagnostics": diagnostics,
}),
summary,
})
}