BareGit
#pragma once

#include <cstddef>
#include <chrono>
#include <string>
#include <string_view>

#include <mw/error.hpp>
#include <nlohmann/json.hpp>

namespace agent_smith
{

/// MCP transport, protocol, or remote JSON-RPC failure.
struct McpError
{
    /// Human-readable transport, protocol, or remote failure.
    std::string msg;
    /// Configured server alias, when a connection is available.
    std::string server = {};
    /// Remote JSON-RPC error code, absent for local errors.
    std::optional<int> rpc_code = std::nullopt;
    /// Original remote error details.
    nlohmann::json data = nullptr;
    /// Whether reconnecting can repair the underlying connection.
    bool transport = false;
};

/// The common result type for Agent Smith operations that can fail.
template <typename T> using Result = mw::E<T>;

/// Describes malformed data received from an external protocol payload.
struct ParseError
{
    std::string msg;
    std::size_t offset = 0;
};

/// Describes a non-success response returned by an LLM HTTP endpoint.
struct LlmApiError
{
    std::string msg;
    int http_status = 0;
    std::string body_excerpt;
};

/// An operation exceeded its execution-time budget.
struct TimeoutError
{
    /// Human-readable failure description.
    std::string msg;
    /// Name of the operation that timed out.
    std::string operation;
    /// Maximum duration allowed for the operation.
    std::chrono::milliseconds budget;
};

/// Execution stopped because of cancellation or an agent limit.
struct CancelledError
{
    /// Human-readable stop reason.
    std::string msg;
    /// Operation that was stopped.
    std::string operation;
};

namespace error
{

/// Create a typed stop-condition error for an agent send.
inline mw::Error cancel(std::string_view reason)
{
    return CancelledError{std::string(reason), "agent send"};
}

/// Create a typed parse error with an optional byte offset.
inline mw::Error parse(std::string_view message, std::size_t offset = 0)
{
    return ParseError{
        .msg = std::string(message),
        .offset = offset,
    };
}

/// Create a typed error for a non-success response from an LLM endpoint.
inline mw::Error llmApi(int http_status, std::string_view body_excerpt)
{
    return LlmApiError{
        .msg = "LLM endpoint returned HTTP " + std::to_string(http_status),
        .http_status = http_status,
        .body_excerpt = std::string(body_excerpt),
    };
}

} // namespace error

} // namespace agent_smith