//! fetch_url AI 工具声明式注册(URL → markdown 文档嗅探,只读 GET)。
//!
//! 工具职责:GET 网页 URL → HTML 转 markdown(htmd)→ 去噪音 + 截断 → 返回 {url,title,markdown,...}。
//! 让 LLM 高效理解网页文档,替代 http_request 拿原始 HTML(噪声大、爆 token)。
//!
//! 风险:Low(只读 GET,无副作用)。SSRF 防护与 http_request 共享同一套(validate_url +
//! resolve_and_check_host + 重定向每跳校验,见 commands/ai/http.rs)。
//!
//! handler body 在 commands/ai/fetch_url.rs::execute_fetch_url,声明式注册收敛样板。

use std::sync::Arc;

use df_ai::ai_tools::{AiToolRegistry, RiskLevel};
use df_ai::declare_tool;

/// 注册 fetch_url 工具到 `$registry`(无 db 捕获,纯网络 GET + htmd 转换)。
///
/// - name/desc/schema 面向 LLM 的工具说明
/// - risk=Low(只读 GET)
/// - handler 转调 fetch_url.rs::execute_fetch_url(SSRF 防护 + htmd + 截断全在那)
pub fn register(registry: &mut AiToolRegistry) {
    // 无捕获:占位 Arc<()>(handler 不持 db,仅转调 fetch_url.rs)。
    let dummy: Arc<()> = Arc::new(());
    // schema:url(必填)+ max_length(可选,默认 8000)+ render(可选,默认 false)。
    // headers 用手工 serde_json::Map 表达(additionalProperties 需对象 schema,object_schema 不支持)。
    let schema = {
        let mut props = serde_json::Map::new();
        props.insert("url".into(), serde_json::json!({ "type": "string", "description": "要获取的网页 URL,仅 http/https(拒私网/localhost,SSRF 防护)" }));
        props.insert("max_length".into(), serde_json::json!({ "type": "integer", "description": "返回 markdown 的截断长度(chars,默认 8000,clamp [500,50000])", "minimum": 500, "maximum": 50000, "default": 8000 }));
        props.insert("render".into(), serde_json::json!({ "type": "boolean", "description": "是否用 obscura(JS 渲染)抓取,默认 false(静态 reqwest+htmd)。render=true 适合 SPA/JS 动态渲染/反爬文档:检测本地 obscura(Rust 无头浏览器,自带 V8),已装则 spawn 渲染,未装/失败/超时自动回退静态并附 hint。需装 obscura:github.com/h4ckf0r0day/obscura", "default": false }));
        props.insert("headers".into(), serde_json::json!({ "type": "object", "description": "可选请求头 map<string,string>(如自定义 User-Agent)。默认带主流浏览器 UA 以拿完整渲染 HTML(仅静态模式生效,render=true 时由 obscura 自管 UA)", "additionalProperties": { "type": "string" } }));
        props.insert("timeout_secs".into(), serde_json::json!({ "type": "integer", "description": "超时秒数(默认 30,上限 60,仅静态模式生效;render=true 用固定 45s obscura 超时)", "minimum": 1, "maximum": 60 }));
        serde_json::json!({
            "type": "object",
            "properties": props,
            "required": ["url"],
        })
    };
    declare_tool!(
        registry,
        dummy: Arc<()>,
        "fetch_url",
        "获取网页 URL 内容并转为 markdown(HTML 清洗 + 截断),用于高效理解网页文档(API 文档/博客/技术资料)。只读 GET,自动剥离 script/style/nav 等噪声,提取 title,按 max_length 截断。返回 {url, title, markdown, length, truncated, render_mode, ?hint}。安全:仅 http/https,拒绝私网/保留 IP(SSRF 防护含 DNS resolve 后校验),重定向≤3 跳。render=true 用 obscura 渲染 JS(SPA/反爬,需装 obscura,未装自动回退静态)。如需 POST/鉴权/原始响应用 http_request",
        RiskLevel::Low,
        schema: schema,
        args => {
            // 转调 fetch_url.rs handler(SSRF 防护 + htmd 转换 + 去噪音 + 截断全在那)
            crate::commands::ai::fetch_url::execute_fetch_url(args).await
        }
    );
}
