use crank_adapter_rest::RestAdapterError; use crank_community_mcp::tool_error::tool_error_contract_from_runtime; use crank_runtime::RuntimeError; use serde_json::json; #[test] fn maps_upstream_429_to_recoverable_structured_tool_error() { let contract = tool_error_contract_from_runtime( &RuntimeError::RestAdapter(RestAdapterError::UnexpectedStatus { status: 429, body: json!({ "error": "rate limit exceeded", "internal_trace": "do not leak" }), }), "req-429", ); assert_eq!(contract.error_code, "upstream_rate_limited"); assert!(contract.recoverable); assert_eq!(contract.upstream_status, Some(429)); assert_eq!(contract.request_id, "req-429"); assert_eq!(contract.suggested_action, Some("Повторите запрос позже.")); assert!(!contract.message.contains("internal_trace")); } #[test] fn maps_mapping_error_to_non_recoverable_structured_tool_error() { let contract = tool_error_contract_from_runtime( &RuntimeError::InvalidPreparedRequest { field: "query.base".to_owned(), reason: "expected string".to_owned(), }, "req-map", ); assert_eq!(contract.error_code, "runtime_error"); assert!(!contract.recoverable); assert_eq!(contract.upstream_status, None); assert_eq!(contract.request_id, "req-map"); assert_eq!( contract.suggested_action, Some("Проверьте параметры вызова инструмента.") ); }