vtcode_desktop_protocol/config.rs
1//! Configuration snapshots, settings catalog, and model picker DTOs.
2
3use serde::{Deserialize, Serialize};
4use serde_json::Value;
5
6use super::secret::SecretStoreInfo;
7use super::session::SessionOptionsSnapshot;
8
9/// Basic workspace and provider configuration exposed to the GUI.
10#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
11#[serde(rename_all = "camelCase")]
12pub struct ConfigurationSnapshot {
13 /// Active provider identifier.
14 pub provider: String,
15 /// Active model identifier.
16 pub model: String,
17 /// Whether provider authentication requirements passed startup preflight.
18 pub authenticated: bool,
19 /// Existing CLI command users can run to configure credentials.
20 pub credential_setup_command: String,
21 /// Human label for the execution policy the service runs under.
22 #[serde(default, skip_serializing_if = "Option::is_none")]
23 pub sandbox: Option<String>,
24 /// Context window of the active model, when the catalog knows it.
25 #[serde(default, skip_serializing_if = "Option::is_none")]
26 pub context_window: Option<u64>,
27 /// Non-secret CLI UI preferences available to the native client.
28 #[serde(default, skip_serializing_if = "Option::is_none")]
29 pub shared_ui: Option<SharedUiPreferences>,
30 /// In-app secret-form support for the active provider, absent for
31 /// login-flow/local providers and older services.
32 #[serde(default, skip_serializing_if = "Option::is_none")]
33 pub secret_store: Option<SecretStoreInfo>,
34 /// Effective options for the next runtime session, absent on older helpers.
35 #[serde(default, skip_serializing_if = "Option::is_none")]
36 pub session_options: Option<SessionOptionsSnapshot>,
37}
38
39/// Writable configuration layer understood by the CLI config service.
40#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
41#[serde(rename_all = "snake_case")]
42pub enum ConfigTarget {
43 /// User-level configuration.
44 User,
45 /// Workspace-level configuration.
46 Workspace,
47 /// Project profile configuration.
48 Project,
49}
50
51/// Non-secret setting value exposed to the native configuration browser.
52#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
53#[serde(rename_all = "camelCase")]
54pub struct ConfigSetting {
55 /// Stable dotted path accepted by the CLI config writer.
56 pub path: String,
57 /// Effective CLI value after defaults; null represents an unset documented optional field.
58 pub value: Value,
59 /// Safe layer label such as `workspace` or `user`; never a filesystem path.
60 pub origin: Option<String>,
61 /// CLI `/config` display label, when documented.
62 #[serde(default, skip_serializing_if = "Option::is_none")]
63 pub label: Option<String>,
64 /// CLI schema type used when a setting has no explicit effective value.
65 #[serde(default, skip_serializing_if = "Option::is_none")]
66 pub type_name: Option<String>,
67 /// Documented default value, rendered as plain text.
68 #[serde(default, skip_serializing_if = "Option::is_none")]
69 pub default_value: Option<String>,
70 /// Description from the shared CLI configuration reference.
71 #[serde(default, skip_serializing_if = "Option::is_none")]
72 pub description: Option<String>,
73 /// Documented choices, if the CLI exposes a finite set.
74 #[serde(default)]
75 pub options: Vec<String>,
76 /// Curated CLI `/config` group or `Advanced settings`.
77 #[serde(default, skip_serializing_if = "Option::is_none")]
78 pub group: Option<String>,
79 /// Purpose of the curated group.
80 #[serde(default, skip_serializing_if = "Option::is_none")]
81 pub group_description: Option<String>,
82 /// Whether the current CLI catalog considers this a writable setting.
83 #[serde(default = "config_setting_editable_default")]
84 pub editable: bool,
85}
86
87const fn config_setting_editable_default() -> bool {
88 true
89}
90
91/// Version of one writable config layer, for optimistic write protection.
92#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
93#[serde(rename_all = "camelCase")]
94pub struct ConfigTargetVersion {
95 /// Layer represented by this version.
96 pub target: ConfigTarget,
97 /// Layer fingerprint, when the selected layer was loaded.
98 pub version: Option<String>,
99}
100
101/// Bounded, credential-filtered catalog of the CLI's effective and documented settings.
102#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
103#[serde(rename_all = "camelCase")]
104pub struct ConfigSettingsSnapshot {
105 /// Effective settings and documented schema entries from the shared CLI `/config` catalog.
106 pub settings: Vec<ConfigSetting>,
107 /// Fingerprints for user, workspace, and project layers.
108 pub target_versions: Vec<ConfigTargetVersion>,
109 /// Number of credential-bearing branches excluded from the catalog.
110 pub omitted_sensitive: usize,
111 /// Number of values omitted because they exceeded the UI size bound.
112 pub omitted_large: usize,
113 /// Number of additional settings omitted because the catalog reached its limit.
114 pub omitted_limit: usize,
115}
116
117/// Write one setting through the shared, validated CLI configuration service.
118#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
119#[serde(rename_all = "camelCase", deny_unknown_fields)]
120pub struct ConfigSettingsWriteParams {
121 /// Layer to update.
122 pub target: ConfigTarget,
123 /// Dotted setting path from `ConfigSettingsSnapshot`.
124 pub path: String,
125 /// Replacement value. Its type must match the effective setting or documented schema type.
126 pub value: Value,
127 /// Version observed when the setting editor opened.
128 pub expected_layer_version: Option<String>,
129}
130
131/// Result of persisting a CLI configuration value.
132#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
133#[serde(rename_all = "camelCase")]
134pub struct ConfigSettingsWriteResult {
135 /// Layer updated by the CLI config service.
136 pub target: ConfigTarget,
137 /// Setting path that was persisted.
138 pub path: String,
139 /// Version of the updated layer.
140 pub written_layer_version: String,
141 /// Whether a higher-precedence layer still controls the effective value.
142 pub overridden: bool,
143}
144
145/// Open one layered config file in the platform default editor.
146#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
147#[serde(rename_all = "camelCase", deny_unknown_fields)]
148pub struct ConfigOpenFileParams {
149 /// Layer whose file should be opened.
150 pub target: ConfigTarget,
151}
152
153fn default_communication_style() -> String {
154 "balanced".to_string()
155}
156
157/// CLI preferences projected through existing parsers rather than a second config loader.
158#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
159#[serde(rename_all = "camelCase")]
160pub struct SharedUiPreferences {
161 /// Theme ID resolved by the CLI startup loader.
162 pub theme: String,
163 /// Effective `ui.communication_style` (`balanced`/`quiet`/`verbose`).
164 /// Absent on older services; the desktop falls back to `balanced`.
165 #[serde(default = "default_communication_style")]
166 pub communication_style: String,
167 /// Desktop command ID to normalized native key combinations; an empty list unbinds it.
168 #[serde(default)]
169 pub shortcuts: std::collections::BTreeMap<String, Vec<String>>,
170 /// Explicit diagnostics for skipped bindings; contains no configuration secrets.
171 #[serde(default)]
172 pub shortcut_warnings: Vec<String>,
173}
174
175/// One selectable model from the service's catalog.
176#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
177#[serde(rename_all = "camelCase")]
178pub struct ModelInfo {
179 /// Provider identifier the model runs on.
180 pub provider: String,
181 /// Canonical model identifier.
182 pub id: String,
183 /// Human-friendly display name.
184 pub display_name: String,
185 /// Context window in tokens, when the catalog knows it.
186 #[serde(default, skip_serializing_if = "Option::is_none")]
187 pub context_window: Option<u64>,
188 /// Whether this is the currently active provider/model.
189 #[serde(default)]
190 pub current: bool,
191 /// Position in the CLI's recommended model set, if the model is recommended.
192 #[serde(default, skip_serializing_if = "Option::is_none")]
193 pub recommended_rank: Option<u8>,
194 /// Capability details sourced from the CLI's model catalog.
195 #[serde(default, skip_serializing_if = "Option::is_none")]
196 pub capabilities: Option<ModelCapabilities>,
197}
198
199/// Non-secret model capabilities used to explain model choices in the desktop picker.
200#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
201#[serde(rename_all = "camelCase")]
202pub struct ModelCapabilities {
203 /// Supports reasoning controls.
204 #[serde(default)]
205 pub reasoning: bool,
206 /// Accepts image input.
207 #[serde(default)]
208 pub vision: bool,
209 /// Supports tool calls.
210 #[serde(default)]
211 pub tool_call: bool,
212 /// Supports structured output.
213 #[serde(default)]
214 pub structured_output: bool,
215 /// Identifies a pro-tier model.
216 #[serde(default)]
217 pub is_pro: bool,
218 /// Input modalities advertised by the CLI catalog.
219 #[serde(default)]
220 pub input_modalities: Vec<String>,
221}
222
223/// Parameters for selecting a provider and model. The service restarts the
224/// selected session's runtime under the same session id; the thread keeps its
225/// history and the new route applies to subsequent turns.
226#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
227#[serde(rename_all = "camelCase")]
228pub struct ModelSelectParams {
229 /// Provider identifier.
230 pub provider: String,
231 /// Canonical model identifier.
232 pub model: String,
233}