use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use agent_client_protocol::schema::{SessionId, ToolCallStatus, ToolKind};
use agent_client_protocol::{Client, ConnectionTo};
use crate::engine::WikiEngine;
use crate::ops;
use super::helpers::{
clear_active_run, get_cancelled, send_text, send_tool_call, send_tool_result,
};
use super::{Sessions, StepResult, make_tool_id};
pub fn step_lint(
cx: &ConnectionTo<Client>,
manager: &WikiEngine,
session_id: &SessionId,
wiki_name: &str,
rules: Option<&str>,
cancelled: Option<Arc<AtomicBool>>,
) -> StepResult {
let tool_id = make_tool_id("lint", "lint");
let label = rules
.filter(|r| !r.is_empty())
.map(|r| format!("wiki_lint rules={r}"))
.unwrap_or_else(|| "wiki_lint".to_string());
send_tool_call(cx, session_id, &tool_id, &label, ToolKind::Other)?;
let result = {
let engine = manager
.state
.read()
.map_err(|_| agent_client_protocol::schema::Error::internal_error())?;
ops::run_lint(&engine, wiki_name, rules, None)
};
match result {
Ok(report) => {
let summary = format!(
"{} findings ({} errors, {} warnings)",
report.total, report.errors, report.warnings
);
send_tool_result(
cx,
session_id,
&tool_id,
ToolCallStatus::Completed,
&summary,
)?;
for f in &report.findings {
if cancelled
.as_ref()
.map(|c| c.load(Ordering::Relaxed))
.unwrap_or(false)
{
send_text(cx, session_id, "Cancelled.")?;
return Ok(());
}
send_text(
cx,
session_id,
&format!("[{}] {}: {}", f.severity, f.slug, f.message),
)?;
}
Ok(())
}
Err(e) => {
send_tool_result(
cx,
session_id,
&tool_id,
ToolCallStatus::Failed,
&format!("{e}"),
)?;
Ok(())
}
}
}
pub fn run_lint(
cx: &ConnectionTo<Client>,
manager: &WikiEngine,
sessions: &Sessions,
session_id: &SessionId,
query: &str,
wiki_name: &str,
) -> StepResult {
let cancelled = get_cancelled(sessions, &session_id.to_string());
let rules = (!query.is_empty()).then_some(query);
step_lint(cx, manager, session_id, wiki_name, rules, cancelled)?;
clear_active_run(sessions, &session_id.to_string());
Ok(())
}