1use rmcp::ErrorData;
4use serde_json::{Map, Value, json};
5
6fn obj(m: Map<String, Value>) -> Value {
7 Value::Object(m)
8}
9use void_crawl_core::VoidCrawlError;
10
11pub fn map_err(err: VoidCrawlError) -> ErrorData {
17 match err {
18 VoidCrawlError::ElementNotFound(s)
19 | VoidCrawlError::NavigationFailed(s)
20 | VoidCrawlError::JsEvalError(s) => ErrorData::invalid_params(s, None),
21 VoidCrawlError::Timeout(s) => ErrorData::internal_error(format!("timeout: {s}"), None),
22 VoidCrawlError::BrowserClosed => ErrorData::internal_error("browser closed", None),
23 VoidCrawlError::CaptchaDetected { ref kind } => {
24 let data = tagged("CaptchaDetected", json!({ "kind": kind }));
25 ErrorData::internal_error(err.to_string(), Some(obj(data)))
26 }
27 VoidCrawlError::ProfileBusy { ref name } => {
28 let data = tagged("ProfileBusy", json!({ "name": name }));
29 ErrorData::internal_error(err.to_string(), Some(obj(data)))
30 }
31 VoidCrawlError::ProfileLeaseExpired { ref name, timeout_secs } => {
32 let data = tagged(
33 "ProfileLeaseExpired",
34 json!({ "name": name, "timeout_secs": timeout_secs }),
35 );
36 ErrorData::internal_error(err.to_string(), Some(obj(data)))
37 }
38 VoidCrawlError::ProfileNotFound { ref name, ref searched } => {
39 let data = tagged("ProfileNotFound", json!({ "name": name, "searched": searched }));
40 ErrorData::invalid_params(err.to_string(), Some(obj(data)))
41 }
42 other => ErrorData::internal_error(other.to_string(), None),
43 }
44}
45
46fn tagged(exception: &str, extra: Value) -> Map<String, Value> {
47 let mut m = Map::new();
48 m.insert("exception".into(), Value::String(exception.into()));
49 if let Value::Object(obj) = extra {
50 for (k, v) in obj {
51 m.insert(k, v);
52 }
53 }
54 m
55}