72 lines
2.2 KiB
Rust
72 lines
2.2 KiB
Rust
use serde::Serialize;
|
|
|
|
#[derive(Debug, thiserror::Error)]
|
|
pub enum AcpError {
|
|
#[error("agent process failed to spawn: {0}")]
|
|
SpawnFailed(String),
|
|
#[error("connection not found: {0}")]
|
|
ConnectionNotFound(String),
|
|
#[error("ACP protocol error: {0}")]
|
|
Protocol(String),
|
|
#[error("agent process exited unexpectedly")]
|
|
ProcessExited,
|
|
#[error("binary download failed: {0}")]
|
|
DownloadFailed(String),
|
|
#[error("platform not supported: {0}")]
|
|
PlatformNotSupported(String),
|
|
}
|
|
|
|
impl AcpError {
|
|
pub fn protocol(raw: impl Into<String>) -> Self {
|
|
let raw = raw.into();
|
|
let sanitized = sanitize_protocol_message(&raw);
|
|
|
|
if is_executable_format_error(&sanitized) {
|
|
return Self::Protocol(
|
|
"Agent executable appears incompatible or corrupted. Please retry to re-download it."
|
|
.into(),
|
|
);
|
|
}
|
|
|
|
Self::Protocol(sanitized)
|
|
}
|
|
}
|
|
|
|
impl Serialize for AcpError {
|
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
where
|
|
S: serde::Serializer,
|
|
{
|
|
serializer.serialize_str(&self.to_string())
|
|
}
|
|
}
|
|
|
|
fn sanitize_protocol_message(raw: &str) -> String {
|
|
let without_spawned_at = regex::Regex::new(r#"\s*,?\s*"spawned_at"\s*:\s*"[^"]*"\s*,?"#)
|
|
.ok()
|
|
.map(|re| re.replace_all(raw, "").into_owned())
|
|
.unwrap_or_else(|| raw.to_string());
|
|
|
|
let without_dangling_comma = regex::Regex::new(r#",\s*([}\]])"#)
|
|
.ok()
|
|
.map(|re| re.replace_all(&without_spawned_at, "$1").into_owned())
|
|
.unwrap_or(without_spawned_at);
|
|
|
|
regex::Regex::new(r#"/(?:Users|home)/[^"\s]+"#)
|
|
.ok()
|
|
.map(|re| {
|
|
re.replace_all(&without_dangling_comma, "<local-path>")
|
|
.into_owned()
|
|
})
|
|
.unwrap_or(without_dangling_comma)
|
|
}
|
|
|
|
fn is_executable_format_error(message: &str) -> bool {
|
|
let lowered = message.to_lowercase();
|
|
lowered.contains("malformed mach-o file")
|
|
|| lowered.contains("exec format error")
|
|
|| lowered.contains("bad cpu type in executable")
|
|
|| lowered.contains("not a valid win32 application")
|
|
|| lowered.contains("is not a valid application for this os platform")
|
|
}
|