Skip to main content

objectiveai_cli/filesystem/install/
error.rs

1use reqwest::StatusCode;
2use std::path::PathBuf;
3
4/// Failures the GitHub-install pipeline (shared by tools and plugins)
5/// can encounter. Shape modelled after `objectiveai-api`'s
6/// `github::Error`: split request / response / status / parse so
7/// diagnostics name what failed, plus IO variants for the local-disk
8/// side of the flow.
9#[derive(thiserror::Error, Debug)]
10pub enum InstallError {
11    #[error("manifest request failed: {0}")]
12    ManifestRequest(reqwest::Error),
13    #[error("manifest fetch returned bad status {code} from {url}: {body}")]
14    ManifestBadStatus {
15        code: StatusCode,
16        url: String,
17        body: String,
18    },
19    #[error("manifest body could not be read: {0}")]
20    ManifestResponse(reqwest::Error),
21    #[error("manifest parse failed: {0}")]
22    ManifestParse(serde_path_to_error::Error<serde_json::Error>),
23    #[error("cli-zip request failed: {0}")]
24    CliZipRequest(reqwest::Error),
25    #[error("cli-zip fetch returned bad status {code} from {url}")]
26    CliZipBadStatus { code: StatusCode, url: String },
27    #[error("cli-zip body could not be read: {0}")]
28    CliZipResponse(reqwest::Error),
29    #[error("failed to create install directory {0}: {1}")]
30    PluginDirCreate(PathBuf, std::io::Error),
31    #[error("failed to serialize manifest for persistence: {0}")]
32    ManifestSerialize(serde_json::Error),
33    #[error("failed to persist manifest at {0}: {1}")]
34    ManifestPersist(PathBuf, std::io::Error),
35    #[error("viewer-zip request failed: {0}")]
36    ViewerZipRequest(reqwest::Error),
37    #[error("viewer-zip fetch returned bad status {code} from {url}")]
38    ViewerZipBadStatus { code: StatusCode, url: String },
39    #[error("viewer-zip body could not be read: {0}")]
40    ViewerZipResponse(reqwest::Error),
41    #[error("failed to extract zip into {0}: {1}")]
42    ZipExtract(PathBuf, String),
43    #[error("invalid header name {name:?}: {reason}")]
44    InvalidHeaderName { name: String, reason: String },
45    #[error("invalid header value for {name:?}: {reason}")]
46    InvalidHeaderValue { name: String, reason: String },
47    #[error(
48        "{repository} is already installed; pass `--upgrade` to replace it"
49    )]
50    AlreadyInstalled { repository: String },
51    #[error(
52        "repository name {repository:?} is reserved and cannot be used as a plugin name"
53    )]
54    ReservedRepositoryName { repository: String },
55    #[error("manifest failed validation: {0}")]
56    ManifestInvalid(&'static str),
57    /// `owner`, `repository`, or `commit` does not match the
58    /// `^[A-Za-z0-9_.-]{1,128}$` shape required for them to land in a
59    /// usable LLM tool name (Anthropic enforces `^[a-zA-Z0-9_-]{1,128}$`;
60    /// we additionally allow `.` so semver-shaped version strings can
61    /// flow through, with `.` -> `-` substitution applied when the tool
62    /// name is materialized).
63    #[error("invalid {kind}: {value:?} must match ^[A-Za-z0-9_.-]{{1,128}}$")]
64    InvalidIdentifier { kind: &'static str, value: String },
65}