use std::{io, path::PathBuf};
use thiserror::Error;
use tree_sitter::{LanguageError, WasmError};
use crate::{embed::candle::EmbeddingError, store::lance::StoreError, usock::SocketError};
#[derive(Debug, Error)]
pub enum Error {
#[error("io error: {0}")]
Io(#[from] io::Error),
#[error("store error: {0}")]
Store(#[from] StoreError),
#[error("embedding error: {0}")]
Embedding(#[from] EmbeddingError),
#[error("chunker error: {0}")]
Chunker(#[from] ChunkerError),
#[error("git error: {0}")]
Git(#[from] git2::Error),
#[error("config error: {0}")]
Config(#[from] ConfigError),
#[error("http error: {0}")]
Http(#[from] HttpError),
#[error("json error: {0}")]
Json(#[from] serde_json::Error),
#[error("postcard error: {0}")]
Postcard(#[from] postcard::Error),
#[error("lancedb error: {0}")]
LanceDb(#[from] lancedb::error::Error),
#[error("ipc error: {0}")]
Ipc(#[from] IpcError),
#[error("socket error: {0}")]
Socket(#[from] SocketError),
#[error("server error during {op}: {reason}")]
Server { op: &'static str, reason: String },
#[error("unexpected response from server during {0}")]
UnexpectedResponse(&'static str),
#[error("failed to find smgrep root directory: {0}")]
FindRoot(#[source] io::Error),
#[error("failed to spawn daemon: {0}")]
DaemonSpawn(#[source] io::Error),
#[error("failed to run claude command: {0}")]
ClaudeSpawn(#[source] io::Error),
#[error("claude command exited with code {0}")]
ClaudeCommand(i32),
#[error("file system error: {op} '{path}': {reason}")]
FileSystem { op: &'static str, path: PathBuf, reason: String },
#[error("mcp unknown method: {0}")]
McpUnknownMethod(String),
#[error("mcp unknown tool: {0}")]
McpUnknownTool(String),
#[error("hf_hub error: {0}")]
HfHub(#[from] hf_hub::api::tokio::ApiError),
#[error("arrow error: {0}")]
Arrow(#[from] arrow_schema::ArrowError),
#[error("failed to read index: {0}")]
ReadIndex(#[source] git2::Error),
#[error("failed to get working directory: {path}", path = _0.display())]
NoWorkingDirectory(PathBuf),
#[error("failed to open repository: {0}")]
OpenRepository(#[source] git2::Error),
}
#[derive(Debug, Error)]
pub enum IpcError {
#[error("message too large: {0} bytes")]
MessageTooLarge(usize),
#[error("failed to serialize: {0}")]
Serialize(#[source] postcard::Error),
#[error("failed to deserialize: {0}")]
Deserialize(#[source] postcard::Error),
#[error("failed to read: {0}")]
Read(#[source] io::Error),
#[error("failed to write: {0}")]
Write(#[source] io::Error),
}
#[derive(Debug, Error)]
pub enum ChunkerError {
#[error("failed to create WASM store: {0}")]
CreateWasmStore(#[source] WasmError),
#[error("set language error: {0}")]
SetLanguage(#[source] LanguageError),
#[error("set WASM store error: {0}")]
SetWasmStore(#[source] LanguageError),
#[error("failed to load language {lang}: {reason}")]
LoadLanguage {
lang: String,
#[source]
reason: WasmError,
},
#[error("failed to parse file")]
ParseFailed,
}
#[derive(Debug, Error)]
pub enum ConfigError {
#[error("failed to get user directories")]
GetUserDirectories,
#[error("failed to create grammars directory: {0}")]
CreateGrammarsDir(#[source] io::Error),
#[error("unknown language: {0}")]
UnknownLanguage(String),
#[error("failed to download {lang}: {reason}")]
DownloadFailed {
lang: String,
#[source]
reason: reqwest::Error,
},
#[error("failed to download {lang}: HTTP {status}")]
DownloadHttpStatus { lang: String, status: u16 },
#[error("failed to read response: {0}")]
ReadResponse(#[source] reqwest::Error),
#[error("failed to write WASM file: {0}")]
WriteWasmFile(#[source] io::Error),
#[error("failed to rename WASM file: {0}")]
RenameWasmFile(#[source] io::Error),
#[error("failed to create runtime: {0}")]
CreateRuntime(#[source] io::Error),
}
#[derive(Debug, Error)]
pub enum HttpError {
#[error("request failed: {0}")]
Request(#[from] reqwest::Error),
#[error("invalid status code: {0}")]
StatusCode(u16),
}
impl From<notify::Error> for Error {
fn from(e: notify::Error) -> Self {
Self::Io(io::Error::other(e))
}
}
pub type Result<T, E = Error> = std::result::Result<T, E>;