codetether-agent 4.5.7

A2A-native AI coding agent for the CodeTether ecosystem
Documentation
use super::BrowserError;
use chromiumoxide::cdp::js_protocol::runtime::{ExceptionDetails, StackTrace};
use chromiumoxide::error::CdpError;

impl From<CdpError> for BrowserError {
    fn from(error: CdpError) -> Self {
        match error {
            CdpError::FrameNotFound(_) | CdpError::NotFound => Self::ElementNotFound("page".into()),
            CdpError::JavascriptException(details) => exception(*details),
            CdpError::NoResponse | CdpError::Ws(_) | CdpError::ChannelSendError(_) => {
                Self::BrowserCrashed
            }
            CdpError::Timeout => Self::NavigationTimeout,
            other => Self::OperationFailed(other.to_string()),
        }
    }
}

fn exception(details: ExceptionDetails) -> BrowserError {
    let message = details
        .exception
        .as_ref()
        .and_then(|value| value.description.as_deref().map(summary))
        .unwrap_or_else(|| details.text.clone());
    if details.text.contains("in promise") {
        return BrowserError::EvalRejection { message };
    }
    BrowserError::JsException {
        message,
        stack: details.stack_trace.map(stack),
    }
}

fn stack(trace: StackTrace) -> String {
    trace
        .call_frames
        .into_iter()
        .map(|frame| {
            format!(
                "at {} ({}:{}:{})",
                frame.function_name,
                frame.url,
                frame.line_number + 1,
                frame.column_number + 1
            )
        })
        .collect::<Vec<_>>()
        .join("\n")
}

fn summary(value: &str) -> String {
    value.lines().next().unwrap_or(value).to_string()
}