1use anyhow::{Result, bail};
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct FeatureSupport {
7 pub supported: bool,
8 pub native: bool,
9}
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct SessionLogSupport {
14 pub supported: bool,
15 pub native: bool,
16 #[serde(skip_serializing_if = "Option::is_none")]
18 pub completeness: Option<String>,
19}
20
21#[derive(Debug, Clone, Serialize, Deserialize)]
23pub struct SizeMappings {
24 pub small: String,
25 pub medium: String,
26 pub large: String,
27}
28
29#[derive(Debug, Clone, Serialize, Deserialize)]
31pub struct Features {
32 pub interactive: FeatureSupport,
33 pub non_interactive: FeatureSupport,
34 pub resume: FeatureSupport,
35 pub resume_with_prompt: FeatureSupport,
36 pub session_logs: SessionLogSupport,
37 pub json_output: FeatureSupport,
38 pub stream_json: FeatureSupport,
39 pub json_schema: FeatureSupport,
40 pub input_format: FeatureSupport,
41 pub streaming_input: FeatureSupport,
42 pub worktree: FeatureSupport,
43 pub sandbox: FeatureSupport,
44 pub system_prompt: FeatureSupport,
45 pub auto_approve: FeatureSupport,
46 pub review: FeatureSupport,
47 pub add_dirs: FeatureSupport,
48 pub max_turns: FeatureSupport,
49}
50
51#[derive(Debug, Clone, Serialize, Deserialize)]
53pub struct ProviderCapability {
54 pub provider: String,
55 pub default_model: String,
56 pub available_models: Vec<String>,
57 pub size_mappings: SizeMappings,
58 pub features: Features,
59}
60
61impl FeatureSupport {
62 pub fn native() -> Self {
63 Self {
64 supported: true,
65 native: true,
66 }
67 }
68
69 pub fn wrapper() -> Self {
70 Self {
71 supported: true,
72 native: false,
73 }
74 }
75
76 pub fn unsupported() -> Self {
77 Self {
78 supported: false,
79 native: false,
80 }
81 }
82}
83
84impl SessionLogSupport {
85 pub fn full() -> Self {
86 Self {
87 supported: true,
88 native: true,
89 completeness: Some("full".to_string()),
90 }
91 }
92
93 pub fn partial() -> Self {
94 Self {
95 supported: true,
96 native: true,
97 completeness: Some("partial".to_string()),
98 }
99 }
100
101 pub fn unsupported() -> Self {
102 Self {
103 supported: false,
104 native: false,
105 completeness: None,
106 }
107 }
108}
109
110pub fn format_capability(cap: &ProviderCapability, format: &str, pretty: bool) -> Result<String> {
112 match format {
113 "json" => {
114 if pretty {
115 Ok(serde_json::to_string_pretty(cap)?)
116 } else {
117 Ok(serde_json::to_string(cap)?)
118 }
119 }
120 "yaml" => Ok(serde_yaml::to_string(cap)?),
121 "toml" => Ok(toml::to_string_pretty(cap)?),
122 _ => bail!(
123 "Unsupported format '{}'. Available: json, yaml, toml",
124 format
125 ),
126 }
127}
128
129pub fn models_to_vec(models: &[&str]) -> Vec<String> {
131 models.iter().map(|s| s.to_string()).collect()
132}
133
134#[cfg(test)]
135#[path = "capability_tests.rs"]
136mod tests;