返回 CodeWhale
errors.rs
根目录 / crates / config / src / route / errors.rs
1 //! Route resolution errors (#3384).
2 //!
3 //! `thiserror` is not a dependency of this crate, so [`std::fmt::Display`] and
4 //! [`std::error::Error`] are hand-implemented. No new dependency is added.
5
6 use std::fmt;
7
8 use super::ids::ProviderId;
9
10 /// Why a [`super::resolver::RouteResolver`] could not produce a candidate.
11 #[derive(Debug, Clone)]
12 pub enum RouteError {
13 /// The requested model selector was empty.
14 EmptyModel,
15 /// The named provider could not be resolved.
16 InvalidProvider(String),
17 /// A model matched multiple providers; the caller must disambiguate.
18 AmbiguousModel(Vec<ProviderId>),
19 /// A clearly-foreign model was requested for a strict direct provider.
20 ForeignModelForDirectProvider {
21 /// The strict direct provider that rejected the model.
22 provider: ProviderId,
23 /// The foreign model selector that was rejected.
24 model: String,
25 },
26 /// A model-aware provider did not prove a supported request protocol for
27 /// the selected model/endpoint.
28 UnsupportedModelProtocol {
29 /// Provider whose catalog row was incomplete or unsupported.
30 provider: ProviderId,
31 /// Selected provider-owned model id.
32 model: String,
33 /// Catalog endpoint key, when one was present.
34 endpoint_key: String,
35 },
36 }
37
38 impl fmt::Display for RouteError {
39 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40 match self {
41 Self::EmptyModel => write!(f, "model selector was empty"),
42 Self::InvalidProvider(name) => write!(f, "invalid provider: {name}"),
43 Self::AmbiguousModel(providers) => {
44 let names: Vec<&str> = providers.iter().map(ProviderId::as_str).collect();
45 write!(
46 f,
47 "model matches multiple providers ({}); specify a provider",
48 names.join(", ")
49 )
50 }
51 Self::ForeignModelForDirectProvider { provider, model } => write!(
52 f,
53 "model {model:?} is not served by direct provider {}",
54 provider.as_str()
55 ),
56 Self::UnsupportedModelProtocol {
57 provider,
58 model,
59 endpoint_key,
60 } => {
61 write!(
62 f,
63 "model {model:?} on provider {} has unsupported or unproven endpoint {endpoint_key:?}",
64 provider.as_str()
65 )?;
66 // #6705: say which case this is, so a catalog Codewhale has not
67 // caught up with does not read as a broken install. The
68 // refresh remedy belongs to callers whose resolver actually
69 // reads the refreshed catalog, so it is not stated here.
70 match endpoint_key.as_str() {
71 "unproven" => write!(
72 f,
73 ": no catalog Codewhale has loaded proves this model's wire protocol. \
74 Reach it through a `kind = \"openai-compatible\"` provider with an \
75 explicit `wire`"
76 ),
77 super::OPENCODE_ZEN_DEPRECATED_ENDPOINT_KEY => write!(
78 f,
79 ": the provider's catalog marks this model deprecated; choose a current model"
80 ),
81 _ => write!(
82 f,
83 ": the provider serves this model over a protocol Codewhale does not speak"
84 ),
85 }
86 }
87 }
88 }
89 }
90
91 impl std::error::Error for RouteError {}
92
92 lines RUST